Index: .bzrignore
===================================================================
--- .bzrignore	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ .bzrignore	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -67,4 +67,6 @@
 ./uspace/app/usbinfo/usbinfo
 ./uspace/app/virtusbkbd/vuk
+./uspace/app/virtusbhub/vuh
+./uspace/app/virtusbhub/vhc_hub/*
 ./uspace/app/websrv/websrv
 ./uspace/dist/app/*
@@ -82,7 +84,9 @@
 ./uspace/drv/test1/test1
 ./uspace/drv/test2/test2
-./uspace/drv/uhci/uhci
+./uspace/drv/uhci-hcd/uhci-hcd
+./uspace/drv/uhci-rhd/uhci-rhd
 ./uspace/drv/usbhub/usbhub
-./uspace/drv/usbkbd/usbkbd
+./uspace/drv/usbhid/usbhid
+./uspace/drv/usbmid/usbmid
 ./uspace/drv/vhc/vhc
 ./uspace/srv/bd/ata_bd/ata_bd
@@ -109,5 +113,6 @@
 ./uspace/srv/hw/irc/apic/apic
 ./uspace/srv/hw/irc/i8259/i8259
-./uspace/srv/hw/netif/dp8390/dp8390
+./uspace/srv/hw/netif/ne2000/dp8390
+./uspace/srv/hw/netif/ne2000/ne2000
 ./uspace/srv/loader/loader
 ./uspace/srv/net/cfg/lo
Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ HelenOS.config	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -549,2 +549,5 @@
 ! [CONFIG_DEBUG=y] CONFIG_TEST_DRIVERS (n/y)
 
+% Start virtual USB host controller
+! CONFIG_RUN_VIRTUAL_USB_HC (n/y)
+
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ boot/Makefile.common	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -144,4 +144,5 @@
 	$(USPACE_PATH)/app/usbinfo/usbinfo \
 	$(USPACE_PATH)/app/virtusbkbd/vuk \
+	$(USPACE_PATH)/app/virtusbhub/vuh \
 	$(USPACE_PATH)/app/websrv/websrv
 
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ boot/arch/amd64/Makefile.inc	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -43,7 +43,9 @@
 	isa \
 	ns8250 \
-	uhci \
+	uhci-hcd \
+	uhci-rhd \
 	usbhub \
-	usbkbd \
+	usbhid \
+	usbmid \
 	vhc
 
Index: contrib/arch/kernel/kernel.adl
===================================================================
--- contrib/arch/kernel/kernel.adl	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ contrib/arch/kernel/kernel.adl	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -203,8 +203,8 @@
 		
 		/* Connect an IRQ handler to the current task */
-		sysarg_t sys_ipc_register_irq(inr_t inr, devno_t devno, sysarg_t method, irq_code_t *ucode);
+		sysarg_t sys_register_irq(inr_t inr, devno_t devno, sysarg_t method, irq_code_t *ucode);
 		
 		/* Disconnect an IRQ handler from the current task */
-		sysarg_t sys_ipc_unregister_irq(inr_t inr, devno_t devno);
+		sysarg_t sys_unregister_irq(inr_t inr, devno_t devno);
 	protocol:
 		(
@@ -213,6 +213,6 @@
 			?sys_device_assign_devno +
 			?sys_preempt_control +
-			?sys_ipc_register_irq +
-			?sys_ipc_unregister_irq
+			?sys_register_irq +
+			?sys_unregister_irq
 		)*
 };
Index: contrib/arch/uspace/lib/libc/protocol
===================================================================
--- contrib/arch/uspace/lib/libc/protocol	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ contrib/arch/uspace/lib/libc/protocol	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,6 +34,6 @@
 	!sys_ddi.sys_device_assign_devno +
 	!sys_ddi.sys_preempt_control +
-	!sys_ddi.sys_ipc_register_irq +
-	!sys_ddi.sys_ipc_unregister_irq +
+	!sys_ddi.sys_register_irq +
+	!sys_ddi.sys_unregister_irq +
 	!sys_sysinfo.sys_sysinfo_valid +
 	!sys_sysinfo.sys_sysinfo_value +
Index: kernel/arch/arm32/src/mach/gta02/gta02.c
===================================================================
--- kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -174,4 +174,5 @@
 		fb_parea.pbase = GTA02_FB_BASE;
 		fb_parea.frames = 150;
+		fb_parea.unpriv = false;
 		ddi_parea_register(&fb_parea);
 	}
Index: kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
===================================================================
--- kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -300,4 +300,5 @@
 		fb_parea.pbase = ICP_FB;
 		fb_parea.frames = 300;
+		fb_parea.unpriv = false;
 		ddi_parea_register(&fb_parea);
 	}
Index: kernel/arch/ia32/_link.ld.in
===================================================================
--- kernel/arch/ia32/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/arch/ia32/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -49,7 +49,19 @@
 	}
 	
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); }
+	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_info 0 : { *(.debug_info); }
+	.debug_line 0 : { *(.debug_line); }
+	.debug_loc 0 : { *(.debug_loc); }
+	.debug_pubnames 0 : { *(.debug_pubnames); }
+	.debug_pubtypes 0 : { *(.debug_pubtypes); }
+	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_str 0 : { *(.debug_str); }
+#endif
+	
 	/DISCARD/ : {
-		*(.note.GNU-stack);
-		*(.comment);
+		*(*);
 	}
 	
Index: kernel/arch/mips32/src/mm/tlb.c
===================================================================
--- kernel/arch/mips32/src/mm/tlb.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/arch/mips32/src/mm/tlb.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -557,6 +557,7 @@
 	entry_hi_t hi, hi_save;
 	tlb_index_t index;
-
-	ASSERT(asid != ASID_INVALID);
+	
+	if (asid == ASID_INVALID)
+		return;
 
 	hi_save.value = cp0_entry_hi_read();
Index: kernel/arch/sparc64/src/drivers/niagara.c
===================================================================
--- kernel/arch/sparc64/src/drivers/niagara.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/arch/sparc64/src/drivers/niagara.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -216,4 +216,5 @@
 	outbuf_parea.pbase = (uintptr_t) (KA2PA(&output_buffer));
 	outbuf_parea.frames = 1;
+	outbuf_parea.unpriv = false;
 	ddi_parea_register(&outbuf_parea);
 
@@ -221,4 +222,5 @@
 	inbuf_parea.pbase = (uintptr_t) (KA2PA(&input_buffer));
 	inbuf_parea.frames = 1;
+	inbuf_parea.unpriv = false;
 	ddi_parea_register(&inbuf_parea);
 
Index: kernel/generic/include/ddi/ddi.h
===================================================================
--- kernel/generic/include/ddi/ddi.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/ddi/ddi.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -43,8 +43,9 @@
 /** Structure representing contiguous physical memory area. */
 typedef struct {
-	uintptr_t pbase;    /**< Physical base of the area. */
-	pfn_t frames;       /**< Number of frames in the area. */
+	link_t link;      /**< Linked list link */
 	
-	link_t link;        /**< Linked list link */
+	uintptr_t pbase;  /**< Physical base of the area. */
+	pfn_t frames;     /**< Number of frames in the area. */
+	bool unpriv;      /**< Allow mapping by unprivileged tasks. */
 } parea_t;
 
@@ -60,5 +61,4 @@
 extern int ddi_iospace_enable_arch(task_t *, uintptr_t, size_t);
 
-
 #endif
 
Index: kernel/generic/include/debug.h
===================================================================
--- kernel/generic/include/debug.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/debug.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -55,5 +55,6 @@
 	do { \
 		if (!(expr)) \
-			panic_assert("%s", #expr); \
+			panic_assert("%s() at %s:%u:\n%s", \
+			    __func__, __FILE__, __LINE__, #expr); \
 	} while (0)
 
@@ -72,5 +73,6 @@
 	do { \
 		if (!(expr)) \
-			panic_assert("%s, %s", #expr, msg); \
+			panic_assert("%s() at %s:%u:\n%s, %s", \
+			    __func__, __FILE__, __LINE__, #expr, msg); \
 	} while (0)
 
Index: kernel/generic/include/ipc/event_types.h
===================================================================
--- kernel/generic/include/ipc/event_types.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/ipc/event_types.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,5 +41,5 @@
 	/** Returning from kernel console to userspace */
 	EVENT_KCONSOLE,
-	/** A thread has faulted and will be terminated */
+	/** A task/thread has faulted and will be terminated */
 	EVENT_FAULT,
 	EVENT_END
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/ipc/ipc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -165,5 +165,7 @@
  *                       error is sent back to caller. Otherwise 
  *                       the call is accepted and the response is sent back.
- *                     - the allocated phoneid is passed to userspace 
+ *                     - the hash of the client task is passed to userspace
+ *                       (on the receiving side) as ARG4 of the call.
+ *                     - the hash of the allocated phone is passed to userspace
  *                       (on the receiving side) as ARG5 of the call.
  *
@@ -319,4 +321,7 @@
 typedef struct {
 	sysarg_t args[IPC_CALL_LEN];
+	/** Task which made or forwarded the call with IPC_FF_ROUTE_FROM_ME. */
+	struct task *task;
+	/** Phone which made or last masqueraded this call. */
 	phone_t *phone;
 } ipc_data_t;
@@ -333,5 +338,4 @@
 	 * The caller box is different from sender->answerbox
 	 * for synchronous calls.
-	 *
 	 */
 	answerbox_t *callerbox;
@@ -350,5 +354,4 @@
 	 * cases, we must keep it aside so that the answer is processed
 	 * correctly.
-	 *
 	 */
 	phone_t *caller_phone;
Index: kernel/generic/include/ipc/sysipc.h
===================================================================
--- kernel/generic/include/ipc/sysipc.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/ipc/sysipc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -56,6 +56,6 @@
     unsigned int);
 extern sysarg_t sys_ipc_hangup(sysarg_t);
-extern sysarg_t sys_ipc_register_irq(inr_t, devno_t, sysarg_t, irq_code_t *);
-extern sysarg_t sys_ipc_unregister_irq(inr_t, devno_t);
+extern sysarg_t sys_register_irq(inr_t, devno_t, sysarg_t, irq_code_t *);
+extern sysarg_t sys_unregister_irq(inr_t, devno_t);
 
 #ifdef __32_BITS__
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/mm/as.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -115,17 +115,19 @@
 	
 	/**
-	 * Number of processors on wich is this address space active.
-	 * Protected by asidlock.
+	 * Number of processors on which this
+	 * address space is active. Protected by
+	 * asidlock.
 	 */
 	size_t cpu_refcount;
 	
-	/**
-	 * Address space identifier.
-	 * Constant on architectures that do not support ASIDs.
-	 * Protected by asidlock.
+	/** Address space identifier.
+	 *
+	 * Constant on architectures that do not
+	 * support ASIDs. Protected by asidlock.
+	 *
 	 */
 	asid_t asid;
 	
-	/** Number of references (i.e tasks that reference this as). */
+	/** Number of references (i.e. tasks that reference this as). */
 	atomic_t refcount;
 	
@@ -199,24 +201,29 @@
 typedef struct {
 	mutex_t lock;
+	
 	/** Containing address space. */
 	as_t *as;
 	
-	/**
-	 * Flags related to the memory represented by the address space area.
-	 */
+	/** Memory flags. */
 	unsigned int flags;
 	
-	/** Attributes related to the address space area itself. */
+	/** Address space area attributes. */
 	unsigned int attributes;
-	/** Size of this area in multiples of PAGE_SIZE. */
+	
+	/** Number of pages in the area. */
 	size_t pages;
+	
+	/** Number of resident pages in the area. */
+	size_t resident;
+	
 	/** Base address of this area. */
 	uintptr_t base;
+	
 	/** Map of used space. */
 	btree_t used_space;
 	
 	/**
-	 * If the address space area has been shared, this pointer will
-	 * reference the share info structure.
+	 * If the address space area is shared. this is
+	 * a reference to the share info structure.
 	 */
 	share_info_t *sh_info;
@@ -261,7 +268,6 @@
 extern bool as_area_check_access(as_area_t *, pf_access_t);
 extern size_t as_area_get_size(uintptr_t);
-extern int used_space_insert(as_area_t *, uintptr_t, size_t);
-extern int used_space_remove(as_area_t *, uintptr_t, size_t);
-
+extern bool used_space_insert(as_area_t *, uintptr_t, size_t);
+extern bool used_space_remove(as_area_t *, uintptr_t, size_t);
 
 /* Interface to be implemented by architectures. */
@@ -307,4 +313,5 @@
 extern sysarg_t sys_as_area_change_flags(uintptr_t, unsigned int);
 extern sysarg_t sys_as_area_destroy(uintptr_t);
+extern sysarg_t sys_as_get_unmapped_area(uintptr_t, size_t);
 
 /* Introspection functions. */
Index: kernel/generic/include/mm/page.h
===================================================================
--- kernel/generic/include/mm/page.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/mm/page.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,4 +37,5 @@
 
 #include <typedefs.h>
+#include <proc/task.h>
 #include <mm/as.h>
 #include <memstr.h>
@@ -62,4 +63,6 @@
 extern uintptr_t hw_map(uintptr_t, size_t);
 
+extern sysarg_t sys_page_find_mapping(uintptr_t, uintptr_t *);
+
 #endif
 
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/proc/task.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -131,4 +131,5 @@
 extern task_t *task_find_by_id(task_id_t);
 extern int task_kill(task_id_t);
+extern void task_kill_self(bool) __attribute__((noreturn));
 extern void task_get_accounting(task_t *, uint64_t *, uint64_t *);
 extern void task_print_list(bool);
@@ -155,4 +156,5 @@
 extern sysarg_t sys_task_set_name(const char *, size_t);
 extern sysarg_t sys_task_kill(task_id_t *);
+extern sysarg_t sys_task_exit(sysarg_t);
 
 #endif
Index: kernel/generic/include/proc/thread.h
===================================================================
--- kernel/generic/include/proc/thread.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/proc/thread.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -91,21 +91,23 @@
 	
 	/** Function implementing the thread. */
-	void (* thread_code)(void *);
+	void (*thread_code)(void *);
 	/** Argument passed to thread_code() function. */
 	void *thread_arg;
 	
 	/**
-	 * From here, the stored context is restored when the thread is
-	 * scheduled.
+	 * From here, the stored context is restored
+	 * when the thread is scheduled.
 	 */
 	context_t saved_context;
-	/**
-	 * From here, the stored timeout context is restored when sleep times
-	 * out.
+	
+	/**
+	 * From here, the stored timeout context
+	 * is restored when sleep times out.
 	 */
 	context_t sleep_timeout_context;
-	/**
-	 * From here, the stored interruption context is restored when sleep is
-	 * interrupted.
+	
+	/**
+	 * From here, the stored interruption context
+	 * is restored when sleep is interrupted.
 	 */
 	context_t sleep_interruption_context;
@@ -125,4 +127,5 @@
 	 */
 	bool in_copy_from_uspace;
+	
 	/**
 	 * True if this thread is executing copy_to_uspace().
@@ -187,4 +190,10 @@
 	
 #ifdef CONFIG_UDEBUG
+	/**
+	 * If true, the scheduler will print a stack trace
+	 * to the kernel console upon scheduling this thread.
+	 */
+	bool btrace;
+	
 	/** Debugging stuff */
 	udebug_thread_t udebug;
@@ -237,4 +246,8 @@
 extern bool thread_exists(thread_t *);
 
+#ifdef CONFIG_UDEBUG
+extern void thread_stack_trace(thread_id_t);
+#endif
+
 /** Fpu context slab cache. */
 extern slab_cache_t *fpu_context_slab;
Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/syscall/syscall.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -48,4 +48,5 @@
 	SYS_TASK_SET_NAME,
 	SYS_TASK_KILL,
+	SYS_TASK_EXIT,
 	SYS_PROGRAM_SPAWN_LOADER,
 	
@@ -58,4 +59,7 @@
 	SYS_AS_AREA_CHANGE_FLAGS,
 	SYS_AS_AREA_DESTROY,
+	SYS_AS_GET_UNMAPPED_AREA,
+	
+	SYS_PAGE_FIND_MAPPING,
 	
 	SYS_IPC_CALL_SYNC_FAST,
@@ -70,6 +74,4 @@
 	SYS_IPC_POKE,
 	SYS_IPC_HANGUP,
-	SYS_IPC_REGISTER_IRQ,
-	SYS_IPC_UNREGISTER_IRQ,
 	SYS_IPC_CONNECT_KBOX,
 	
@@ -82,4 +84,6 @@
 	SYS_PHYSMEM_MAP,
 	SYS_IOSPACE_ENABLE,
+	SYS_REGISTER_IRQ,
+	SYS_UNREGISTER_IRQ,
 	
 	SYS_SYSINFO_GET_TAG,
Index: kernel/generic/include/sysinfo/abi.h
===================================================================
--- kernel/generic/include/sysinfo/abi.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/sysinfo/abi.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -104,4 +104,5 @@
 	char name[TASK_NAME_BUFLEN];  /**< Task name (in kernel) */
 	size_t virtmem;               /**< Size of VAS (bytes) */
+	size_t resmem;                /**< Size of resident (used) memory (bytes) */
 	size_t threads;               /**< Number of threads */
 	uint64_t ucycles;             /**< Number of CPU cycles in user space */
Index: kernel/generic/include/sysinfo/sysinfo.h
===================================================================
--- kernel/generic/include/sysinfo/sysinfo.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/sysinfo/sysinfo.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -148,5 +148,5 @@
 extern sysarg_t sys_sysinfo_get_value(void *, size_t, void *);
 extern sysarg_t sys_sysinfo_get_data_size(void *, size_t, void *);
-extern sysarg_t sys_sysinfo_get_data(void *, size_t, void *, size_t);
+extern sysarg_t sys_sysinfo_get_data(void *, size_t, void *, size_t, size_t *);
 
 #endif
Index: kernel/generic/include/udebug/udebug.h
===================================================================
--- kernel/generic/include/udebug/udebug.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/include/udebug/udebug.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,144 +36,150 @@
 #define KERN_UDEBUG_H_
 
+#define UDEBUG_EVMASK(event)  (1 << ((event) - 1))
+
+typedef enum { /* udebug_method_t */
+	
+	/** Start debugging the recipient.
+	 *
+	 * Causes all threads in the receiving task to stop. When they
+	 * are all stoped, an answer with retval 0 is generated.
+	 *
+	 */
+	UDEBUG_M_BEGIN = 1,
+	
+	/** Finish debugging the recipient.
+	 *
+	 * Answers all pending GO and GUARD messages.
+	 *
+	 */
+	UDEBUG_M_END,
+	
+	/** Set which events should be captured. */
+	UDEBUG_M_SET_EVMASK,
+	
+	/** Make sure the debugged task is still there.
+	 *
+	 * This message is answered when the debugged task dies
+	 * or the debugging session ends.
+	 *
+	 */
+	UDEBUG_M_GUARD,
+	
+	/** Run a thread until a debugging event occurs.
+	 *
+	 * This message is answered when the thread stops
+	 * in a debugging event.
+	 *
+	 * - ARG2 - id of the thread to run
+	 *
+	 */
+	UDEBUG_M_GO,
+	
+	/** Stop a thread being debugged.
+	 *
+	 * Creates a special STOP event in the thread, causing
+	 * it to answer a pending GO message (if any).
+	 *
+	 */
+	UDEBUG_M_STOP,
+	
+	/** Read arguments of a syscall.
+	 *
+	 * - ARG2 - thread identification
+	 * - ARG3 - destination address in the caller's address space
+	 *
+	 */
+	UDEBUG_M_ARGS_READ,
+	
+	/** Read thread's userspace register state (istate_t).
+	 *
+	 * - ARG2 - thread identification
+	 * - ARG3 - destination address in the caller's address space
+	 *
+	 * or, on error, retval will be
+	 * - ENOENT - thread does not exist
+	 * - EBUSY - register state not available
+	 */
+	UDEBUG_M_REGS_READ,
+	
+	/** Read the list of the debugged tasks's threads.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - size of receiving buffer in bytes
+	 *
+	 * The kernel fills the buffer with a series of sysarg_t values
+	 * (thread ids). On answer, the kernel will set:
+	 *
+	 * - ARG2 - number of bytes that were actually copied
+	 * - ARG3 - number of bytes of the complete data
+	 *
+	 */
+	UDEBUG_M_THREAD_READ,
+	
+	/** Read the name of the debugged task.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - size of receiving buffer in bytes
+	 *
+	 * The kernel fills the buffer with a non-terminated string.
+	 *
+	 * - ARG2 - number of bytes that were actually copied
+	 * - ARG3 - number of bytes of the complete data
+	 *
+	 */
+	UDEBUG_M_NAME_READ,
+	
+	/** Read the list of the debugged task's address space areas.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - size of receiving buffer in bytes
+	 *
+	 * The kernel fills the buffer with a series of as_area_info_t structures.
+	 * Upon answer, the kernel will set:
+	 *
+	 * - ARG2 - number of bytes that were actually copied
+	 * - ARG3 - number of bytes of the complete data
+	 *
+	 */
+	UDEBUG_M_AREAS_READ,
+	
+	/** Read the debugged tasks's memory.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - source address in the recipient's address space
+	 * - ARG4 - size of receiving buffer in bytes
+	 *
+	 */
+	UDEBUG_M_MEM_READ
+} udebug_method_t;
+
+typedef enum {
+	UDEBUG_EVENT_FINISHED = 1,  /**< Debuging session has finished */
+	UDEBUG_EVENT_STOP,          /**< Stopped on DEBUG_STOP request */
+	UDEBUG_EVENT_SYSCALL_B,     /**< Before beginning syscall execution */
+	UDEBUG_EVENT_SYSCALL_E,     /**< After finishing syscall execution */
+	UDEBUG_EVENT_THREAD_B,      /**< The task created a new thread */
+	UDEBUG_EVENT_THREAD_E       /**< A thread exited */
+} udebug_event_t;
+
+typedef enum {
+	UDEBUG_EM_FINISHED = UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED),
+	UDEBUG_EM_STOP = UDEBUG_EVMASK(UDEBUG_EVENT_STOP),
+	UDEBUG_EM_SYSCALL_B = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B),
+	UDEBUG_EM_SYSCALL_E = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E),
+	UDEBUG_EM_THREAD_B = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B),
+	UDEBUG_EM_THREAD_E = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E),
+	UDEBUG_EM_ALL =
+	    (UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_STOP) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E))
+} udebug_evmask_t;
+
+#ifdef KERNEL
+
 #include <ipc/ipc.h>
-
-typedef enum { /* udebug_method_t */
-
-/** Start debugging the recipient.
- * Causes all threads in the receiving task to stop. When they
- * are all stoped, an answer with retval 0 is generated.
- */
-UDEBUG_M_BEGIN = 1,
-
-/** Finish debugging the recipient.
- * Answers all pending GO and GUARD messages.
- */
-UDEBUG_M_END,
-
-/** Set which events should be captured.
- */
-UDEBUG_M_SET_EVMASK,
-
-/** Make sure the debugged task is still there.
- * This message is answered when the debugged task dies
- * or the debugging session ends.
- */
-UDEBUG_M_GUARD,
-
-/** Run a thread until a debugging event occurs.
- * This message is answered when the thread stops
- * in a debugging event.
- *
- * - ARG2 - id of the thread to run
- */
-UDEBUG_M_GO,
-
-/** Stop a thread being debugged.
- * Creates a special STOP event in the thread, causing
- * it to answer a pending GO message (if any).
- */
-UDEBUG_M_STOP,
-
-/** Read arguments of a syscall.
- *
- * - ARG2 - thread identification
- * - ARG3 - destination address in the caller's address space
- *
- */
-UDEBUG_M_ARGS_READ,
-
-/** Read thread's userspace register state (istate_t).
- *
- * - ARG2 - thread identification
- * - ARG3 - destination address in the caller's address space
- *
- * or, on error, retval will be
- * - ENOENT - thread does not exist
- * - EBUSY - register state not available
- */
-UDEBUG_M_REGS_READ,
-
-/** Read the list of the debugged tasks's threads.
- *
- * - ARG2 - destination address in the caller's address space
- * - ARG3 - size of receiving buffer in bytes
- *
- * The kernel fills the buffer with a series of sysarg_t values
- * (thread ids). On answer, the kernel will set:
- *
- * - ARG2 - number of bytes that were actually copied
- * - ARG3 - number of bytes of the complete data
- *
- */
-UDEBUG_M_THREAD_READ,
-
-/** Read the name of the debugged task.
- *
- * - ARG2 - destination address in the caller's address space
- * - ARG3 - size of receiving buffer in bytes
- *
- * The kernel fills the buffer with a non-terminated string.
- *
- * - ARG2 - number of bytes that were actually copied
- * - ARG3 - number of bytes of the complete data
- *
- */
-UDEBUG_M_NAME_READ,
-
-/** Read the list of the debugged task's address space areas.
- *
- * - ARG2 - destination address in the caller's address space
- * - ARG3 - size of receiving buffer in bytes
- *
- * The kernel fills the buffer with a series of as_area_info_t structures.
- * Upon answer, the kernel will set:
- *
- * - ARG2 - number of bytes that were actually copied
- * - ARG3 - number of bytes of the complete data
- *
- */
-UDEBUG_M_AREAS_READ,
-
-/** Read the debugged tasks's memory.
- *
- * - ARG2 - destination address in the caller's address space
- * - ARG3 - source address in the recipient's address space
- * - ARG4 - size of receiving buffer in bytes
- *
- */
-UDEBUG_M_MEM_READ,
-
-} udebug_method_t;
-
-
-typedef enum {
-	UDEBUG_EVENT_FINISHED = 1,	/**< Debuging session has finished */
-	UDEBUG_EVENT_STOP,		/**< Stopped on DEBUG_STOP request */
-	UDEBUG_EVENT_SYSCALL_B,		/**< Before beginning syscall execution */
-	UDEBUG_EVENT_SYSCALL_E,		/**< After finishing syscall execution */
-	UDEBUG_EVENT_THREAD_B,		/**< The task created a new thread */
-	UDEBUG_EVENT_THREAD_E		/**< A thread exited */
-} udebug_event_t;
-
-#define UDEBUG_EVMASK(event) (1 << ((event) - 1))
-
-typedef enum {
-	UDEBUG_EM_FINISHED	= UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED),
-	UDEBUG_EM_STOP		= UDEBUG_EVMASK(UDEBUG_EVENT_STOP),
-	UDEBUG_EM_SYSCALL_B	= UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B),
-	UDEBUG_EM_SYSCALL_E	= UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E),
-	UDEBUG_EM_THREAD_B	= UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B),
-	UDEBUG_EM_THREAD_E	= UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E),
-	UDEBUG_EM_ALL		=
-		UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED) |
-		UDEBUG_EVMASK(UDEBUG_EVENT_STOP) |
-		UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B) |
-		UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E) |
-		UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B) |
-		UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E)
-} udebug_evmask_t;
-
-#ifdef KERNEL
-
 #include <synch/mutex.h>
 #include <synch/condvar.h>
@@ -196,5 +202,5 @@
 	mutex_t lock;
 	char *lock_owner;
-
+	
 	udebug_task_state_t dt_state;
 	call_t *begin_call;
@@ -209,15 +215,15 @@
 	/** Synchronize debug ops on this thread / access to this structure. */
 	mutex_t lock;
-
+	
 	waitq_t go_wq;
 	call_t *go_call;
 	sysarg_t syscall_args[6];
 	istate_t *uspace_state;
-
+	
 	/** What type of event are we stopped in or 0 if none. */
 	udebug_event_t cur_event;
-	bool go;		/**< thread is GO */
-	bool stoppable;		/**< thread is stoppable */
-	bool active;		/**< thread is in a debugging session */
+	bool go;         /**< Thread is GO */
+	bool stoppable;  /**< Thread is stoppable */
+	bool active;     /**< Thread is in a debugging session */
 	condvar_t active_cv;
 } udebug_thread_t;
@@ -226,12 +232,11 @@
 struct thread;
 
-void udebug_task_init(udebug_task_t *ut);
-void udebug_thread_initialize(udebug_thread_t *ut);
-
-void udebug_syscall_event(sysarg_t a1, sysarg_t a2, sysarg_t a3,
-    sysarg_t a4, sysarg_t a5, sysarg_t a6, sysarg_t id, sysarg_t rc,
-    bool end_variant);
-
-void udebug_thread_b_event_attach(struct thread *t, struct task *ta);
+void udebug_task_init(udebug_task_t *);
+void udebug_thread_initialize(udebug_thread_t *);
+
+void udebug_syscall_event(sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, bool);
+
+void udebug_thread_b_event_attach(struct thread *, struct task *);
 void udebug_thread_e_event(void);
 
@@ -241,5 +246,5 @@
 void udebug_before_thread_runs(void);
 
-int udebug_task_cleanup(struct task *ta);
+int udebug_task_cleanup(struct task *);
 void udebug_thread_fault(void);
 
Index: kernel/generic/src/adt/avl.c
===================================================================
--- kernel/generic/src/adt/avl.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/adt/avl.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -723,5 +723,6 @@
 void avltree_walk(avltree_t *t, avltree_walker_t walker, void *arg)
 {
-	_avltree_walk(t->root, walker, arg);
+	if (t->root)
+		_avltree_walk(t->root, walker, arg);
 }
 
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/console/cmd.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -78,25 +78,28 @@
 static cmd_info_t help_info = {
 	.name = "help",
-	.description = "List of supported commands.",
+	.description = "List supported commands.",
 	.func = cmd_help,
 	.argc = 0
 };
 
+/* Data and methods for 'reboot' command. */
 static int cmd_reboot(cmd_arg_t *argv);
 static cmd_info_t reboot_info = {
 	.name = "reboot",
-	.description = "Reboot.",
+	.description = "Reboot system.",
 	.func = cmd_reboot,
 	.argc = 0
 };
 
+/* Data and methods for 'uptime' command. */
 static int cmd_uptime(cmd_arg_t *argv);
 static cmd_info_t uptime_info = {
 	.name = "uptime",
-	.description = "Print uptime information.",
+	.description = "Show system uptime.",
 	.func = cmd_uptime,
 	.argc = 0
 };
 
+/* Data and methods for 'continue' command. */
 static int cmd_continue(cmd_arg_t *argv);
 static cmd_info_t continue_info = {
@@ -108,4 +111,6 @@
 
 #ifdef CONFIG_TEST
+
+/* Data and methods for 'test' command. */
 static char test_buf[MAX_CMDLINE + 1];
 static int cmd_test(cmd_arg_t *argv);
@@ -119,5 +124,5 @@
 static cmd_info_t test_info = {
 	.name = "test",
-	.description = "Print list of kernel tests or run a test.",
+	.description = "<test> List kernel tests or run a test.",
 	.func = cmd_test,
 	.argc = 1,
@@ -125,4 +130,5 @@
 };
 
+/* Data and methods for 'bench' command. */
 static int cmd_bench(cmd_arg_t *argv);
 static cmd_arg_t bench_argv[] = {
@@ -138,15 +144,16 @@
 static cmd_info_t bench_info = {
 	.name = "bench",
-	.description = "Run kernel test as benchmark.",
+	.description = "<test> <count> Run kernel test as benchmark.",
 	.func = cmd_bench,
 	.argc = 2,
 	.argv = bench_argv
 };
-#endif
+
+#endif /* CONFIG_TEST */
 
 /* Data and methods for 'description' command. */
 static int cmd_desc(cmd_arg_t *argv);
 static void desc_help(void);
-static char desc_buf[MAX_CMDLINE+1];
+static char desc_buf[MAX_CMDLINE + 1];
 static cmd_arg_t desc_argv = {
 	.type = ARG_TYPE_STRING,
@@ -156,5 +163,5 @@
 static cmd_info_t desc_info = {
 	.name = "describe",
-	.description = "Describe specified command.",
+	.description = "<command> Describe specified command.",
 	.help = desc_help,
 	.func = cmd_desc,
@@ -165,5 +172,5 @@
 /* Data and methods for 'symaddr' command. */
 static int cmd_symaddr(cmd_arg_t *argv);
-static char symaddr_buf[MAX_CMDLINE+1];
+static char symaddr_buf[MAX_CMDLINE + 1];
 static cmd_arg_t symaddr_argv = {
 	.type = ARG_TYPE_STRING,
@@ -173,5 +180,5 @@
 static cmd_info_t symaddr_info = {
 	.name = "symaddr",
-	.description = "Return symbol address.",
+	.description = "<symbol> Return symbol address.",
 	.func = cmd_symaddr,
 	.argc = 1,
@@ -179,5 +186,6 @@
 };
 
-static char set_buf[MAX_CMDLINE+1];
+/* Data and methods for 'set4' command. */
+static char set_buf[MAX_CMDLINE + 1];
 static int cmd_set4(cmd_arg_t *argv);
 static cmd_arg_t set4_argv[] = {
@@ -193,5 +201,5 @@
 static cmd_info_t set4_info = {
 	.name = "set4",
-	.description = "set <dest_addr> <value> - 4byte version",
+	.description = "<addr> <value> Set 4B memory location to a value.",
 	.func = cmd_set4,
 	.argc = 2,
@@ -213,5 +221,5 @@
 static cmd_info_t call0_info = {
 	.name = "call0",
-	.description = "call0 <function> -> call function().",
+	.description = "<function> Call function().",
 	.func = cmd_call0,
 	.argc = 1,
@@ -228,5 +236,5 @@
 static cmd_info_t mcall0_info = {
 	.name = "mcall0",
-	.description = "mcall0 <function> -> call function() on each CPU.",
+	.description = "<function> Call function() on each CPU.",
 	.func = cmd_mcall0,
 	.argc = 1,
@@ -250,5 +258,5 @@
 static cmd_info_t call1_info = {
 	.name = "call1",
-	.description = "call1 <function> <arg1> -> call function(arg1).",
+	.description = "<function> <arg1> Call function(arg1).",
 	.func = cmd_call1,
 	.argc = 2,
@@ -277,5 +285,5 @@
 static cmd_info_t call2_info = {
 	.name = "call2",
-	.description = "call2 <function> <arg1> <arg2> -> call function(arg1,arg2).",
+	.description = "<function> <arg1> <arg2> Call function(arg1, arg2).",
 	.func = cmd_call2,
 	.argc = 3,
@@ -310,5 +318,5 @@
 static cmd_info_t call3_info = {
 	.name = "call3",
-	.description = "call3 <function> <arg1> <arg2> <arg3> -> call function(arg1,arg2,arg3).",
+	.description = "<function> <arg1> <arg2> <arg3> Call function(arg1, arg2, arg3).",
 	.func = cmd_call3,
 	.argc = 4,
@@ -340,5 +348,5 @@
 cmd_info_t tlb_info = {
 	.name = "tlb",
-	.description = "Print TLB of current processor.",
+	.description = "Print TLB of the current CPU.",
 	.help = NULL,
 	.func = cmd_tlb,
@@ -377,9 +385,25 @@
 };
 
+#ifdef CONFIG_UDEBUG
+
+/* Data and methods for 'btrace' command */
+static int cmd_btrace(cmd_arg_t *argv);
+static cmd_arg_t btrace_argv = {
+	.type = ARG_TYPE_INT,
+};
+static cmd_info_t btrace_info = {
+	.name = "btrace",
+	.description = "<threadid> Show thread stack trace.",
+	.func = cmd_btrace,
+	.argc = 1,
+	.argv = &btrace_argv
+};
+
+#endif /* CONFIG_UDEBUG */
 
 static int cmd_sched(cmd_arg_t *argv);
 static cmd_info_t sched_info = {
 	.name = "scheduler",
-	.description = "List all scheduler information.",
+	.description = "Show scheduler information.",
 	.func = cmd_sched,
 	.argc = 0
@@ -406,7 +430,21 @@
 static cmd_info_t zones_info = {
 	.name = "zones",
-	.description = "List of memory zones.",
+	.description = "List memory zones.",
 	.func = cmd_zones,
 	.argc = 0
+};
+
+/* Data and methods for 'zone' command */
+static int cmd_zone(cmd_arg_t *argv);
+static cmd_arg_t zone_argv = {
+	.type = ARG_TYPE_INT,
+};
+
+static cmd_info_t zone_info = {
+	.name = "zone",
+	.description = "<zone> Show memory zone structure.",
+	.func = cmd_zone,
+	.argc = 1,
+	.argv = &zone_argv
 };
 
@@ -418,5 +456,5 @@
 static cmd_info_t ipc_info = {
 	.name = "ipc",
-	.description = "ipc <taskid> Show IPC information of given task.",
+	.description = "<taskid> Show IPC information of a task.",
 	.func = cmd_ipc,
 	.argc = 1,
@@ -431,22 +469,8 @@
 static cmd_info_t kill_info = {
 	.name = "kill",
-	.description = "kill <taskid> Kill a task.",
+	.description = "<taskid> Kill a task.",
 	.func = cmd_kill,
 	.argc = 1,
 	.argv = &kill_argv
-};
-
-/* Data and methods for 'zone' command */
-static int cmd_zone(cmd_arg_t *argv);
-static cmd_arg_t zone_argv = {
-	.type = ARG_TYPE_INT,
-};
-
-static cmd_info_t zone_info = {
-	.name = "zone",
-	.description = "Show memory zone structure.",
-	.func = cmd_zone,
-	.argc = 1,
-	.argv = &zone_argv
 };
 
@@ -482,19 +506,19 @@
 	&cpus_info,
 	&desc_info,
-	&reboot_info,
-	&uptime_info,
 	&halt_info,
 	&help_info,
 	&ipc_info,
 	&kill_info,
+	&physmem_info,
+	&reboot_info,
+	&sched_info,
 	&set4_info,
 	&slabs_info,
+	&symaddr_info,
 	&sysinfo_info,
-	&symaddr_info,
-	&sched_info,
+	&tasks_info,
 	&threads_info,
-	&tasks_info,
-	&physmem_info,
 	&tlb_info,
+	&uptime_info,
 	&version_info,
 	&zones_info,
@@ -504,4 +528,7 @@
 	&bench_info,
 #endif
+#ifdef CONFIG_UDEBUG
+	&btrace_info,
+#endif
 	NULL
 };
@@ -526,9 +553,13 @@
 	for (i = 0; basic_commands[i]; i++) {
 		cmd_initialize(basic_commands[i]);
-		if (!cmd_register(basic_commands[i]))
-			printf("Cannot register command %s\n", basic_commands[i]->name);
-	}
-}
-
+	}
+
+	for (i = 0; basic_commands[i]; i++) {
+		if (!cmd_register(basic_commands[i])) {
+			printf("Cannot register command %s\n",
+			    basic_commands[i]->name);
+		}
+	}
+}
 
 /** List supported commands.
@@ -574,5 +605,4 @@
 }
 
-
 /** Reboot the system.
  *
@@ -588,5 +618,4 @@
 	return 1;
 }
-
 
 /** Print system uptime information.
@@ -824,5 +853,4 @@
 }
 
-
 /** Print detailed description of 'describe' command. */
 void desc_help(void)
@@ -911,5 +939,5 @@
  * @return Always 1
  */
-int cmd_slabs(cmd_arg_t * argv)
+int cmd_slabs(cmd_arg_t *argv)
 {
 	slab_print_list();
@@ -923,5 +951,5 @@
  * @return Always 1
  */
-int cmd_sysinfo(cmd_arg_t * argv)
+int cmd_sysinfo(cmd_arg_t *argv)
 {
 	sysinfo_dump(NULL);
@@ -929,6 +957,5 @@
 }
 
-
-/** Command for listings Thread information
+/** Command for listing thread information
  *
  * @param argv Ignored
@@ -948,5 +975,5 @@
 }
 
-/** Command for listings Task information
+/** Command for listing task information
  *
  * @param argv Ignored
@@ -966,5 +993,22 @@
 }
 
-/** Command for listings Thread information
+#ifdef CONFIG_UDEBUG
+
+/** Command for printing thread stack trace
+ *
+ * @param argv Integer argument from cmdline expected
+ *
+ * return Always 1
+ *
+ */
+int cmd_btrace(cmd_arg_t *argv)
+{
+	thread_stack_trace(argv[0].intval);
+	return 1;
+}
+
+#endif /* CONFIG_UDEBUG */
+
+/** Command for printing scheduler information
  *
  * @param argv Ignores
@@ -972,5 +1016,5 @@
  * @return Always 1
  */
-int cmd_sched(cmd_arg_t * argv)
+int cmd_sched(cmd_arg_t *argv)
 {
 	sched_print_list();
@@ -984,5 +1028,5 @@
  * return Always 1
  */
-int cmd_zones(cmd_arg_t * argv)
+int cmd_zones(cmd_arg_t *argv)
 {
 	zones_print_list();
@@ -996,5 +1040,5 @@
  * return Always 1
  */
-int cmd_zone(cmd_arg_t * argv)
+int cmd_zone(cmd_arg_t *argv)
 {
 	zone_print_one(argv[0].intval);
@@ -1002,5 +1046,5 @@
 }
 
-/** Command for printing task ipc details
+/** Command for printing task IPC details
  *
  * @param argv Integer argument from cmdline expected
@@ -1008,5 +1052,5 @@
  * return Always 1
  */
-int cmd_ipc(cmd_arg_t * argv)
+int cmd_ipc(cmd_arg_t *argv)
 {
 	ipc_print_task(argv[0].intval);
@@ -1020,5 +1064,5 @@
  * return 0 on failure, 1 on success.
  */
-int cmd_kill(cmd_arg_t * argv)
+int cmd_kill(cmd_arg_t *argv)
 {
 	if (task_kill(argv[0].intval) != EOK)
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/console/console.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -160,4 +160,5 @@
 	klog_parea.pbase = (uintptr_t) faddr;
 	klog_parea.frames = SIZE2FRAMES(sizeof(klog));
+	klog_parea.unpriv = false;
 	ddi_parea_register(&klog_parea);
 	
Index: kernel/generic/src/ddi/ddi.c
===================================================================
--- kernel/generic/src/ddi/ddi.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/ddi/ddi.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -104,13 +104,17 @@
 {
 	ASSERT(TASK);
-	ASSERT((pf % FRAME_SIZE) == 0);
-	ASSERT((vp % PAGE_SIZE) == 0);
-	
-	/*
-	 * Make sure the caller is authorised to make this syscall.
-	 */
-	cap_t caps = cap_get(TASK);
-	if (!(caps & CAP_MEM_MANAGER))
-		return EPERM;
+	
+	if ((pf % FRAME_SIZE) != 0)
+		return EBADMEM;
+	
+	if ((vp % PAGE_SIZE) != 0)
+		return EBADMEM;
+	
+	/*
+	 * Unprivileged tasks are only allowed to map pareas
+	 * which are explicitly marked as such.
+	 */
+	bool priv =
+	    ((cap_get(TASK) & CAP_MEM_MANAGER) == CAP_MEM_MANAGER);
 	
 	mem_backend_data_t backend_data;
@@ -123,14 +127,27 @@
 	
 	if (znum == (size_t) -1) {
-		/* Frames not found in any zones
-		 * -> assume it is hardware device and allow mapping
+		/*
+		 * Frames not found in any zone
+		 * -> assume it is a hardware device and allow mapping
+		 *    for privileged tasks.
 		 */
 		irq_spinlock_unlock(&zones.lock, true);
+		
+		if (!priv)
+			return EPERM;
+		
 		goto map;
 	}
 	
 	if (zones.info[znum].flags & ZONE_FIRMWARE) {
-		/* Frames are part of firmware */
+		/*
+		 * Frames are part of firmware
+		 * -> allow mapping for privileged tasks.
+		 */
 		irq_spinlock_unlock(&zones.lock, true);
+		
+		if (!priv)
+			return EPERM;
+		
 		goto map;
 	}
@@ -138,6 +155,6 @@
 	if (zone_flags_available(zones.info[znum].flags)) {
 		/*
-		 * Frames are part of physical memory, check if the memory
-		 * region is enabled for mapping.
+		 * Frames are part of physical memory, check
+		 * if the memory region is enabled for mapping.
 		 */
 		irq_spinlock_unlock(&zones.lock, true);
@@ -150,5 +167,12 @@
 		if ((!parea) || (parea->frames < pages)) {
 			mutex_unlock(&parea_lock);
-			goto err;
+			return ENOENT;
+		}
+		
+		if (!priv) {
+			if (!parea->unpriv) {
+				mutex_unlock(&parea_lock);
+				return EPERM;
+			}
 		}
 		
@@ -158,6 +182,4 @@
 	
 	irq_spinlock_unlock(&zones.lock, true);
-	
-err:
 	return ENOENT;
 	
Index: kernel/generic/src/interrupt/interrupt.c
===================================================================
--- kernel/generic/src/interrupt/interrupt.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/interrupt/interrupt.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,5 +45,4 @@
 #include <console/console.h>
 #include <console/cmd.h>
-#include <ipc/event.h>
 #include <synch/mutex.h>
 #include <time/delay.h>
@@ -188,23 +187,5 @@
 	printf("\n");
 	
-	/*
-	 * Userspace can subscribe for FAULT events to take action
-	 * whenever a thread faults. (E.g. take a dump, run a debugger).
-	 * The notification is always available, but unless Udebug is enabled,
-	 * that's all you get.
-	 */
-	if (event_is_subscribed(EVENT_FAULT)) {
-		/* Notify the subscriber that a fault occurred. */
-		event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid),
-		    UPPER32(TASK->taskid), (sysarg_t) THREAD);
-		
-#ifdef CONFIG_UDEBUG
-		/* Wait for a debugging session. */
-		udebug_thread_fault();
-#endif
-	}
-	
-	task_kill(TASK->taskid);
-	thread_exit();
+	task_kill_self(true);
 }
 
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/ipc/ipc.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -295,4 +295,5 @@
 		atomic_inc(&phone->active_calls);
 		call->data.phone = phone;
+		call->data.task = TASK;
 	}
 	
@@ -406,4 +407,5 @@
 			call->caller_phone = call->data.phone;
 		call->data.phone = newphone;
+		call->data.task = TASK;
 	}
 	
@@ -688,32 +690,32 @@
 	irq_spinlock_exchange(&tasks_lock, &task->lock);
 	
-	/* Print opened phones & details */
-	printf("PHONE:\n");
+	printf("[phone id] [calls] [state\n");
 	
 	size_t i;
 	for (i = 0; i < IPC_MAX_PHONES; i++) {
 		if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) {
-			printf("%zu: mutex busy\n", i);
+			printf("%-10zu (mutex busy)\n", i);
 			continue;
 		}
 		
 		if (task->phones[i].state != IPC_PHONE_FREE) {
-			printf("%zu: ", i);
+			printf("%-10zu %7" PRIun " ", i,
+			    atomic_get(&task->phones[i].active_calls));
 			
 			switch (task->phones[i].state) {
 			case IPC_PHONE_CONNECTING:
-				printf("connecting ");
+				printf("connecting");
 				break;
 			case IPC_PHONE_CONNECTED:
-				printf("connected to: %p (%" PRIu64 ") ",
-				    task->phones[i].callee,
-				    task->phones[i].callee->task->taskid);
+				printf("connected to %" PRIu64 " (%s)",
+				    task->phones[i].callee->task->taskid,
+				    task->phones[i].callee->task->name);
 				break;
 			case IPC_PHONE_SLAMMED:
-				printf("slammed by: %p ", 
+				printf("slammed by %p",
 				    task->phones[i].callee);
 				break;
 			case IPC_PHONE_HUNGUP:
-				printf("hung up - was: %p ", 
+				printf("hung up by %p",
 				    task->phones[i].callee);
 				break;
@@ -722,6 +724,5 @@
 			}
 			
-			printf("active: %" PRIun "\n",
-			    atomic_get(&task->phones[i].active_calls));
+			printf("\n");
 		}
 		
@@ -731,49 +732,79 @@
 	irq_spinlock_lock(&task->answerbox.lock, false);
 	
+#ifdef __32_BITS__
+	printf("[call id ] [method] [arg1] [arg2] [arg3] [arg4] [arg5]"
+	    " [flags] [sender\n");
+#endif
+	
+#ifdef __64_BITS__
+	printf("[call id         ] [method] [arg1] [arg2] [arg3] [arg4]"
+	    " [arg5] [flags] [sender\n");
+#endif
+	
 	link_t *cur;
 	
-	/* Print answerbox - calls */
-	printf("ABOX - CALLS:\n");
+	printf(" --- incomming calls ---\n");
 	for (cur = task->answerbox.calls.next; cur != &task->answerbox.calls;
 	    cur = cur->next) {
 		call_t *call = list_get_instance(cur, call_t, link);
-		printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun 
-		    " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
-		    " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call,
-		    call->sender->taskid,
+		
+#ifdef __32_BITS__
+		printf("%10p ", call);
+#endif
+		
+#ifdef __64_BITS__
+		printf("%18p ", call);
+#endif
+		
+		printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun
+		    " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n",
 		    IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data),
 		    IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
 		    IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
-		    call->flags);
-	}
-	
-	/* Print answerbox - dispatched calls */
-	printf("ABOX - DISPATCHED CALLS:\n");
+		    call->flags, call->sender->taskid, call->sender->name);
+	}
+	
+	printf(" --- dispatched calls ---\n");
 	for (cur = task->answerbox.dispatched_calls.next;
 	    cur != &task->answerbox.dispatched_calls;
 	    cur = cur->next) {
 		call_t *call = list_get_instance(cur, call_t, link);
-		printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
-		    " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
-		    " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call,
-		    call->sender->taskid,
+		
+#ifdef __32_BITS__
+		printf("%10p ", call);
+#endif
+		
+#ifdef __64_BITS__
+		printf("%18p ", call);
+#endif
+		
+		printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun
+		    " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n",
 		    IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data),
 		    IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
 		    IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
-		    call->flags);
-	}
-	
-	/* Print answerbox - answers */
-	printf("ABOX - ANSWERS:\n");
+		    call->flags, call->sender->taskid, call->sender->name);
+	}
+	
+	printf(" --- incoming answers ---\n");
 	for (cur = task->answerbox.answers.next;
 	    cur != &task->answerbox.answers;
 	    cur = cur->next) {
 		call_t *call = list_get_instance(cur, call_t, link);
-		printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun
-		    " A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n",
-		    call, IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data),
+		
+#ifdef __32_BITS__
+		printf("%10p ", call);
+#endif
+		
+#ifdef __64_BITS__
+		printf("%18p ", call);
+#endif
+		
+		printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun
+		    " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n",
+		    IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data),
 		    IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
 		    IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
-		    call->flags);
+		    call->flags, call->sender->taskid, call->sender->name);
 	}
 	
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/ipc/irq.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -42,5 +42,5 @@
  *
  * The structure of a notification message is as follows:
- * - IMETHOD: interface and method as registered by the SYS_IPC_REGISTER_IRQ
+ * - IMETHOD: interface and method as registered by the SYS_REGISTER_IRQ
  *            syscall
  * - ARG1: payload modified by a 'top-half' handler
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/ipc/sysipc.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -248,4 +248,6 @@
 			/* The connection was accepted */
 			phone_connect(phoneid, &answer->sender->answerbox);
+			/* Set 'task hash' as arg4 of response */
+			IPC_SET_ARG4(answer->data, (sysarg_t) TASK);
 			/* Set 'phone hash' as arg5 of response */
 			IPC_SET_ARG5(answer->data,
@@ -1103,5 +1105,5 @@
  *
  */
-sysarg_t sys_ipc_register_irq(inr_t inr, devno_t devno, sysarg_t imethod,
+sysarg_t sys_register_irq(inr_t inr, devno_t devno, sysarg_t imethod,
     irq_code_t *ucode)
 {
@@ -1120,5 +1122,5 @@
  *
  */
-sysarg_t sys_ipc_unregister_irq(inr_t inr, devno_t devno)
+sysarg_t sys_unregister_irq(inr_t inr, devno_t devno)
 {
 	if (!(cap_get(TASK) & CAP_IRQ_REG))
Index: kernel/generic/src/lib/elf.c
===================================================================
--- kernel/generic/src/lib/elf.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/lib/elf.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -157,4 +157,5 @@
 	case PT_NULL:
 	case PT_PHDR:
+	case PT_NOTE:
 		break;
 	case PT_LOAD:
@@ -173,5 +174,4 @@
 		break;
 	case PT_SHLIB:
-	case PT_NOTE:
 	case PT_LOPROC:
 	case PT_HIPROC:
Index: kernel/generic/src/lib/rd.c
===================================================================
--- kernel/generic/src/lib/rd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/lib/rd.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -90,4 +90,5 @@
 	    FRAME_SIZE);
 	rd_parea.frames = SIZE2FRAMES(dsize);
+	rd_parea.unpriv = false;
 	ddi_parea_register(&rd_parea);
 
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/mm/as.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -71,4 +71,5 @@
 #include <memstr.h>
 #include <macros.h>
+#include <bitops.h>
 #include <arch.h>
 #include <errno.h>
@@ -86,17 +87,15 @@
  * Each architecture decides what functions will be used to carry out
  * address space operations such as creating or locking page tables.
- *
  */
 as_operations_t *as_operations = NULL;
 
-/**
- * Slab for as_t objects.
+/** Slab for as_t objects.
  *
  */
 static slab_cache_t *as_slab;
 
-/**
- * This lock serializes access to the ASID subsystem.
- * It protects:
+/** ASID subsystem lock.
+ *
+ * This lock protects:
  * - inactive_as_with_asid_head list
  * - as->asid for each as of the as_t type
@@ -107,7 +106,6 @@
 
 /**
- * This list contains address spaces that are not active on any
- * processor and that have valid ASID.
- *
+ * Inactive address spaces (on all processors)
+ * that have valid ASID.
  */
 LIST_INITIALIZE(inactive_as_with_asid_head);
@@ -123,13 +121,10 @@
 	mutex_initialize(&as->lock, MUTEX_PASSIVE);
 	
-	int rc = as_constructor_arch(as, flags);
-	
-	return rc;
+	return as_constructor_arch(as, flags);
 }
 
 NO_TRACE static size_t as_destructor(void *obj)
 {
-	as_t *as = (as_t *) obj;
-	return as_destructor_arch(as);
+	return as_destructor_arch((as_t *) obj);
 }
 
@@ -146,5 +141,6 @@
 		panic("Cannot create kernel address space.");
 	
-	/* Make sure the kernel address space
+	/*
+	 * Make sure the kernel address space
 	 * reference count never drops to zero.
 	 */
@@ -195,5 +191,5 @@
 {
 	DEADLOCK_PROBE_INIT(p_asidlock);
-
+	
 	ASSERT(as != AS);
 	ASSERT(atomic_get(&as->refcount) == 0);
@@ -203,5 +199,5 @@
 	 * lock its mutex.
 	 */
-
+	
 	/*
 	 * We need to avoid deadlock between TLB shootdown and asidlock.
@@ -210,5 +206,4 @@
 	 * disabled to prevent nested context switches. We also depend on the
 	 * fact that so far no spinlocks are held.
-	 *
 	 */
 	preemption_disable();
@@ -235,5 +230,5 @@
 	spinlock_unlock(&asidlock);
 	interrupts_restore(ipl);
-
+	
 	
 	/*
@@ -241,5 +236,4 @@
 	 * The B+tree must be walked carefully because it is
 	 * also being destroyed.
-	 *
 	 */
 	bool cond = true;
@@ -268,6 +262,6 @@
 /** Hold a reference to an address space.
  *
- * Holding a reference to an address space prevents destruction of that address
- * space.
+ * Holding a reference to an address space prevents destruction
+ * of that address space.
  *
  * @param as Address space to be held.
@@ -281,6 +275,6 @@
 /** Release a reference to an address space.
  *
- * The last one to release a reference to an address space destroys the address
- * space.
+ * The last one to release a reference to an address space
+ * destroys the address space.
  *
  * @param asAddress space to be released.
@@ -295,22 +289,22 @@
 /** Check area conflicts with other areas.
  *
- * @param as         Address space.
- * @param va         Starting virtual address of the area being tested.
- * @param size       Size of the area being tested.
- * @param avoid_area Do not touch this area.
+ * @param as    Address space.
+ * @param addr  Starting virtual address of the area being tested.
+ * @param count Number of pages in the area being tested.
+ * @param avoid Do not touch this area.
  *
  * @return True if there is no conflict, false otherwise.
  *
  */
-NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
-    as_area_t *avoid_area)
-{
+NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr,
+    size_t count, as_area_t *avoid)
+{
+	ASSERT((addr % PAGE_SIZE) == 0);
 	ASSERT(mutex_locked(&as->lock));
 	
 	/*
 	 * We don't want any area to have conflicts with NULL page.
-	 *
-	 */
-	if (overlaps(va, size, (uintptr_t) NULL, PAGE_SIZE))
+	 */
+	if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
 		return false;
 	
@@ -321,11 +315,10 @@
 	 * record in the left neighbour, the leftmost record in the right
 	 * neighbour and all records in the leaf node itself.
-	 *
 	 */
 	btree_node_t *leaf;
 	as_area_t *area =
-	    (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
+	    (as_area_t *) btree_search(&as->as_area_btree, addr, &leaf);
 	if (area) {
-		if (area != avoid_area)
+		if (area != avoid)
 			return false;
 	}
@@ -337,12 +330,15 @@
 		area = (as_area_t *) node->value[node->keys - 1];
 		
-		mutex_lock(&area->lock);
-		
-		if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
+		if (area != avoid) {
+			mutex_lock(&area->lock);
+			
+			if (overlaps(addr, count << PAGE_WIDTH,
+			    area->base, area->pages << PAGE_WIDTH)) {
+				mutex_unlock(&area->lock);
+				return false;
+			}
+			
 			mutex_unlock(&area->lock);
-			return false;
-		}
-		
-		mutex_unlock(&area->lock);
+		}
 	}
 	
@@ -351,12 +347,15 @@
 		area = (as_area_t *) node->value[0];
 		
-		mutex_lock(&area->lock);
-		
-		if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
+		if (area != avoid) {
+			mutex_lock(&area->lock);
+			
+			if (overlaps(addr, count << PAGE_WIDTH,
+			    area->base, area->pages << PAGE_WIDTH)) {
+				mutex_unlock(&area->lock);
+				return false;
+			}
+			
 			mutex_unlock(&area->lock);
-			return false;
-		}
-		
-		mutex_unlock(&area->lock);
+		}
 	}
 	
@@ -366,10 +365,11 @@
 		area = (as_area_t *) leaf->value[i];
 		
-		if (area == avoid_area)
+		if (area == avoid)
 			continue;
 		
 		mutex_lock(&area->lock);
 		
-		if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
+		if (overlaps(addr, count << PAGE_WIDTH,
+		    area->base, area->pages << PAGE_WIDTH)) {
 			mutex_unlock(&area->lock);
 			return false;
@@ -382,8 +382,7 @@
 	 * So far, the area does not conflict with other areas.
 	 * Check if it doesn't conflict with kernel address space.
-	 *
 	 */
 	if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
-		return !overlaps(va, size,
+		return !overlaps(addr, count << PAGE_WIDTH,
 		    KERNEL_ADDRESS_SPACE_START,
 		    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
@@ -412,9 +411,11 @@
     mem_backend_data_t *backend_data)
 {
-	if (base % PAGE_SIZE)
+	if ((base % PAGE_SIZE) != 0)
 		return NULL;
 	
-	if (!size)
+	if (size == 0)
 		return NULL;
+	
+	size_t pages = SIZE2FRAMES(size);
 	
 	/* Writeable executable areas are not supported. */
@@ -424,5 +425,5 @@
 	mutex_lock(&as->lock);
 	
-	if (!check_area_conflicts(as, base, size, NULL)) {
+	if (!check_area_conflicts(as, base, pages, NULL)) {
 		mutex_unlock(&as->lock);
 		return NULL;
@@ -436,5 +437,6 @@
 	area->flags = flags;
 	area->attributes = attrs;
-	area->pages = SIZE2FRAMES(size);
+	area->pages = pages;
+	area->resident = 0;
 	area->base = base;
 	area->sh_info = NULL;
@@ -479,5 +481,4 @@
 	 * to find out whether this is a miss or va belongs to an address
 	 * space area found there.
-	 *
 	 */
 	
@@ -490,5 +491,6 @@
 		mutex_lock(&area->lock);
 		
-		if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
+		if ((area->base <= va) &&
+		    (va < area->base + (area->pages << PAGE_WIDTH)))
 			return area;
 		
@@ -499,5 +501,4 @@
 	 * Second, locate the left neighbour and test its last record.
 	 * Because of its position in the B+tree, it must have base < va.
-	 *
 	 */
 	btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
@@ -507,5 +508,5 @@
 		mutex_lock(&area->lock);
 		
-		if (va < area->base + area->pages * PAGE_SIZE)
+		if (va < area->base + (area->pages << PAGE_WIDTH))
 			return area;
 		
@@ -534,5 +535,4 @@
 	/*
 	 * Locate the area.
-	 *
 	 */
 	as_area_t *area = find_area_and_lock(as, address);
@@ -546,5 +546,4 @@
 		 * Remapping of address space areas associated
 		 * with memory mapped devices is not supported.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -557,5 +556,4 @@
 		 * Remapping of shared address space areas
 		 * is not supported.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -568,5 +566,4 @@
 		/*
 		 * Zero size address space areas are not allowed.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -576,10 +573,9 @@
 	
 	if (pages < area->pages) {
-		uintptr_t start_free = area->base + pages * PAGE_SIZE;
+		uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
 		
 		/*
 		 * Shrinking the area.
 		 * No need to check for overlaps.
-		 *
 		 */
 		
@@ -588,8 +584,7 @@
 		/*
 		 * Start TLB shootdown sequence.
-		 *
 		 */
 		ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
-		    area->base + pages * PAGE_SIZE, area->pages - pages);
+		    area->base + (pages << PAGE_WIDTH), area->pages - pages);
 		
 		/*
@@ -599,5 +594,4 @@
 		 * is also the right way to remove part of the used_space
 		 * B+tree leaf list.
-		 *
 		 */
 		bool cond = true;
@@ -615,13 +609,12 @@
 				size_t i = 0;
 				
-				if (overlaps(ptr, size * PAGE_SIZE, area->base,
-				    pages * PAGE_SIZE)) {
+				if (overlaps(ptr, size << PAGE_WIDTH, area->base,
+				    pages << PAGE_WIDTH)) {
 					
-					if (ptr + size * PAGE_SIZE <= start_free) {
+					if (ptr + (size << PAGE_WIDTH) <= start_free) {
 						/*
 						 * The whole interval fits
 						 * completely in the resized
 						 * address space area.
-						 *
 						 */
 						break;
@@ -632,5 +625,4 @@
 					 * to b and c overlaps with the resized
 					 * address space area.
-					 *
 					 */
 					
@@ -652,5 +644,5 @@
 				for (; i < size; i++) {
 					pte_t *pte = page_mapping_find(as, ptr +
-					    i * PAGE_SIZE);
+					    (i << PAGE_WIDTH));
 					
 					ASSERT(pte);
@@ -661,10 +653,10 @@
 					    (area->backend->frame_free)) {
 						area->backend->frame_free(area,
-						    ptr + i * PAGE_SIZE,
+						    ptr + (i << PAGE_WIDTH),
 						    PTE_GET_FRAME(pte));
 					}
 					
 					page_mapping_remove(as, ptr +
-					    i * PAGE_SIZE);
+					    (i << PAGE_WIDTH));
 				}
 			}
@@ -673,16 +665,14 @@
 		/*
 		 * Finish TLB shootdown sequence.
-		 *
-		 */
-		
-		tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
+		 */
+		
+		tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
 		    area->pages - pages);
 		
 		/*
 		 * Invalidate software translation caches (e.g. TSB on sparc64).
-		 *
 		 */
 		as_invalidate_translation_cache(as, area->base +
-		    pages * PAGE_SIZE, area->pages - pages);
+		    (pages << PAGE_WIDTH), area->pages - pages);
 		tlb_shootdown_finalize(ipl);
 		
@@ -692,8 +682,6 @@
 		 * Growing the area.
 		 * Check for overlaps with other address space areas.
-		 *
-		 */
-		if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
-		    area)) {
+		 */
+		if (!check_area_conflicts(as, address, pages, area)) {
 			mutex_unlock(&area->lock);
 			mutex_unlock(&as->lock);
@@ -794,5 +782,6 @@
 			
 			for (size = 0; size < (size_t) node->value[i]; size++) {
-				pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
+				pte_t *pte =
+				    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
 				
 				ASSERT(pte);
@@ -803,8 +792,8 @@
 				    (area->backend->frame_free)) {
 					area->backend->frame_free(area,
-					    ptr + size * PAGE_SIZE, PTE_GET_FRAME(pte));
+					    ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
 				}
 				
-				page_mapping_remove(as, ptr + size * PAGE_SIZE);
+				page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
 			}
 		}
@@ -813,5 +802,4 @@
 	/*
 	 * Finish TLB shootdown sequence.
-	 *
 	 */
 	
@@ -821,5 +809,4 @@
 	 * Invalidate potential software translation caches (e.g. TSB on
 	 * sparc64).
-	 *
 	 */
 	as_invalidate_translation_cache(as, area->base, area->pages);
@@ -839,5 +826,4 @@
 	/*
 	 * Remove the empty area from address space.
-	 *
 	 */
 	btree_remove(&as->as_area_btree, base, NULL);
@@ -881,5 +867,4 @@
 		/*
 		 * Could not find the source address space area.
-		 *
 		 */
 		mutex_unlock(&src_as->lock);
@@ -891,5 +876,4 @@
 		 * There is no backend or the backend does not
 		 * know how to share the area.
-		 *
 		 */
 		mutex_unlock(&src_area->lock);
@@ -898,5 +882,5 @@
 	}
 	
-	size_t src_size = src_area->pages * PAGE_SIZE;
+	size_t src_size = src_area->pages << PAGE_WIDTH;
 	unsigned int src_flags = src_area->flags;
 	mem_backend_t *src_backend = src_area->backend;
@@ -918,5 +902,4 @@
 	 * First, prepare the area for sharing.
 	 * Then it will be safe to unlock it.
-	 *
 	 */
 	share_info_t *sh_info = src_area->sh_info;
@@ -930,5 +913,4 @@
 		/*
 		 * Call the backend to setup sharing.
-		 *
 		 */
 		src_area->backend->share(src_area);
@@ -949,5 +931,4 @@
 	 * The flags of the source area are masked against dst_flags_mask
 	 * to support sharing in less privileged mode.
-	 *
 	 */
 	as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask, src_size,
@@ -966,5 +947,4 @@
 	 * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
 	 * attribute and set the sh_info.
-	 *
 	 */
 	mutex_lock(&dst_as->lock);
@@ -989,4 +969,6 @@
 NO_TRACE bool as_area_check_access(as_area_t *area, pf_access_t access)
 {
+	ASSERT(mutex_locked(&area->lock));
+	
 	int flagmap[] = {
 		[PF_ACCESS_READ] = AS_AREA_READ,
@@ -994,6 +976,4 @@
 		[PF_ACCESS_EXEC] = AS_AREA_EXEC
 	};
-
-	ASSERT(mutex_locked(&area->lock));
 	
 	if (!(area->flags & flagmap[access]))
@@ -1066,5 +1046,4 @@
 	/*
 	 * Compute total number of used pages in the used_space B+tree
-	 *
 	 */
 	size_t used_pages = 0;
@@ -1088,5 +1067,4 @@
 	/*
 	 * Start TLB shootdown sequence.
-	 *
 	 */
 	ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
@@ -1096,5 +1074,4 @@
 	 * Remove used pages from page tables and remember their frame
 	 * numbers.
-	 *
 	 */
 	size_t frame_idx = 0;
@@ -1111,5 +1088,6 @@
 			
 			for (size = 0; size < (size_t) node->value[i]; size++) {
-				pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
+				pte_t *pte =
+				    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
 				
 				ASSERT(pte);
@@ -1120,5 +1098,5 @@
 				
 				/* Remove old mapping */
-				page_mapping_remove(as, ptr + size * PAGE_SIZE);
+				page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
 			}
 		}
@@ -1127,5 +1105,4 @@
 	/*
 	 * Finish TLB shootdown sequence.
-	 *
 	 */
 	
@@ -1135,5 +1112,4 @@
 	 * Invalidate potential software translation caches (e.g. TSB on
 	 * sparc64).
-	 *
 	 */
 	as_invalidate_translation_cache(as, area->base, area->pages);
@@ -1168,5 +1144,5 @@
 				
 				/* Insert the new mapping */
-				page_mapping_insert(as, ptr + size * PAGE_SIZE,
+				page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
 				    old_frame[frame_idx++], page_flags);
 				
@@ -1217,5 +1193,4 @@
 		 * No area contained mapping for 'page'.
 		 * Signal page fault to low-level handler.
-		 *
 		 */
 		mutex_unlock(&AS->lock);
@@ -1237,5 +1212,4 @@
 		 * The address space area is not backed by any backend
 		 * or the backend cannot handle page faults.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -1249,5 +1223,4 @@
 	 * To avoid race condition between two page faults on the same address,
 	 * we need to make sure the mapping has not been already inserted.
-	 *
 	 */
 	pte_t *pte;
@@ -1267,5 +1240,4 @@
 	/*
 	 * Resort to the backend page fault handler.
-	 *
 	 */
 	if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
@@ -1322,5 +1294,4 @@
 		 * preemption is disabled. We should not be
 		 * holding any other lock.
-		 *
 		 */
 		(void) interrupts_enable();
@@ -1342,5 +1313,4 @@
 			 * list of inactive address spaces with assigned
 			 * ASID.
-			 *
 			 */
 			ASSERT(old_as->asid != ASID_INVALID);
@@ -1353,5 +1323,4 @@
 		 * Perform architecture-specific tasks when the address space
 		 * is being removed from the CPU.
-		 *
 		 */
 		as_deinstall_arch(old_as);
@@ -1360,5 +1329,4 @@
 	/*
 	 * Second, prepare the new address space.
-	 *
 	 */
 	if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
@@ -1376,5 +1344,4 @@
 	 * Perform architecture-specific steps.
 	 * (e.g. write ASID to hardware register etc.)
-	 *
 	 */
 	as_install_arch(new_as);
@@ -1395,5 +1362,5 @@
 {
 	ASSERT(mutex_locked(&area->lock));
-
+	
 	return area_flags_to_page_flags(area->flags);
 }
@@ -1499,5 +1466,5 @@
 	
 	if (src_area) {
-		size = src_area->pages * PAGE_SIZE;
+		size = src_area->pages << PAGE_WIDTH;
 		mutex_unlock(&src_area->lock);
 	} else
@@ -1516,8 +1483,8 @@
  * @param count Number of page to be marked.
  *
- * @return Zero on failure and non-zero on success.
- *
- */
-int used_space_insert(as_area_t *area, uintptr_t page, size_t count)
+ * @return False on failure or true on success.
+ *
+ */
+bool used_space_insert(as_area_t *area, uintptr_t page, size_t count)
 {
 	ASSERT(mutex_locked(&area->lock));
@@ -1530,12 +1497,11 @@
 		/*
 		 * We hit the beginning of some used space.
-		 *
-		 */
-		return 0;
+		 */
+		return false;
 	}
 	
 	if (!leaf->keys) {
 		btree_insert(&area->used_space, page, (void *) count, leaf);
-		return 1;
+		goto success;
 	}
 	
@@ -1551,54 +1517,49 @@
 		 * somewhere between the rightmost interval of
 		 * the left neigbour and the first interval of the leaf.
-		 *
 		 */
 		
 		if (page >= right_pg) {
 			/* Do nothing. */
-		} else if (overlaps(page, count * PAGE_SIZE, left_pg,
-		    left_cnt * PAGE_SIZE)) {
+		} else if (overlaps(page, count << PAGE_WIDTH, left_pg,
+		    left_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the left interval. */
-			return 0;
-		} else if (overlaps(page, count * PAGE_SIZE, right_pg,
-		    right_cnt * PAGE_SIZE)) {
+			return false;
+		} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
+		    right_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the right interval. */
-			return 0;
-		} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
-		    (page + count * PAGE_SIZE == right_pg)) {
+			return false;
+		} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
+		    (page + (count << PAGE_WIDTH) == right_pg)) {
 			/*
 			 * The interval can be added by merging the two already
 			 * present intervals.
-			 *
 			 */
 			node->value[node->keys - 1] += count + right_cnt;
 			btree_remove(&area->used_space, right_pg, leaf);
-			return 1;
-		} else if (page == left_pg + left_cnt * PAGE_SIZE) {
+			goto success;
+		} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
 			/*
 			 * The interval can be added by simply growing the left
 			 * interval.
-			 *
 			 */
 			node->value[node->keys - 1] += count;
-			return 1;
-		} else if (page + count * PAGE_SIZE == right_pg) {
+			goto success;
+		} else if (page + (count << PAGE_WIDTH) == right_pg) {
 			/*
 			 * The interval can be addded by simply moving base of
 			 * the right interval down and increasing its size
 			 * accordingly.
-			 *
 			 */
 			leaf->value[0] += count;
 			leaf->key[0] = page;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval is between both neigbouring intervals,
 			 * but cannot be merged with any of them.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	} else if (page < leaf->key[0]) {
@@ -1609,30 +1570,27 @@
 		 * Investigate the border case in which the left neighbour does
 		 * not exist but the interval fits from the left.
-		 *
-		 */
-		
-		if (overlaps(page, count * PAGE_SIZE, right_pg,
-		    right_cnt * PAGE_SIZE)) {
+		 */
+		
+		if (overlaps(page, count << PAGE_WIDTH, right_pg,
+		    right_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the right interval. */
-			return 0;
-		} else if (page + count * PAGE_SIZE == right_pg) {
+			return false;
+		} else if (page + (count << PAGE_WIDTH) == right_pg) {
 			/*
 			 * The interval can be added by moving the base of the
 			 * right interval down and increasing its size
 			 * accordingly.
-			 *
 			 */
 			leaf->key[0] = page;
 			leaf->value[0] += count;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval doesn't adjoin with the right interval.
 			 * It must be added individually.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	}
@@ -1649,54 +1607,49 @@
 		 * somewhere between the leftmost interval of
 		 * the right neigbour and the last interval of the leaf.
-		 *
 		 */
 		
 		if (page < left_pg) {
 			/* Do nothing. */
-		} else if (overlaps(page, count * PAGE_SIZE, left_pg,
-		    left_cnt * PAGE_SIZE)) {
+		} else if (overlaps(page, count << PAGE_WIDTH, left_pg,
+		    left_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the left interval. */
-			return 0;
-		} else if (overlaps(page, count * PAGE_SIZE, right_pg,
-		    right_cnt * PAGE_SIZE)) {
+			return false;
+		} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
+		    right_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the right interval. */
-			return 0;
-		} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
-		    (page + count * PAGE_SIZE == right_pg)) {
+			return false;
+		} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
+		    (page + (count << PAGE_WIDTH) == right_pg)) {
 			/*
 			 * The interval can be added by merging the two already
 			 * present intervals.
-			 *
 			 */
 			leaf->value[leaf->keys - 1] += count + right_cnt;
 			btree_remove(&area->used_space, right_pg, node);
-			return 1;
-		} else if (page == left_pg + left_cnt * PAGE_SIZE) {
+			goto success;
+		} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
 			/*
 			 * The interval can be added by simply growing the left
 			 * interval.
-			 *
 			 */
-			leaf->value[leaf->keys - 1] +=  count;
-			return 1;
-		} else if (page + count * PAGE_SIZE == right_pg) {
+			leaf->value[leaf->keys - 1] += count;
+			goto success;
+		} else if (page + (count << PAGE_WIDTH) == right_pg) {
 			/*
 			 * The interval can be addded by simply moving base of
 			 * the right interval down and increasing its size
 			 * accordingly.
-			 *
 			 */
 			node->value[0] += count;
 			node->key[0] = page;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval is between both neigbouring intervals,
 			 * but cannot be merged with any of them.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	} else if (page >= leaf->key[leaf->keys - 1]) {
@@ -1707,28 +1660,25 @@
 		 * Investigate the border case in which the right neighbour
 		 * does not exist but the interval fits from the right.
-		 *
-		 */
-		
-		if (overlaps(page, count * PAGE_SIZE, left_pg,
-		    left_cnt * PAGE_SIZE)) {
+		 */
+		
+		if (overlaps(page, count << PAGE_WIDTH, left_pg,
+		    left_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the left interval. */
-			return 0;
-		} else if (left_pg + left_cnt * PAGE_SIZE == page) {
+			return false;
+		} else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
 			/*
 			 * The interval can be added by growing the left
 			 * interval.
-			 *
 			 */
 			leaf->value[leaf->keys - 1] += count;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval doesn't adjoin with the left interval.
 			 * It must be added individually.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	}
@@ -1738,5 +1688,4 @@
 	 * only between two other intervals of the leaf. The two border cases
 	 * were already resolved.
-	 *
 	 */
 	btree_key_t i;
@@ -1750,51 +1699,45 @@
 			/*
 			 * The interval fits between left_pg and right_pg.
-			 *
 			 */
 			
-			if (overlaps(page, count * PAGE_SIZE, left_pg,
-			    left_cnt * PAGE_SIZE)) {
+			if (overlaps(page, count << PAGE_WIDTH, left_pg,
+			    left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval intersects with the left
 				 * interval.
-				 *
 				 */
-				return 0;
-			} else if (overlaps(page, count * PAGE_SIZE, right_pg,
-			    right_cnt * PAGE_SIZE)) {
+				return false;
+			} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
+			    right_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval intersects with the right
 				 * interval.
-				 *
 				 */
-				return 0;
-			} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
-			    (page + count * PAGE_SIZE == right_pg)) {
+				return false;
+			} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
+			    (page + (count << PAGE_WIDTH) == right_pg)) {
 				/*
 				 * The interval can be added by merging the two
 				 * already present intervals.
-				 *
 				 */
 				leaf->value[i - 1] += count + right_cnt;
 				btree_remove(&area->used_space, right_pg, leaf);
-				return 1;
-			} else if (page == left_pg + left_cnt * PAGE_SIZE) {
+				goto success;
+			} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval can be added by simply growing
 				 * the left interval.
-				 *
 				 */
 				leaf->value[i - 1] += count;
-				return 1;
-			} else if (page + count * PAGE_SIZE == right_pg) {
+				goto success;
+			} else if (page + (count << PAGE_WIDTH) == right_pg) {
 				/*
 				 * The interval can be addded by simply moving
 				 * base of the right interval down and
 				 * increasing its size accordingly.
-				 *
 				 */
 				leaf->value[i] += count;
 				leaf->key[i] = page;
-				return 1;
+				goto success;
 			} else {
 				/*
@@ -1802,9 +1745,8 @@
 				 * intervals, but cannot be merged with any of
 				 * them.
-				 *
 				 */
 				btree_insert(&area->used_space, page,
 				    (void *) count, leaf);
-				return 1;
+				goto success;
 			}
 		}
@@ -1813,4 +1755,8 @@
 	panic("Inconsistency detected while adding %zu pages of used "
 	    "space at %p.", count, (void *) page);
+	
+success:
+	area->resident += count;
+	return true;
 }
 
@@ -1823,8 +1769,8 @@
  * @param count Number of page to be marked.
  *
- * @return Zero on failure and non-zero on success.
- *
- */
-int used_space_remove(as_area_t *area, uintptr_t page, size_t count)
+ * @return False on failure or true on success.
+ *
+ */
+bool used_space_remove(as_area_t *area, uintptr_t page, size_t count)
 {
 	ASSERT(mutex_locked(&area->lock));
@@ -1837,25 +1783,24 @@
 		/*
 		 * We are lucky, page is the beginning of some interval.
-		 *
 		 */
 		if (count > pages) {
-			return 0;
+			return false;
 		} else if (count == pages) {
 			btree_remove(&area->used_space, page, leaf);
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * Find the respective interval.
 			 * Decrease its size and relocate its start address.
-			 *
 			 */
 			btree_key_t i;
 			for (i = 0; i < leaf->keys; i++) {
 				if (leaf->key[i] == page) {
-					leaf->key[i] += count * PAGE_SIZE;
+					leaf->key[i] += count << PAGE_WIDTH;
 					leaf->value[i] -= count;
-					return 1;
+					goto success;
 				}
 			}
+			
 			goto error;
 		}
@@ -1867,8 +1812,8 @@
 		size_t left_cnt = (size_t) node->value[node->keys - 1];
 		
-		if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
-		    count * PAGE_SIZE)) {
-			if (page + count * PAGE_SIZE ==
-			    left_pg + left_cnt * PAGE_SIZE) {
+		if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
+		    count << PAGE_WIDTH)) {
+			if (page + (count << PAGE_WIDTH) ==
+			    left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1876,10 +1821,9 @@
 				 * removed by updating the size of the bigger
 				 * interval.
-				 *
 				 */
 				node->value[node->keys - 1] -= count;
-				return 1;
-			} else if (page + count * PAGE_SIZE <
-			    left_pg + left_cnt*PAGE_SIZE) {
+				goto success;
+			} else if (page + (count << PAGE_WIDTH) <
+			    left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1888,17 +1832,17 @@
 				 * the original interval and also inserting a
 				 * new interval.
-				 *
 				 */
-				size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
-				    (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
+				size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
+				    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
 				node->value[node->keys - 1] -= count + new_cnt;
 				btree_insert(&area->used_space, page +
-				    count * PAGE_SIZE, (void *) new_cnt, leaf);
-				return 1;
+				    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
+				goto success;
 			}
 		}
-		return 0;
+		
+		return false;
 	} else if (page < leaf->key[0])
-		return 0;
+		return false;
 	
 	if (page > leaf->key[leaf->keys - 1]) {
@@ -1906,18 +1850,17 @@
 		size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
 		
-		if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
-		    count * PAGE_SIZE)) {
-			if (page + count * PAGE_SIZE ==
-			    left_pg + left_cnt * PAGE_SIZE) {
+		if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
+		    count << PAGE_WIDTH)) {
+			if (page + (count << PAGE_WIDTH) ==
+			    left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
 				 * interval of the leaf and can be removed by
 				 * updating the size of the bigger interval.
-				 *
 				 */
 				leaf->value[leaf->keys - 1] -= count;
-				return 1;
-			} else if (page + count * PAGE_SIZE < left_pg +
-			    left_cnt * PAGE_SIZE) {
+				goto success;
+			} else if (page + (count << PAGE_WIDTH) < left_pg +
+			    (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1926,20 +1869,20 @@
 				 * original interval and also inserting a new
 				 * interval.
-				 *
 				 */
-				size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
-				    (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
+				size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
+				    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
 				leaf->value[leaf->keys - 1] -= count + new_cnt;
 				btree_insert(&area->used_space, page +
-				    count * PAGE_SIZE, (void *) new_cnt, leaf);
-				return 1;
+				    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
+				goto success;
 			}
 		}
-		return 0;
+		
+		return false;
 	}
 	
 	/*
 	 * The border cases have been already resolved.
-	 * Now the interval can be only between intervals of the leaf. 
+	 * Now the interval can be only between intervals of the leaf.
 	 */
 	btree_key_t i;
@@ -1953,8 +1896,8 @@
 			 * to (i - 1) and i.
 			 */
-			if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
-			    count * PAGE_SIZE)) {
-				if (page + count * PAGE_SIZE ==
-				    left_pg + left_cnt*PAGE_SIZE) {
+			if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
+			    count << PAGE_WIDTH)) {
+				if (page + (count << PAGE_WIDTH) ==
+				    left_pg + (left_cnt << PAGE_WIDTH)) {
 					/*
 					 * The interval is contained in the
@@ -1962,10 +1905,9 @@
 					 * be removed by updating the size of
 					 * the bigger interval.
-					 *
 					 */
 					leaf->value[i - 1] -= count;
-					return 1;
-				} else if (page + count * PAGE_SIZE <
-				    left_pg + left_cnt * PAGE_SIZE) {
+					goto success;
+				} else if (page + (count << PAGE_WIDTH) <
+				    left_pg + (left_cnt << PAGE_WIDTH)) {
 					/*
 					 * The interval is contained in the
@@ -1976,15 +1918,16 @@
 					 */
 					size_t new_cnt = ((left_pg +
-					    left_cnt * PAGE_SIZE) -
-					    (page + count * PAGE_SIZE)) >>
+					    (left_cnt << PAGE_WIDTH)) -
+					    (page + (count << PAGE_WIDTH))) >>
 					    PAGE_WIDTH;
 					leaf->value[i - 1] -= count + new_cnt;
 					btree_insert(&area->used_space, page +
-					    count * PAGE_SIZE, (void *) new_cnt,
+					    (count << PAGE_WIDTH), (void *) new_cnt,
 					    leaf);
-					return 1;
+					goto success;
 				}
 			}
-			return 0;
+			
+			return false;
 		}
 	}
@@ -1993,4 +1936,8 @@
 	panic("Inconsistency detected while removing %zu pages of used "
 	    "space from %p.", count, (void *) page);
+	
+success:
+	area->resident -= count;
+	return true;
 }
 
@@ -2027,4 +1974,70 @@
 }
 
+/** Return pointer to unmapped address space area
+ *
+ * @param base Lowest address bound.
+ * @param size Requested size of the allocation.
+ *
+ * @return Pointer to the beginning of unmapped address space area.
+ *
+ */
+sysarg_t sys_as_get_unmapped_area(uintptr_t base, size_t size)
+{
+	if (size == 0)
+		return 0;
+	
+	/*
+	 * Make sure we allocate from page-aligned
+	 * address. Check for possible overflow in
+	 * each step.
+	 */
+	
+	size_t pages = SIZE2FRAMES(size);
+	uintptr_t ret = 0;
+	
+	/*
+	 * Find the lowest unmapped address aligned on the sz
+	 * boundary, not smaller than base and of the required size.
+	 */
+	
+	mutex_lock(&AS->lock);
+	
+	/* First check the base address itself */
+	uintptr_t addr = ALIGN_UP(base, PAGE_SIZE);
+	if ((addr >= base) &&
+	    (check_area_conflicts(AS, addr, pages, NULL)))
+		ret = addr;
+	
+	/* Eventually check the addresses behind each area */
+	link_t *cur;
+	for (cur = AS->as_area_btree.leaf_head.next;
+	    (ret == 0) && (cur != &AS->as_area_btree.leaf_head);
+	    cur = cur->next) {
+		btree_node_t *node =
+		    list_get_instance(cur, btree_node_t, leaf_link);
+		
+		btree_key_t i;
+		for (i = 0; (ret == 0) && (i < node->keys); i++) {
+			as_area_t *area = (as_area_t *) node->value[i];
+			
+			mutex_lock(&area->lock);
+			
+			uintptr_t addr =
+			    ALIGN_UP(area->base + (area->pages << PAGE_WIDTH),
+			    PAGE_SIZE);
+			
+			if ((addr >= base) && (addr >= area->base) &&
+			    (check_area_conflicts(AS, addr, pages, area)))
+				ret = addr;
+			
+			mutex_unlock(&area->lock);
+		}
+	}
+	
+	mutex_unlock(&AS->lock);
+	
+	return (sysarg_t) ret;
+}
+
 /** Get list of adress space areas.
  *
@@ -2093,5 +2106,5 @@
 	mutex_lock(&as->lock);
 	
-	/* print out info about address space areas */
+	/* Print out info about address space areas */
 	link_t *cur;
 	for (cur = as->as_area_btree.leaf_head.next;
Index: kernel/generic/src/mm/backend_phys.c
===================================================================
--- kernel/generic/src/mm/backend_phys.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/mm/backend_phys.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -81,6 +81,7 @@
 	page_mapping_insert(AS, addr, base + (addr - area->base),
 	    as_area_get_flags(area));
-        if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
-                panic("Cannot insert used space.");
+	
+	if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
+		panic("Cannot insert used space.");
 
 	return AS_PF_OK;
Index: kernel/generic/src/mm/page.c
===================================================================
--- kernel/generic/src/mm/page.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/mm/page.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -60,4 +60,6 @@
 
 #include <mm/page.h>
+#include <genarch/mm/page_ht.h>
+#include <genarch/mm/page_pt.h>
 #include <arch/mm/page.h>
 #include <arch/mm/asid.h>
@@ -70,4 +72,6 @@
 #include <debug.h>
 #include <arch.h>
+#include <syscall/copy.h>
+#include <errno.h>
 
 /** Virtual operations for page subsystem. */
@@ -173,4 +177,35 @@
 }
 
+/** Syscall wrapper for getting mapping of a virtual page.
+ * 
+ * @retval EOK Everything went find, @p uspace_frame and @p uspace_node
+ *             contains correct values.
+ * @retval ENOENT Virtual address has no mapping.
+ */
+sysarg_t sys_page_find_mapping(uintptr_t virt_address,
+    uintptr_t *uspace_frame)
+{
+	mutex_lock(&AS->lock);
+	
+	pte_t *pte = page_mapping_find(AS, virt_address);
+	if (!PTE_VALID(pte) || !PTE_PRESENT(pte)) {
+		mutex_unlock(&AS->lock);
+		
+		return (sysarg_t) ENOENT;
+	}
+	
+	uintptr_t phys_address = PTE_GET_FRAME(pte);
+	
+	mutex_unlock(&AS->lock);
+	
+	int rc = copy_to_uspace(uspace_frame,
+	    &phys_address, sizeof(phys_address));
+	if (rc != EOK) {
+		return (sysarg_t) rc;
+	}
+	
+	return EOK;
+}
+
 /** @}
  */
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/proc/program.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -171,4 +171,5 @@
 	void *loader = program_loader;
 	if (!loader) {
+		as_destroy(as);
 		printf("Cannot spawn loader as none was registered\n");
 		return ENOENT;
@@ -179,4 +180,5 @@
 	if (rc != EE_OK) {
 		as_destroy(as);
+		printf("Cannot spawn loader (%s)\n", elf_error(rc));
 		return ENOENT;
 	}
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/proc/scheduler.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -62,8 +62,6 @@
 #include <print.h>
 #include <debug.h>
-
-static void before_task_runs(void);
-static void before_thread_runs(void);
-static void after_thread_ran(void);
+#include <stacktrace.h>
+
 static void scheduler_separated_stack(void);
 
@@ -71,5 +69,5 @@
 
 /** Carry out actions before new task runs. */
-void before_task_runs(void)
+static void before_task_runs(void)
 {
 	before_task_runs_arch();
@@ -80,14 +78,15 @@
  * Perform actions that need to be
  * taken before the newly selected
- * tread is passed control.
+ * thread is passed control.
  *
  * THREAD->lock is locked on entry
  *
  */
-void before_thread_runs(void)
+static void before_thread_runs(void)
 {
 	before_thread_runs_arch();
+	
 #ifdef CONFIG_FPU_LAZY
-	if(THREAD == CPU->fpu_owner)
+	if (THREAD == CPU->fpu_owner)
 		fpu_enable();
 	else
@@ -102,4 +101,16 @@
 	}
 #endif
+	
+#ifdef CONFIG_UDEBUG
+	if (THREAD->btrace) {
+		istate_t *istate = THREAD->udebug.uspace_state;
+		if (istate != NULL) {
+			printf("Thread %" PRIu64 " stack trace:\n", THREAD->tid);
+			stack_trace_istate(istate);
+		}
+		
+		THREAD->btrace = false;
+	}
+#endif
 }
 
@@ -113,5 +124,5 @@
  *
  */
-void after_thread_ran(void)
+static void after_thread_ran(void)
 {
 	after_thread_ran_arch();
@@ -391,5 +402,4 @@
 	 * possible destruction should thread_destroy() be called on this or any
 	 * other processor while the scheduler is still using them.
-	 *
 	 */
 	if (old_task)
@@ -417,10 +427,8 @@
 				 * The thread structure is kept allocated until
 				 * somebody calls thread_detach() on it.
-				 *
 				 */
 				if (!irq_spinlock_trylock(&THREAD->join_wq.lock)) {
 					/*
 					 * Avoid deadlock.
-					 *
 					 */
 					irq_spinlock_unlock(&THREAD->lock, false);
@@ -443,5 +451,4 @@
 			/*
 			 * Prefer the thread after it's woken up.
-			 *
 			 */
 			THREAD->priority = -1;
@@ -451,5 +458,4 @@
 			 * waitq_sleep(). Address of wq->lock is kept in
 			 * THREAD->sleep_queue.
-			 *
 			 */
 			irq_spinlock_unlock(&THREAD->sleep_queue->lock, false);
@@ -461,5 +467,4 @@
 			/*
 			 * Entering state is unexpected.
-			 *
 			 */
 			panic("tid%" PRIu64 ": unexpected state %s.",
@@ -480,7 +485,6 @@
 	
 	/*
-	 * If both the old and the new task are the same, lots of work is
-	 * avoided.
-	 *
+	 * If both the old and the new task are the same,
+	 * lots of work is avoided.
 	 */
 	if (TASK != THREAD->task) {
@@ -488,7 +492,6 @@
 		
 		/*
-		 * Note that it is possible for two tasks to share one address
-		 * space.
-		 (
+		 * Note that it is possible for two tasks
+		 * to share one address space.
 		 */
 		if (old_as != new_as) {
@@ -496,5 +499,4 @@
 			 * Both tasks and address spaces are different.
 			 * Replace the old one with the new one.
-			 *
 			 */
 			as_switch(old_as, new_as);
@@ -527,5 +529,4 @@
 	 * necessary, is to be mapped in before_thread_runs(). This
 	 * function must be executed before the switch to the new stack.
-	 *
 	 */
 	before_thread_runs();
@@ -534,5 +535,4 @@
 	 * Copy the knowledge of CPU, TASK, THREAD and preemption counter to
 	 * thread's stack.
-	 *
 	 */
 	the_copy(THE, (the_t *) THREAD->kstack);
@@ -658,5 +658,4 @@
 				/*
 				 * Ready thread on local CPU
-				 *
 				 */
 				
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/proc/task.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -342,19 +342,33 @@
 sysarg_t sys_task_set_name(const char *uspace_name, size_t name_len)
 {
-	int rc;
 	char namebuf[TASK_NAME_BUFLEN];
 	
 	/* Cap length of name and copy it from userspace. */
-	
 	if (name_len > TASK_NAME_BUFLEN - 1)
 		name_len = TASK_NAME_BUFLEN - 1;
 	
-	rc = copy_from_uspace(namebuf, uspace_name, name_len);
+	int rc = copy_from_uspace(namebuf, uspace_name, name_len);
 	if (rc != 0)
 		return (sysarg_t) rc;
 	
 	namebuf[name_len] = '\0';
+	
+	/*
+	 * As the task name is referenced also from the
+	 * threads, lock the threads' lock for the course
+	 * of the update.
+	 */
+	
+	irq_spinlock_lock(&tasks_lock, true);
+	irq_spinlock_lock(&TASK->lock, false);
+	irq_spinlock_lock(&threads_lock, false);
+	
+	/* Set task name */
 	str_cpy(TASK->name, TASK_NAME_BUFLEN, namebuf);
 	
+	irq_spinlock_unlock(&threads_lock, false);
+	irq_spinlock_unlock(&TASK->lock, false);
+	irq_spinlock_unlock(&tasks_lock, true);
+	
 	return EOK;
 }
@@ -370,10 +384,8 @@
 {
 	task_id_t taskid;
-	int rc;
-
-	rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(taskid));
+	int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(taskid));
 	if (rc != 0)
 		return (sysarg_t) rc;
-
+	
 	return (sysarg_t) task_kill(taskid);
 }
@@ -449,10 +461,12 @@
 static void task_kill_internal(task_t *task)
 {
+	irq_spinlock_lock(&task->lock, false);
+	irq_spinlock_lock(&threads_lock, false);
+	
+	/*
+	 * Interrupt all threads.
+	 */
+	
 	link_t *cur;
-	
-	/*
-	 * Interrupt all threads.
-	 */
-	irq_spinlock_lock(&task->lock, false);
 	for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
@@ -471,4 +485,5 @@
 	}
 	
+	irq_spinlock_unlock(&threads_lock, false);
 	irq_spinlock_unlock(&task->lock, false);
 }
@@ -500,4 +515,52 @@
 	irq_spinlock_unlock(&tasks_lock, true);
 	
+	return EOK;
+}
+
+/** Kill the currently running task.
+ *
+ * @param notify Send out fault notifications.
+ *
+ * @return Zero on success or an error code from errno.h.
+ *
+ */
+void task_kill_self(bool notify)
+{
+	/*
+	 * User space can subscribe for FAULT events to take action
+	 * whenever a task faults (to take a dump, run a debugger, etc.).
+	 * The notification is always available, but unless udebug is enabled,
+	 * that's all you get.
+	*/
+	if (notify) {
+		if (event_is_subscribed(EVENT_FAULT)) {
+			/* Notify the subscriber that a fault occurred. */
+			event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid),
+			    UPPER32(TASK->taskid), (sysarg_t) THREAD);
+		
+#ifdef CONFIG_UDEBUG
+			/* Wait for a debugging session. */
+			udebug_thread_fault();
+#endif
+		}
+	}
+	
+	irq_spinlock_lock(&tasks_lock, true);
+	task_kill_internal(TASK);
+	irq_spinlock_unlock(&tasks_lock, true);
+	
+	thread_exit();
+}
+
+/** Process syscall to terminate the current task.
+ *
+ * @param notify Send out fault notifications.
+ *
+ */
+sysarg_t sys_task_exit(sysarg_t notify)
+{
+	task_kill_self(notify);
+	
+	/* Unreachable */
 	return EOK;
 }
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/proc/thread.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -239,5 +239,5 @@
  * Switch thread to the ready state.
  *
- * @param t Thread to make ready.
+ * @param thread Thread to make ready.
  *
  */
@@ -246,5 +246,5 @@
 	irq_spinlock_lock(&thread->lock, true);
 	
-	ASSERT(!(thread->state == Ready));
+	ASSERT(thread->state != Ready);
 	
 	int i = (thread->priority < RQ_COUNT - 1)
@@ -350,5 +350,6 @@
 	
 #ifdef CONFIG_UDEBUG
-	/* Init debugging stuff */
+	/* Initialize debugging stuff */
+	thread->btrace = false;
 	udebug_thread_initialize(&thread->udebug);
 #endif
@@ -535,6 +536,6 @@
 /** Detach thread.
  *
- * Mark the thread as detached, if the thread is already in the Lingering
- * state, deallocate its resources.
+ * Mark the thread as detached. If the thread is already
+ * in the Lingering state, deallocate its resources.
  *
  * @param thread Thread to be detached.
@@ -590,24 +591,30 @@
 	order_suffix(thread->kcycles, &kcycles, &ksuffix);
 	
+	char *name;
+	if (str_cmp(thread->name, "uinit") == 0)
+		name = thread->task->name;
+	else
+		name = thread->name;
+	
 #ifdef __32_BITS__
 	if (*additional)
-		printf("%-8" PRIu64" %10p %9" PRIu64 "%c %9" PRIu64 "%c ",
-		    thread->tid, thread->kstack, ucycles, usuffix,
-		    kcycles, ksuffix);
+		printf("%-8" PRIu64 " %10p %10p %9" PRIu64 "%c %9" PRIu64 "%c ",
+		    thread->tid, thread->thread_code, thread->kstack,
+		    ucycles, usuffix, kcycles, ksuffix);
 	else
-		printf("%-8" PRIu64" %-14s %10p %-8s %10p %-5" PRIu32 " %10p\n",
-		    thread->tid, thread->name, thread, thread_states[thread->state],
-		    thread->task, thread->task->context, thread->thread_code);
+		printf("%-8" PRIu64 " %-14s %10p %-8s %10p %-5" PRIu32 "\n",
+		    thread->tid, name, thread, thread_states[thread->state],
+		    thread->task, thread->task->context);
 #endif
 	
 #ifdef __64_BITS__
 	if (*additional)
-		printf("%-8" PRIu64" %18p %18p\n"
+		printf("%-8" PRIu64 " %18p %18p\n"
 		    "         %9" PRIu64 "%c %9" PRIu64 "%c ",
 		    thread->tid, thread->thread_code, thread->kstack,
 		    ucycles, usuffix, kcycles, ksuffix);
 	else
-		printf("%-8" PRIu64" %-14s %18p %-8s %18p %-5" PRIu32 "\n",
-		    thread->tid, thread->name, thread, thread_states[thread->state],
+		printf("%-8" PRIu64 " %-14s %18p %-8s %18p %-5" PRIu32 "\n",
+		    thread->tid, name, thread, thread_states[thread->state],
 		    thread->task, thread->task->context);
 #endif
@@ -647,9 +654,9 @@
 #ifdef __32_BITS__
 	if (additional)
-		printf("[id    ] [stack   ] [ucycles ] [kcycles ] [cpu]"
-		    " [waitqueue]\n");
+		printf("[id    ] [code    ] [stack   ] [ucycles ] [kcycles ]"
+		    " [cpu] [waitqueue]\n");
 	else
 		printf("[id    ] [name        ] [address ] [state ] [task    ]"
-		    " [ctx] [code    ]\n");
+		    " [ctx]\n");
 #endif
 	
@@ -740,5 +747,5 @@
 	ASSERT(interrupts_disabled());
 	ASSERT(irq_spinlock_locked(&threads_lock));
-
+	
 	thread_iterator_t iterator;
 	
@@ -751,4 +758,50 @@
 }
 
+#ifdef CONFIG_UDEBUG
+
+void thread_stack_trace(thread_id_t thread_id)
+{
+	irq_spinlock_lock(&threads_lock, true);
+	
+	thread_t *thread = thread_find_by_id(thread_id);
+	if (thread == NULL) {
+		printf("No such thread.\n");
+		irq_spinlock_unlock(&threads_lock, true);
+		return;
+	}
+	
+	irq_spinlock_lock(&thread->lock, false);
+	
+	/*
+	 * Schedule a stack trace to be printed
+	 * just before the thread is scheduled next.
+	 *
+	 * If the thread is sleeping then try to interrupt
+	 * the sleep. Any request for printing an uspace stack
+	 * trace from within the kernel should be always
+	 * considered a last resort debugging means, therefore
+	 * forcing the thread's sleep to be interrupted
+	 * is probably justifiable.
+	 */
+	
+	bool sleeping = false;
+	istate_t *istate = thread->udebug.uspace_state;
+	if (istate != NULL) {
+		printf("Scheduling thread stack trace.\n");
+		thread->btrace = true;
+		if (thread->state == Sleeping)
+			sleeping = true;
+	} else
+		printf("Thread interrupt state not available.\n");
+	
+	irq_spinlock_unlock(&thread->lock, false);
+	
+	if (sleeping)
+		waitq_interrupt_sleep(thread);
+	
+	irq_spinlock_unlock(&threads_lock, true);
+}
+
+#endif /* CONFIG_UDEBUG */
 
 /** Process syscall to create new thread.
@@ -793,5 +846,4 @@
 				 * has already been created. We need to undo its
 				 * creation now.
-				 *
 				 */
 				
@@ -815,5 +867,4 @@
 		 * THREAD_B events for threads that already existed
 		 * and could be detected with THREAD_READ before.
-		 *
 		 */
 		udebug_thread_b_event_attach(thread, TASK);
Index: kernel/generic/src/synch/waitq.c
===================================================================
--- kernel/generic/src/synch/waitq.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/synch/waitq.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -127,6 +127,10 @@
 /** Interrupt sleeping thread.
  *
- * This routine attempts to interrupt a thread from its sleep in a waitqueue.
- * If the thread is not found sleeping, no action is taken.
+ * This routine attempts to interrupt a thread from its sleep in
+ * a waitqueue. If the thread is not found sleeping, no action
+ * is taken.
+ *
+ * The threads_lock must be already held and interrupts must be
+ * disabled upon calling this function.
  *
  * @param thread Thread to be interrupted.
@@ -138,7 +142,8 @@
 	DEADLOCK_PROBE_INIT(p_wqlock);
 	
-	irq_spinlock_lock(&threads_lock, true);
-	if (!thread_exists(thread))
-		goto out;
+	/*
+	 * The thread is quaranteed to exist because
+	 * threads_lock is held.
+	 */
 	
 grab_locks:
@@ -150,14 +155,13 @@
 			/*
 			 * The sleep cannot be interrupted.
-			 *
 			 */
 			irq_spinlock_unlock(&thread->lock, false);
-			goto out;
+			return;
 		}
 		
 		if (!irq_spinlock_trylock(&wq->lock)) {
+			/* Avoid deadlock */
 			irq_spinlock_unlock(&thread->lock, false);
 			DEADLOCK_PROBE(p_wqlock, DEADLOCK_THRESHOLD);
-			/* Avoid deadlock */
 			goto grab_locks;
 		}
@@ -173,11 +177,9 @@
 		irq_spinlock_unlock(&wq->lock, false);
 	}
+	
 	irq_spinlock_unlock(&thread->lock, false);
 	
 	if (do_wakeup)
 		thread_ready(thread);
-	
-out:
-	irq_spinlock_unlock(&threads_lock, true);
 }
 
@@ -370,5 +372,4 @@
 		 * If the thread was already interrupted,
 		 * don't go to sleep at all.
-		 *
 		 */
 		if (THREAD->interrupted) {
@@ -381,5 +382,4 @@
 		 * Set context that will be restored if the sleep
 		 * of this thread is ever interrupted.
-		 *
 		 */
 		THREAD->sleep_interruptible = true;
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/syscall/syscall.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,4 +41,5 @@
 #include <proc/program.h>
 #include <mm/as.h>
+#include <mm/page.h>
 #include <print.h>
 #include <arch.h>
@@ -86,6 +87,5 @@
 	} else {
 		printf("Task %" PRIu64": Unknown syscall %#" PRIxn, TASK->taskid, id);
-		task_kill(TASK->taskid);
-		thread_exit();
+		task_kill_self(true);
 	}
 	
@@ -131,4 +131,5 @@
 	(syshandler_t) sys_task_set_name,
 	(syshandler_t) sys_task_kill,
+	(syshandler_t) sys_task_exit,
 	(syshandler_t) sys_program_spawn_loader,
 	
@@ -143,4 +144,8 @@
 	(syshandler_t) sys_as_area_change_flags,
 	(syshandler_t) sys_as_area_destroy,
+	(syshandler_t) sys_as_get_unmapped_area,
+	
+	/* Page mapping related syscalls. */
+	(syshandler_t) sys_page_find_mapping,
 	
 	/* IPC related syscalls. */
@@ -156,6 +161,4 @@
 	(syshandler_t) sys_ipc_poke,
 	(syshandler_t) sys_ipc_hangup,
-	(syshandler_t) sys_ipc_register_irq,
-	(syshandler_t) sys_ipc_unregister_irq,
 	(syshandler_t) sys_ipc_connect_kbox,
 	
@@ -171,4 +174,6 @@
 	(syshandler_t) sys_physmem_map,
 	(syshandler_t) sys_iospace_enable,
+	(syshandler_t) sys_register_irq,
+	(syshandler_t) sys_unregister_irq,
 	
 	/* Sysinfo syscalls */
Index: kernel/generic/src/sysinfo/stats.c
===================================================================
--- kernel/generic/src/sysinfo/stats.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/sysinfo/stats.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -160,19 +160,15 @@
 static size_t get_task_virtmem(as_t *as)
 {
-	size_t result = 0;
-
 	/*
-	 * We are holding some spinlocks here and therefore are not allowed to
-	 * block. Only attempt to lock the address space and address space area
-	 * mutexes conditionally. If it is not possible to lock either object,
-	 * allow the statistics to be inexact by skipping the respective object.
-	 *
-	 * Note that it may be infinitely better to let the address space
-	 * management code compute these statistics as it proceeds instead of
-	 * having them calculated here over and over again here.
+	 * We are holding spinlocks here and therefore are not allowed to
+	 * block. Only attempt to lock the address space and address space
+	 * area mutexes conditionally. If it is not possible to lock either
+	 * object, return inexact statistics by skipping the respective object.
 	 */
-
+	
 	if (SYNCH_FAILED(mutex_trylock(&as->lock)))
-		return result * PAGE_SIZE;
+		return 0;
+	
+	size_t pages = 0;
 	
 	/* Walk the B+ tree and count pages */
@@ -189,5 +185,6 @@
 			if (SYNCH_FAILED(mutex_trylock(&area->lock)))
 				continue;
-			result += area->pages;
+			
+			pages += area->pages;
 			mutex_unlock(&area->lock);
 		}
@@ -196,5 +193,50 @@
 	mutex_unlock(&as->lock);
 	
-	return result * PAGE_SIZE;
+	return (pages << PAGE_WIDTH);
+}
+
+/** Get the resident (used) size of a virtual address space
+ *
+ * @param as Address space.
+ *
+ * @return Size of the resident (used) virtual address space (bytes).
+ *
+ */
+static size_t get_task_resmem(as_t *as)
+{
+	/*
+	 * We are holding spinlocks here and therefore are not allowed to
+	 * block. Only attempt to lock the address space and address space
+	 * area mutexes conditionally. If it is not possible to lock either
+	 * object, return inexact statistics by skipping the respective object.
+	 */
+	
+	if (SYNCH_FAILED(mutex_trylock(&as->lock)))
+		return 0;
+	
+	size_t pages = 0;
+	
+	/* Walk the B+ tree and count pages */
+	link_t *cur;
+	for (cur = as->as_area_btree.leaf_head.next;
+	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+		btree_node_t *node =
+		    list_get_instance(cur, btree_node_t, leaf_link);
+		
+		unsigned int i;
+		for (i = 0; i < node->keys; i++) {
+			as_area_t *area = node->value[i];
+			
+			if (SYNCH_FAILED(mutex_trylock(&area->lock)))
+				continue;
+			
+			pages += area->resident;
+			mutex_unlock(&area->lock);
+		}
+	}
+	
+	mutex_unlock(&as->lock);
+	
+	return (pages << PAGE_WIDTH);
 }
 
@@ -215,4 +257,5 @@
 	str_cpy(stats_task->name, TASK_NAME_BUFLEN, task->name);
 	stats_task->virtmem = get_task_virtmem(task->as);
+	stats_task->resmem = get_task_resmem(task->as);
 	stats_task->threads = atomic_get(&task->refcount);
 	task_get_accounting(task, &(stats_task->ucycles),
Index: kernel/generic/src/sysinfo/sysinfo.c
===================================================================
--- kernel/generic/src/sysinfo/sysinfo.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/sysinfo/sysinfo.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,4 +40,5 @@
 #include <arch/asm.h>
 #include <errno.h>
+#include <macros.h>
 
 /** Maximal sysinfo path length */
@@ -761,7 +762,13 @@
  * character must be null).
  *
- * The user space buffer must be sized exactly according
- * to the size of the binary data, otherwise the request
- * fails.
+ * If the user space buffer size does not equal
+ * the actual size of the returned data, the data
+ * is truncated. Whether this is actually a fatal
+ * error or the data can be still interpreted as valid
+ * depends on the nature of the data and has to be
+ * decided by the user space.
+ *
+ * The actual size of data returned is stored to
+ * size_ptr.
  *
  * @param path_ptr    Sysinfo path in the user address space.
@@ -770,4 +777,6 @@
  *                    to store the binary data.
  * @param buffer_size User space buffer size.
+ * @param size_ptr    User space pointer where to store the
+ *                    binary data size.
  *
  * @return Error code (EOK in case of no error).
@@ -775,19 +784,19 @@
  */
 sysarg_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
-    void *buffer_ptr, size_t buffer_size)
+    void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
 {
 	int rc;
 	
 	/* Get the item */
-	sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, false);
-
+	sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size,
+	    false);
+	
 	/* Only constant or generated binary data is considered */
-	if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) {
-		/* Check destination buffer size */
-		if (ret.data.size == buffer_size)
-			rc = copy_to_uspace(buffer_ptr, ret.data.data,
-			    ret.data.size);
-		else
-			rc = ENOMEM;
+	if ((ret.tag == SYSINFO_VAL_DATA) ||
+	    (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) {
+		size_t size = min(ret.data.size, buffer_size);
+		rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
+		if (rc == EOK)
+			rc = copy_to_uspace(size_ptr, &size, sizeof(size));
 	} else
 		rc = EINVAL;
Index: kernel/generic/src/time/clock.c
===================================================================
--- kernel/generic/src/time/clock.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ kernel/generic/src/time/clock.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -93,4 +93,5 @@
 	clock_parea.pbase = (uintptr_t) faddr;
 	clock_parea.frames = 1;
+	clock_parea.unpriv = true;
 	ddi_parea_register(&clock_parea);
 	
@@ -100,5 +101,4 @@
 	 *
 	 */
-	sysinfo_set_item_val("clock.cacheable", NULL, (sysarg_t) true);
 	sysinfo_set_item_val("clock.faddr", NULL, (sysarg_t) faddr);
 }
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -46,5 +46,4 @@
 	app/stats \
 	app/taskdump \
-	app/tasks \
 	app/tester \
 	app/tetris \
@@ -53,4 +52,5 @@
 	app/usbinfo \
 	app/virtusbkbd \
+	app/virtusbhub \
 	app/netecho \
 	app/nettest1 \
@@ -117,7 +117,9 @@
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259 \
-		drv/uhci \
+		drv/uhci-hcd \
+		drv/uhci-rhd \
+		drv/usbhid \
 		drv/usbhub \
-		drv/usbkbd \
+		drv/usbmid \
 		drv/vhc
 endif
@@ -131,7 +133,9 @@
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259 \
-		drv/uhci \
+		drv/uhci-hcd \
+		drv/uhci-rhd \
+		drv/usbhid \
 		drv/usbhub \
-		drv/usbkbd \
+		drv/usbmid \
 		drv/vhc
 endif
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/Makefile.common	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -138,4 +138,11 @@
 endif
 
+ifeq ($(CONFIG_LINE_DEBUG),y)
+	GCC_CFLAGS += -g
+	ICC_CFLAGS += -g
+	SUNCC_CFLAGS += -g
+	CLANG_CFLAGS += -g
+endif
+
 ## Setup platform configuration
 #
@@ -213,2 +220,8 @@
 	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > $@ 2> /dev/null
 	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
+
+##
+# This explicit dependecy of the output binary on the object files seems to be
+# necessary to prevent parallel build failures (GNU make bug #26893 ???).
+$(OUTPUT): $(OBJECTS)
+
Index: uspace/app/bdsh/cmds/modules/cat/cat.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -144,14 +144,14 @@
 			return CMD_SUCCESS;
 		case 'H':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			return CMD_FAILURE;
 		case 't':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			return CMD_FAILURE;
 		case 'b':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			break;
 		case 'm':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			return CMD_FAILURE;
 		}
Index: uspace/app/bdsh/cmds/modules/rm/rm.c
===================================================================
--- uspace/app/bdsh/cmds/modules/rm/rm.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/bdsh/cmds/modules/rm/rm.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -227,5 +227,5 @@
 		}
 		memset(buff, 0, sizeof(buff));
-		snprintf(buff, len, argv[i]);
+		snprintf(buff, len, "%s", argv[i]);
 
 		scope = rm_scope(buff);
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/init/init.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,5 +37,4 @@
 #include <stdio.h>
 #include <unistd.h>
-#include <ipc/ipc.h>
 #include <vfs/vfs.h>
 #include <bool.h>
Index: uspace/app/klog/klog.c
===================================================================
--- uspace/app/klog/klog.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/klog/klog.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,13 +36,12 @@
 
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <async.h>
-#include <ipc/services.h>
 #include <as.h>
-#include <sysinfo.h>
+#include <ddi.h>
 #include <event.h>
 #include <errno.h>
 #include <str_error.h>
 #include <io/klog.h>
+#include <sysinfo.h>
 
 #define NAME       "klog"
@@ -79,29 +78,42 @@
 int main(int argc, char *argv[])
 {
-	size_t klog_pages;
-	if (sysinfo_get_value("klog.pages", &klog_pages) != EOK) {
-		printf("%s: Error getting klog address\n", NAME);
-		return -1;
+	size_t pages;
+	int rc = sysinfo_get_value("klog.pages", &pages);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Unable to get number of klog pages\n",
+		    NAME);
+		return rc;
 	}
 	
-	size_t klog_size = klog_pages * PAGE_SIZE;
-	klog_length = klog_size / sizeof(wchar_t);
-	
-	klog = (wchar_t *) as_get_mappable_page(klog_size);
-	if (klog == NULL) {
-		printf("%s: Error allocating memory area\n", NAME);
-		return -1;
+	uintptr_t faddr;
+	rc = sysinfo_get_value("klog.faddr", &faddr);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Unable to get klog physical address\n",
+		    NAME);
+		return rc;
 	}
 	
-	int res = async_share_in_start_1_0(PHONE_NS, (void *) klog,
-	    klog_size, SERVICE_MEM_KLOG);
-	if (res != EOK) {
-		printf("%s: Error initializing memory area\n", NAME);
-		return -1;
+	size_t size = pages * PAGE_SIZE;
+	klog_length = size / sizeof(wchar_t);
+	
+	klog = (wchar_t *) as_get_mappable_page(size);
+	if (klog == NULL) {
+		fprintf(stderr, "%s: Unable to allocate virtual memory area\n",
+		    NAME);
+		return ENOMEM;
 	}
 	
-	if (event_subscribe(EVENT_KLOG, 0) != EOK) {
-		printf("%s: Error registering klog notifications\n", NAME);
-		return -1;
+	rc = physmem_map((void *) faddr, (void *) klog, pages,
+	    AS_AREA_READ | AS_AREA_CACHEABLE);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Unable to map klog\n", NAME);
+		return rc;
+	}
+	
+	rc = event_subscribe(EVENT_KLOG, 0);
+	if (rc != EOK) {
+		fprintf(stderr, "%s: Unable to register klog notifications\n",
+		    NAME);
+		return rc;
 	}
 	
@@ -109,5 +121,4 @@
 	 * Mode "a" would be definitively much better here, but it is
 	 * not well supported by the FAT driver.
-	 *
 	 */
 	log = fopen(LOG_FNAME, "w");
Index: uspace/app/ping/ping.c
===================================================================
--- uspace/app/ping/ping.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/ping/ping.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,9 +35,9 @@
  */
 
+#include <async.h>
 #include <stdio.h>
 #include <str.h>
 #include <task.h>
 #include <time.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <str_error.h>
@@ -340,5 +340,5 @@
 	    config.dest_str, config.size, config.size);
 	
-	int icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT);
+	int icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
 	if (icmp_phone < 0) {
 		fprintf(stderr, "%s: Unable to connect to ICMP service (%s)\n", NAME,
@@ -355,5 +355,5 @@
 			    str_error(ret));
 			
-			ipc_hangup(icmp_phone);
+			async_hangup(icmp_phone);
 			return ret;
 		}
@@ -370,5 +370,5 @@
 			    str_error(ret));
 			
-			ipc_hangup(icmp_phone);
+			async_hangup(icmp_phone);
 			return ret;
 		}
@@ -390,5 +390,5 @@
 	}
 	
-	ipc_hangup(icmp_phone);
+	async_hangup(icmp_phone);
 	
 	return 0;
Index: uspace/app/stats/stats.c
===================================================================
--- uspace/app/stats/stats.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/stats/stats.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Stanislav Kozina
+ * Copyright (c) 2010 Martin Decky
  * All rights reserved.
  *
@@ -36,10 +37,16 @@
 
 #include <stdio.h>
+#include <task.h>
+#include <thread.h>
 #include <stats.h>
-#include <sys/time.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <malloc.h>
 #include <inttypes.h>
-#include <malloc.h>
-
-#define NAME  "sysstat"
+#include <bool.h>
+#include <str.h>
+#include <arg_parse.h>
+
+#define NAME  "stats"
 
 #define DAY     86400
@@ -47,39 +54,260 @@
 #define MINUTE  60
 
-int main(int argc, char *argv[])
-{
-	struct timeval time;
-	if (gettimeofday(&time, NULL) != 0) {
-		fprintf(stderr, "%s: Cannot get time of day\n", NAME);
-		return -1;
-	}
-	
-	uint64_t sec = time.tv_sec;
-	printf("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64,
-	    (sec % DAY) / HOUR, (sec % HOUR) / MINUTE, sec % MINUTE);
-	
+static void list_tasks(void)
+{
+	size_t count;
+	stats_task_t *stats_tasks = stats_get_tasks(&count);
+	
+	if (stats_tasks == NULL) {
+		fprintf(stderr, "%s: Unable to get tasks\n", NAME);
+		return;
+	}
+	
+	printf("[taskid] [thrds] [resident] [virtual] [ucycles]"
+	    " [kcycles] [name\n");
+	
+	size_t i;
+	for (i = 0; i < count; i++) {
+		uint64_t resmem, virtmem, ucycles, kcycles;
+		char resmem_suffix, virtmem_suffix, usuffix, ksuffix;
+		
+		order_suffix(stats_tasks[i].resmem, &resmem, &resmem_suffix);
+		order_suffix(stats_tasks[i].virtmem, &virtmem, &virtmem_suffix);
+		order_suffix(stats_tasks[i].ucycles, &ucycles, &usuffix);
+		order_suffix(stats_tasks[i].kcycles, &kcycles, &ksuffix);
+		
+		printf("%-8" PRIu64 " %7zu %9" PRIu64 "%c %8" PRIu64 "%c"
+		    " %8" PRIu64 "%c %8" PRIu64 "%c %s\n",
+		    stats_tasks[i].task_id, stats_tasks[i].threads,
+		    resmem, resmem_suffix, virtmem, virtmem_suffix,
+		    ucycles, usuffix, kcycles, ksuffix, stats_tasks[i].name);
+	}
+	
+	free(stats_tasks);
+}
+
+static void list_threads(task_id_t task_id, bool all)
+{
+	size_t count;
+	stats_thread_t *stats_threads = stats_get_threads(&count);
+	
+	if (stats_threads == NULL) {
+		fprintf(stderr, "%s: Unable to get threads\n", NAME);
+		return;
+	}
+	
+	printf("[taskid] [threadid] [state ] [prio] [cpu ] [ucycles] [kcycles]\n");
+	
+	size_t i;
+	for (i = 0; i < count; i++) {
+		if ((all) || (stats_threads[i].task_id == task_id)) {
+			uint64_t ucycles, kcycles;
+			char usuffix, ksuffix;
+			
+			order_suffix(stats_threads[i].ucycles, &ucycles, &usuffix);
+			order_suffix(stats_threads[i].kcycles, &kcycles, &ksuffix);
+			
+			printf("%-8" PRIu64 " %-10" PRIu64 " %-8s %6d ",
+			    stats_threads[i].task_id, stats_threads[i].thread_id,
+			    thread_get_state(stats_threads[i].state),
+			    stats_threads[i].priority);
+			
+			if (stats_threads[i].on_cpu)
+				printf("%6u ", stats_threads[i].cpu);
+			else
+				printf("(none) ");
+			
+			printf("%8" PRIu64"%c %8" PRIu64"%c\n",
+			    ucycles, usuffix, kcycles, ksuffix);
+		}
+	}
+	
+	free(stats_threads);
+}
+
+static void list_cpus(void)
+{
+	size_t count;
+	stats_cpu_t *cpus = stats_get_cpus(&count);
+	
+	if (cpus == NULL) {
+		fprintf(stderr, "%s: Unable to get CPU statistics\n", NAME);
+		return;
+	}
+	
+	printf("[id] [MHz     ] [busy cycles] [idle cycles]\n");
+	
+	size_t i;
+	for (i = 0; i < count; i++) {
+		printf("%-4u ", cpus[i].id);
+		if (cpus[i].active) {
+			uint64_t bcycles, icycles;
+			char bsuffix, isuffix;
+			
+			order_suffix(cpus[i].busy_cycles, &bcycles, &bsuffix);
+			order_suffix(cpus[i].idle_cycles, &icycles, &isuffix);
+			
+			printf("%10" PRIu16 " %12" PRIu64 "%c %12" PRIu64 "%c\n",
+			    cpus[i].frequency_mhz, bcycles, bsuffix,
+			    icycles, isuffix);
+		} else
+			printf("inactive\n");
+	}
+	
+	free(cpus);
+}
+
+static void print_load(void)
+{
+	size_t count;
+	load_t *load = stats_get_load(&count);
+	
+	if (load == NULL) {
+		fprintf(stderr, "%s: Unable to get load\n", NAME);
+		return;
+	}
+	
+	printf("%s: Load average: ", NAME);
+	
+	size_t i;
+	for (i = 0; i < count; i++) {
+		if (i > 0)
+			printf(" ");
+		
+		stats_print_load_fragment(load[i], 2);
+	}
+	
+	printf("\n");
+	
+	free(load);
+}
+
+static void print_uptime(void)
+{
 	sysarg_t uptime = stats_get_uptime();
-	printf(", up %" PRIun " days, %" PRIun " hours, "
-	    "%" PRIun " minutes, %" PRIun " seconds",
+	printf("%s: Up %" PRIun " days, %" PRIun " hours, "
+	    "%" PRIun " minutes, %" PRIun " seconds\n", NAME,
 	    uptime / DAY, (uptime % DAY) / HOUR,
 	    (uptime % HOUR) / MINUTE, uptime % MINUTE);
-	
-	size_t count;
-	load_t *load = stats_get_load(&count);
-	if (load != NULL) {
-		printf(", load average: ");
-		
-		size_t i;
-		for (i = 0; i < count; i++) {
-			if (i > 0)
-				printf(" ");
-			
-			stats_print_load_fragment(load[i], 2);
-		}
-		
-		free(load);
-	}
-	
-	printf("\n");
+}
+
+static void usage(const char *name)
+{
+	printf(
+	    "Usage: %s [-t task_id] [-a] [-c] [-l] [-u]\n" \
+	    "\n" \
+	    "Options:\n" \
+	    "\t-t task_id\n" \
+	    "\t--task=task_id\n" \
+	    "\t\tList threads of the given task\n" \
+	    "\n" \
+	    "\t-a\n" \
+	    "\t--all\n" \
+	    "\t\tList all threads\n" \
+	    "\n" \
+	    "\t-c\n" \
+	    "\t--cpus\n" \
+	    "\t\tList CPUs\n" \
+	    "\n" \
+	    "\t-l\n" \
+	    "\t--load\n" \
+	    "\t\tPrint system load\n" \
+	    "\n" \
+	    "\t-u\n" \
+	    "\t--uptime\n" \
+	    "\t\tPrint system uptime\n" \
+	    "\n" \
+	    "\t-h\n" \
+	    "\t--help\n" \
+	    "\t\tPrint this usage information\n"
+	    "\n" \
+	    "Without any options all tasks are listed\n",
+	    name
+	);
+}
+
+int main(int argc, char *argv[])
+{
+	bool toggle_tasks = true;
+	bool toggle_threads = false;
+	bool toggle_all = false;
+	bool toggle_cpus = false;
+	bool toggle_load = false;
+	bool toggle_uptime = false;
+	
+	task_id_t task_id = 0;
+	
+	int i;
+	for (i = 1; i < argc; i++) {
+		int off;
+		
+		/* Usage */
+		if ((off = arg_parse_short_long(argv[i], "-h", "--help")) != -1) {
+			usage(argv[0]);
+			return 0;
+		}
+		
+		/* All threads */
+		if ((off = arg_parse_short_long(argv[i], "-a", "--all")) != -1) {
+			toggle_tasks = false;
+			toggle_threads = true;
+			toggle_all = true;
+			continue;
+		}
+		
+		/* CPUs */
+		if ((off = arg_parse_short_long(argv[i], "-c", "--cpus")) != -1) {
+			toggle_tasks = false;
+			toggle_cpus = true;
+			continue;
+		}
+		
+		/* Threads */
+		if ((off = arg_parse_short_long(argv[i], "-t", "--task=")) != -1) {
+			// TODO: Support for 64b range
+			int tmp;
+			int ret = arg_parse_int(argc, argv, &i, &tmp, off);
+			if (ret != EOK) {
+				printf("%s: Malformed task_id '%s'\n", NAME, argv[i]);
+				return -1;
+			}
+			
+			task_id = tmp;
+			
+			toggle_tasks = false;
+			toggle_threads = true;
+			continue;
+		}
+		
+		/* Load */
+		if ((off = arg_parse_short_long(argv[i], "-l", "--load")) != -1) {
+			toggle_tasks = false;
+			toggle_load = true;
+			continue;
+		}
+		
+		/* Uptime */
+		if ((off = arg_parse_short_long(argv[i], "-u", "--uptime")) != -1) {
+			toggle_tasks = false;
+			toggle_uptime = true;
+			continue;
+		}
+	}
+	
+	if (toggle_tasks)
+		list_tasks();
+	
+	if (toggle_threads)
+		list_threads(task_id, toggle_all);
+	
+	if (toggle_cpus)
+		list_cpus();
+	
+	if (toggle_load)
+		print_load();
+	
+	if (toggle_uptime)
+		print_uptime();
+	
 	return 0;
 }
Index: uspace/app/taskdump/taskdump.c
===================================================================
--- uspace/app/taskdump/taskdump.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/taskdump/taskdump.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,8 +33,8 @@
  */
 
+#include <async.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <ipc/ipc.h>
 #include <errno.h>
 #include <udebug.h>
@@ -105,5 +105,5 @@
 
 	udebug_end(phoneid);
-	ipc_hangup(phoneid);
+	async_hangup(phoneid);
 
 	return 0;
@@ -114,5 +114,5 @@
 	int rc;
 
-	rc = ipc_connect_kbox(task_id);
+	rc = async_connect_kbox(task_id);
 
 	if (rc == ENOTSUP) {
@@ -126,5 +126,5 @@
 	if (rc < 0) {
 		printf("Error connecting\n");
-		printf("ipc_connect_task(%" PRIu64 ") -> %d ", task_id, rc);
+		printf("async_connect_kbox(%" PRIu64 ") -> %d ", task_id, rc);
 		return rc;
 	}
@@ -406,4 +406,17 @@
 	}
 
+	rc = asprintf(&file_name, "/drv/%s/%s", app_name, app_name);
+	if (rc < 0) {
+		printf("Memory allocation failure.\n");
+		exit(1);
+	}
+
+	rc = symtab_load(file_name, &app_symtab);
+	if (rc == EOK) {
+		printf("Loaded symbol table from %s\n", file_name);
+		free(file_name);
+		return;
+	}
+
 	free(file_name);
 	printf("Failed autoloading symbol table.\n");
Index: pace/app/tasks/Makefile
===================================================================
--- uspace/app/tasks/Makefile	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,36 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# 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.
-#
-
-USPACE_PREFIX = ../..
-BINARY = tasks
-
-SOURCES = \
-	tasks.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/tasks/tasks.c
===================================================================
--- uspace/app/tasks/tasks.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,285 +1,0 @@
-/*
- * Copyright (c) 2010 Stanislav Kozina
- * Copyright (c) 2010 Martin Decky
- * 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 tasks
- * @brief Task lister.
- * @{
- */
-/**
- * @file
- */
-
-#include <stdio.h>
-#include <task.h>
-#include <thread.h>
-#include <stats.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <inttypes.h>
-#include <bool.h>
-#include <str.h>
-#include <arg_parse.h>
-
-#define NAME  "tasks"
-
-#define TASK_COUNT    10
-#define THREAD_COUNT  50
-
-#define PRINT_LOAD1(x)  ((x) >> 11)
-#define PRINT_LOAD2(x)  (((x) & 0x7ff) / 2)
-
-static void list_tasks(void)
-{
-	size_t count;
-	stats_task_t *stats_tasks = stats_get_tasks(&count);
-	
-	if (stats_tasks == NULL) {
-		fprintf(stderr, "%s: Unable to get tasks\n", NAME);
-		return;
-	}
-	
-	printf("      ID  Threads      Mem       uCycles       kCycles   Name\n");
-	
-	size_t i;
-	for (i = 0; i < count; i++) {
-		uint64_t virtmem, ucycles, kcycles;
-		char vmsuffix, usuffix, ksuffix;
-		
-		order_suffix(stats_tasks[i].virtmem, &virtmem, &vmsuffix);
-		order_suffix(stats_tasks[i].ucycles, &ucycles, &usuffix);
-		order_suffix(stats_tasks[i].kcycles, &kcycles, &ksuffix);
-		
-		printf("%8" PRIu64 "%8zu %8" PRIu64 "%c %12"
-		    PRIu64 "%c %12" PRIu64 "%c %s\n", stats_tasks[i].task_id,
-		    stats_tasks[i].threads, virtmem, vmsuffix, ucycles, usuffix,
-		    kcycles, ksuffix, stats_tasks[i].name);
-	}
-	
-	free(stats_tasks);
-}
-
-static void list_threads(task_id_t task_id, bool all)
-{
-	size_t count;
-	stats_thread_t *stats_threads = stats_get_threads(&count);
-	
-	if (stats_threads == NULL) {
-		fprintf(stderr, "%s: Unable to get threads\n", NAME);
-		return;
-	}
-	
-	printf("    ID    State  CPU   Prio    [k]uCycles    [k]kcycles   Cycle fault\n");
-	size_t i;
-	for (i = 0; i < count; i++) {
-		if ((all) || (stats_threads[i].task_id == task_id)) {
-			uint64_t ucycles, kcycles;
-			char usuffix, ksuffix;
-			
-			order_suffix(stats_threads[i].ucycles, &ucycles, &usuffix);
-			order_suffix(stats_threads[i].kcycles, &kcycles, &ksuffix);
-			
-			if (stats_threads[i].on_cpu) {
-				printf("%8" PRIu64 " %-8s %4u %6d %12"
-				    PRIu64"%c %12" PRIu64"%c\n", stats_threads[i].thread_id,
-				    thread_get_state(stats_threads[i].state),
-				    stats_threads[i].cpu, stats_threads[i].priority,
-				    ucycles, usuffix, kcycles, ksuffix);
-			} else {
-				printf("%8" PRIu64 " %-8s ---- %6d %12"
-				    PRIu64"%c %12" PRIu64"%c\n", stats_threads[i].thread_id,
-				    thread_get_state(stats_threads[i].state),
-				    stats_threads[i].priority,
-				    ucycles, usuffix, kcycles, ksuffix);
-			}
-		}
-	}
-	
-	free(stats_threads);
-}
-
-static void print_load(void)
-{
-	size_t count;
-	load_t *load = stats_get_load(&count);
-	
-	if (load == NULL) {
-		fprintf(stderr, "%s: Unable to get load\n", NAME);
-		return;
-	}
-	
-	printf("%s: Load average: ", NAME);
-	
-	size_t i;
-	for (i = 0; i < count; i++) {
-		if (i > 0)
-			printf(" ");
-		
-		stats_print_load_fragment(load[i], 2);
-	}
-	
-	printf("\n");
-	
-	free(load);
-}
-
-static void list_cpus(void)
-{
-	size_t count;
-	stats_cpu_t *cpus = stats_get_cpus(&count);
-	
-	if (cpus == NULL) {
-		fprintf(stderr, "%s: Unable to get CPU statistics\n", NAME);
-		return;
-	}
-	
-	printf("%s: %zu CPU(s) detected\n", NAME, count);
-	
-	size_t i;
-	for (i = 0; i < count; i++) {
-		if (cpus[i].active) {
-			printf("cpu%u: %" PRIu16 " MHz, busy cycles: "
-			    "%" PRIu64 ", idle cycles: %" PRIu64 "\n",
-			    cpus[i].id, cpus[i].frequency_mhz, cpus[i].busy_cycles,
-			    cpus[i].idle_cycles);
-		} else {
-			printf("cpu%u: inactive\n", cpus[i].id);
-		}
-	}
-	
-	free(cpus);
-}
-
-static void usage()
-{
-	printf(
-	    "Usage: tasks [-t task_id] [-a] [-l] [-c]\n" \
-	    "\n" \
-	    "Options:\n" \
-	    "\t-t task_id\n" \
-	    "\t--task=task_id\n" \
-	    "\t\tList threads of the given task\n" \
-	    "\n" \
-	    "\t-a\n" \
-	    "\t--all\n" \
-	    "\t\tList all threads\n" \
-	    "\n" \
-	    "\t-l\n" \
-	    "\t--load\n" \
-	    "\t\tPrint system load\n" \
-	    "\n" \
-	    "\t-c\n" \
-	    "\t--cpu\n" \
-	    "\t\tList CPUs\n" \
-	    "\n" \
-	    "\t-h\n" \
-	    "\t--help\n" \
-	    "\t\tPrint this usage information\n"
-	    "\n" \
-	    "Without any options all tasks are listed\n"
-	);
-}
-
-int main(int argc, char *argv[])
-{
-	bool toggle_tasks = true;
-	bool toggle_threads = false;
-	bool toggle_all = false;
-	bool toggle_load = false;
-	bool toggle_cpus = false;
-	
-	task_id_t task_id = 0;
-	
-	int i;
-	for (i = 1; i < argc; i++) {
-		int off;
-		
-		/* Usage */
-		if ((off = arg_parse_short_long(argv[i], "-h", "--help")) != -1) {
-			usage();
-			return 0;
-		}
-		
-		/* All threads */
-		if ((off = arg_parse_short_long(argv[i], "-a", "--all")) != -1) {
-			toggle_tasks = false;
-			toggle_threads = true;
-			toggle_all = true;
-			continue;
-		}
-		
-		/* Load */
-		if ((off = arg_parse_short_long(argv[i], "-l", "--load")) != -1) {
-			toggle_tasks = false;
-			toggle_load = true;
-			continue;
-		}
-		
-		/* CPUs */
-		if ((off = arg_parse_short_long(argv[i], "-c", "--cpus")) != -1) {
-			toggle_tasks = false;
-			toggle_cpus = true;
-			continue;
-		}
-		
-		/* Threads */
-		if ((off = arg_parse_short_long(argv[i], "-t", "--task=")) != -1) {
-			// TODO: Support for 64b range
-			int tmp;
-			int ret = arg_parse_int(argc, argv, &i, &tmp, off);
-			if (ret != EOK) {
-				printf("%s: Malformed task_id '%s'\n", NAME, argv[i]);
-				return -1;
-			}
-			
-			task_id = tmp;
-			
-			toggle_tasks = false;
-			toggle_threads = true;
-			continue;
-		}
-	}
-	
-	if (toggle_tasks)
-		list_tasks();
-	
-	if (toggle_threads)
-		list_threads(task_id, toggle_all);
-	
-	if (toggle_load)
-		print_load();
-	
-	if (toggle_cpus)
-		list_cpus();
-	
-	return 0;
-}
-
-/** @}
- */
Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/tester/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -53,4 +53,5 @@
 	loop/loop1.c \
 	mm/malloc1.c \
+	mm/mapping1.c \
 	hw/misc/virtchar1.c \
 	hw/serial/serial1.c
Index: uspace/app/tester/adt/usbaddrkeep.c
===================================================================
--- uspace/app/tester/adt/usbaddrkeep.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/tester/adt/usbaddrkeep.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -29,5 +29,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <usb/hcd.h>
+#include <usb/addrkeep.h>
 #include <errno.h>
 #include "../tester.h"
Index: uspace/app/tester/hw/misc/virtchar1.c
===================================================================
--- uspace/app/tester/hw/misc/virtchar1.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/tester/hw/misc/virtchar1.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -47,5 +47,5 @@
 #include "../../tester.h"
 
-#define DEVICE_PATH_NORMAL "/dev/devices/\\virt\\null"
+#define DEVICE_PATH_NORMAL "/dev/devices/\\virt\\null\\a"
 #define DEVICE_PATH_CLASSES "/dev/class/virt-null\\1"
 #define BUFFER_SIZE 64
@@ -89,5 +89,5 @@
 	/* Clean-up. */
 	TPRINTF(" Closing phones and file descriptors\n");
-	ipc_hangup(phone);
+	async_hangup(phone);
 	close(fd);
 	
Index: uspace/app/tester/hw/serial/serial1.c
===================================================================
--- uspace/app/tester/hw/serial/serial1.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/tester/hw/serial/serial1.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
 #include <stdlib.h>
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <sys/types.h>
 #include <async.h>
@@ -75,5 +74,5 @@
 	
 	devman_handle_t handle;
-	res = devman_device_get_handle("/hw/pci0/00:01.0/com1", &handle,
+	res = devman_device_get_handle("/hw/pci0/00:01.0/com1/a", &handle,
 	    IPC_FLAG_BLOCKING);
 	if (res != EOK)
@@ -88,5 +87,5 @@
 	char *buf = (char *) malloc(cnt + 1);
 	if (buf == NULL) {
-		ipc_hangup(phone);
+		async_hangup(phone);
 		devman_hangup_phone(DEVMAN_CLIENT);
 		return "Failed to allocate input buffer";
@@ -98,18 +97,18 @@
 	sysarg_t old_word_size;
 	
-	res = ipc_call_sync_0_4(phone, SERIAL_GET_COM_PROPS, &old_baud,
+	res = async_req_0_4(phone, SERIAL_GET_COM_PROPS, &old_baud,
 	    &old_par, &old_word_size, &old_stop);
 	if (res != EOK) {
 		free(buf);
-		ipc_hangup(phone);
+		async_hangup(phone);
 		devman_hangup_phone(DEVMAN_CLIENT);
 		return "Failed to get old serial communication parameters";
 	}
 	
-	res = ipc_call_sync_4_0(phone, SERIAL_SET_COM_PROPS, 1200,
+	res = async_req_4_0(phone, SERIAL_SET_COM_PROPS, 1200,
 	    SERIAL_NO_PARITY, 8, 1);
 	if (EOK != res) {
 		free(buf);
-		ipc_hangup(phone);
+		async_hangup(phone);
 		devman_hangup_phone(DEVMAN_CLIENT);
 		return "Failed to set serial communication parameters";
@@ -124,8 +123,8 @@
 		
 		if (read < 0) {
-			ipc_call_sync_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
+			async_req_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
 			    old_par, old_word_size, old_stop);
 			free(buf);
-			ipc_hangup(phone);
+			async_hangup(phone);
 			devman_hangup_phone(DEVMAN_CLIENT);
 			return "Failed read from serial device";
@@ -133,8 +132,8 @@
 		
 		if ((size_t) read > cnt - total) {
-			ipc_call_sync_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
+			async_req_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
 			    old_par, old_word_size, old_stop);
 			free(buf);
-			ipc_hangup(phone);
+			async_hangup(phone);
 			devman_hangup_phone(DEVMAN_CLIENT);
 			return "Read more data than expected";
@@ -155,8 +154,8 @@
 			
 			if (written < 0) {
-				ipc_call_sync_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
+				async_req_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
 				    old_par, old_word_size, old_stop);
 				free(buf);
-				ipc_hangup(phone);
+				async_hangup(phone);
 				devman_hangup_phone(DEVMAN_CLIENT);
 				return "Failed write to serial device";
@@ -164,8 +163,8 @@
 			
 			if (written != read) {
-				ipc_call_sync_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
+				async_req_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
 				    old_par, old_word_size, old_stop);
 				free(buf);
-				ipc_hangup(phone);
+				async_hangup(phone);
 				devman_hangup_phone(DEVMAN_CLIENT);
 				return "Written less data than read from serial device";
@@ -183,8 +182,8 @@
 	ssize_t written = char_dev_write(phone, (void *) EOT, eot_size);
 	
-	ipc_call_sync_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
+	async_req_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
 	    old_par, old_word_size, old_stop);
 	free(buf);
-	ipc_hangup(phone);
+	async_hangup(phone);
 	devman_hangup_phone(DEVMAN_CLIENT);
 	
Index: uspace/app/tester/mm/mapping1.c
===================================================================
--- uspace/app/tester/mm/mapping1.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/app/tester/mm/mapping1.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <as.h>
+#include <errno.h>
+#include "../tester.h"
+
+#define BUFFER1_PAGES 4
+#define BUFFER2_PAGES 2
+
+static void *create_as_area(size_t size)
+{
+	void *result = as_get_mappable_page(size);
+	TPRINTF("Creating AS area...\n");
+	if (as_area_create(result, size,
+	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE) != result) {
+		return NULL;
+	}
+	return result;
+}
+
+static void touch_area(void *area, size_t size)
+{
+	TPRINTF("Touching (faulting-in) AS area...\n");
+	
+	char *ptr = (char *)area;
+	
+	while (size > 0) {
+		*ptr = 0;
+		size--;
+		ptr++;
+	}
+}
+
+#define VERIFY_MAPPING(area, page_count, expected_rc) \
+    verify_mapping((area), (page_count), (expected_rc), #expected_rc)
+
+static bool verify_mapping(void *area, int page_count, int expected_rc,
+    const char *expected_rc_str)
+{
+	TPRINTF("Verifying mapping (expected: %s).\n", expected_rc_str);
+	int i;
+	for (i = 0; i < page_count; i++) {
+		void *page_start = ((char *)area) + PAGE_SIZE * i;
+		int rc = as_get_physical_mapping(page_start, NULL);
+		if (rc != expected_rc) {
+			TPRINTF("as_get_physical_mapping() = %d != %d\n",
+			    rc, expected_rc);
+			return false;
+		}
+	}
+	return true;
+}
+
+const char *test_mapping1(void)
+{
+	int rc;
+	
+	size_t buffer1_len = BUFFER1_PAGES * PAGE_SIZE;
+	size_t buffer2_len = BUFFER2_PAGES * PAGE_SIZE;
+	void *buffer1 = create_as_area(buffer1_len);
+	void *buffer2 = create_as_area(buffer2_len);
+	if (!buffer1 || !buffer2) {
+		return "Cannot allocate memory";
+	}
+	
+	touch_area(buffer1, buffer1_len);
+	touch_area(buffer2, buffer2_len);
+	
+	/* Now verify that mapping to physical frames exist. */
+	if (!VERIFY_MAPPING(buffer1, BUFFER1_PAGES, EOK)) {
+		return "Failed to find mapping (buffer1)";
+	}
+	if (!VERIFY_MAPPING(buffer2, BUFFER2_PAGES, EOK)) {
+		return "Failed to find mapping (buffer2)";
+	}
+	
+	/* Let's destroy the buffer1 area and access it again. */
+	rc = as_area_destroy(buffer1);
+	if (rc != EOK) {
+		return "Failed to destroy AS area";
+	}
+	if (!VERIFY_MAPPING(buffer1, BUFFER1_PAGES, ENOENT)) {
+		return "Mapping of destroyed area still exists";
+	}
+	
+	/* clean-up */
+	rc = as_area_destroy(buffer2);
+	if (rc != EOK) {
+		return "Failed to destroy AS area";
+	}
+	
+	return NULL;
+}
Index: uspace/app/tester/mm/mapping1.def
===================================================================
--- uspace/app/tester/mm/mapping1.def	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/app/tester/mm/mapping1.def	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,6 @@
+{
+	"mapping1",
+	"Page mapping test",
+	&test_mapping1,
+	true
+},
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/tester/tester.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -62,4 +62,5 @@
 #include "loop/loop1.def"
 #include "mm/malloc1.def"
+#include "mm/mapping1.def"
 #include "hw/serial/serial1.def"
 #include "adt/usbaddrkeep.def"
Index: uspace/app/tester/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/tester/tester.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,5 +38,4 @@
 #include <sys/types.h>
 #include <bool.h>
-#include <ipc/ipc.h>
 
 #define IPC_TEST_SERVICE  10240
@@ -79,4 +78,5 @@
 extern const char *test_loop1(void);
 extern const char *test_malloc1(void);
+extern const char *test_mapping1(void);
 extern const char *test_serial1(void);
 extern const char *test_usbaddrkeep(void);
Index: uspace/app/tetris/screen.h
===================================================================
--- uspace/app/tetris/screen.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/tetris/screen.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -48,5 +48,4 @@
 
 #include <sys/types.h>
-#include <ipc/ipc.h>
 #include <async.h>
 #include <bool.h>
Index: uspace/app/top/screen.c
===================================================================
--- uspace/app/top/screen.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/top/screen.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,5 +37,4 @@
 
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <io/console.h>
 #include <io/style.h>
@@ -274,6 +273,6 @@
 {
 	screen_style_inverted();
-	printf("[taskid] [threads] [virtual] [%%virt] [%%user]"
-	    " [%%kernel] [name");
+	printf("[taskid] [thrds] [resident] [%%resi] [virtual] [%%virt]"
+	    " [%%user] [%%kern] [name");
 	screen_newline();
 	screen_style_normal();
@@ -295,14 +294,20 @@
 		perc_task_t *perc = data->tasks_perc + data->tasks_map[i];
 		
+		uint64_t resmem;
+		char resmem_suffix;
+		order_suffix(task->resmem, &resmem, &resmem_suffix);
+		
 		uint64_t virtmem;
 		char virtmem_suffix;
 		order_suffix(task->virtmem, &virtmem, &virtmem_suffix);
 		
-		printf("%-8" PRIu64 " %9zu %8" PRIu64 "%c ", task->task_id,
-		    task->threads, virtmem, virtmem_suffix);
+		printf("%-8" PRIu64 " %7zu %9" PRIu64 "%c ",
+		    task->task_id, task->threads, resmem, resmem_suffix);
+		print_percent(perc->resmem, 2);
+		printf(" %8" PRIu64 "%c ", virtmem, virtmem_suffix);
 		print_percent(perc->virtmem, 2);
 		puts(" ");
 		print_percent(perc->ucycles, 2);
-		puts("   ");
+		puts(" ");
 		print_percent(perc->kcycles, 2);
 		puts(" ");
Index: uspace/app/top/top.c
===================================================================
--- uspace/app/top/top.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/top/top.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -195,4 +195,5 @@
 	
 	uint64_t virtmem_total = 0;
+	uint64_t resmem_total = 0;
 	uint64_t ucycles_total = 0;
 	uint64_t kcycles_total = 0;
@@ -223,4 +224,5 @@
 		
 		virtmem_total += new_data->tasks[i].virtmem;
+		resmem_total += new_data->tasks[i].resmem;
 		ucycles_total += new_data->ucycles_diff[i];
 		kcycles_total += new_data->kcycles_diff[i];
@@ -232,4 +234,6 @@
 		FRACTION_TO_FLOAT(new_data->tasks_perc[i].virtmem,
 		    new_data->tasks[i].virtmem * 100, virtmem_total);
+		FRACTION_TO_FLOAT(new_data->tasks_perc[i].resmem,
+		    new_data->tasks[i].resmem * 100, resmem_total);
 		FRACTION_TO_FLOAT(new_data->tasks_perc[i].ucycles,
 		    new_data->ucycles_diff[i] * 100, ucycles_total);
Index: uspace/app/top/top.h
===================================================================
--- uspace/app/top/top.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/top/top.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -77,4 +77,5 @@
 typedef struct {
 	fixed_float virtmem;
+	fixed_float resmem;
 	fixed_float ucycles;
 	fixed_float kcycles;
Index: uspace/app/trace/ipc_desc.c
===================================================================
--- uspace/app/trace/ipc_desc.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/trace/ipc_desc.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,6 +33,6 @@
  */
 
+#include <ipc/common.h>
 #include <stdlib.h>
-#include <ipc/ipc.h>
 #include "ipc_desc.h"
 
Index: uspace/app/trace/ipcp.h
===================================================================
--- uspace/app/trace/ipcp.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/trace/ipcp.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
 #define IPCP_H_
 
-#include <ipc/ipc.h>
 #include "proto.h"
 
Index: uspace/app/trace/proto.c
===================================================================
--- uspace/app/trace/proto.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/trace/proto.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,5 +35,4 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <ipc/ipc.h>
 #include <adt/hash_table.h>
 
Index: uspace/app/trace/proto.h
===================================================================
--- uspace/app/trace/proto.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/trace/proto.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,6 +36,6 @@
 #define PROTO_H_
 
+#include <ipc/common.h>
 #include <adt/hash_table.h>
-#include <ipc/ipc.h>
 #include "trace.h"
 
Index: uspace/app/trace/syscalls.c
===================================================================
--- uspace/app/trace/syscalls.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/trace/syscalls.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -64,6 +64,4 @@
     [SYS_IPC_POKE] = { "ipc_poke",			0,	V_ERRNO },
     [SYS_IPC_HANGUP] = { "ipc_hangup",			1,	V_ERRNO },
-    [SYS_IPC_REGISTER_IRQ] = { "ipc_register_irq",	4,	V_ERRNO },
-    [SYS_IPC_UNREGISTER_IRQ] = { "ipc_unregister_irq",	2,	V_ERRNO },
 
     [SYS_EVENT_SUBSCRIBE] = { "event_subscribe",	2,	V_ERRNO },
@@ -73,9 +71,11 @@
     [SYS_PHYSMEM_MAP] = { "physmem_map",		4,	V_ERRNO },
     [SYS_IOSPACE_ENABLE] = { "iospace_enable",		1,	V_ERRNO },
+    [SYS_REGISTER_IRQ] = { "register_irq",	4,	V_ERRNO },
+    [SYS_UNREGISTER_IRQ] = { "unregister_irq",	2,	V_ERRNO },
 
     [SYS_SYSINFO_GET_TAG] = { "sysinfo_get_tag",		2,	V_INTEGER },
     [SYS_SYSINFO_GET_VALUE] = { "sysinfo_get_value",		3,	V_ERRNO },
     [SYS_SYSINFO_GET_DATA_SIZE] = { "sysinfo_get_data_size",	3,	V_ERRNO },
-    [SYS_SYSINFO_GET_DATA] = { "sysinfo_get_data",		4,	V_ERRNO },
+    [SYS_SYSINFO_GET_DATA] = { "sysinfo_get_data",		5,	V_ERRNO },
 
     [SYS_DEBUG_ENABLE_CONSOLE] = { "debug_enable_console", 0,	V_ERRNO },
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/trace/trace.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
 #include <stdlib.h>
 #include <unistd.h>
-#include <ipc/ipc.h>
 #include <fibril.h>
 #include <errno.h>
@@ -149,5 +148,5 @@
 	int rc;
 
-	rc = ipc_connect_kbox(task_id);
+	rc = async_connect_kbox(task_id);
 
 	if (rc == ENOTSUP) {
@@ -745,5 +744,5 @@
 	abort_trace = true;
 	udebug_end(phoneid);
-	ipc_hangup(phoneid);
+	async_hangup(phoneid);
 
 	ipcp_cleanup();
Index: uspace/app/usbinfo/dump.c
===================================================================
--- uspace/app/usbinfo/dump.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/usbinfo/dump.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,10 +27,10 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbinfo
  * @{
  */
 /**
  * @file
- * @brief USB querying.
+ * USB querying.
  */
 
@@ -43,4 +43,6 @@
 #include <usb/usb.h>
 #include <usb/descriptor.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
 
 #include "usbinfo.h"
@@ -50,22 +52,51 @@
 #define BYTES_PER_LINE 12
 
-#define BCD_INT(a) (((unsigned int)(a)) / 256)
-#define BCD_FRAC(a) (((unsigned int)(a)) % 256)
 
-#define BCD_FMT "%x.%x"
-#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
+const char *get_indent(size_t level)
+{
+	static const char *indents[] = {
+		INDENT,
+		INDENT INDENT,
+		INDENT INDENT INDENT,
+		INDENT INDENT INDENT INDENT,
+		INDENT INDENT INDENT INDENT INDENT
+	};
+	static size_t indents_count = sizeof(indents)/sizeof(indents[0]);
+	if (level >= indents_count) {
+		return indents[indents_count - 1];
+	}
+	return indents[level];
+}
 
-void dump_buffer(const char *msg, const uint8_t *buffer, size_t length)
+void dump_buffer(const char *msg, size_t indent,
+    const uint8_t *buffer, size_t length)
 {
-	printf("%s\n", msg);
+	if (msg != NULL) {
+		printf("%s\n", msg);
+	}
 
 	size_t i;
+	if (length > 0) {
+		printf("%s", get_indent(indent));
+	}
 	for (i = 0; i < length; i++) {
-		printf("  0x%02X", buffer[i]);
+		printf("0x%02X", buffer[i]);
 		if (((i > 0) && (((i+1) % BYTES_PER_LINE) == 0))
 		    || (i + 1 == length)) {
 			printf("\n");
+			if (i + 1 < length) {
+				printf("%s", get_indent(indent));
+			}
+		} else {
+			printf("  ");
 		}
 	}
+}
+
+void dump_usb_descriptor(uint8_t *descriptor, size_t size)
+{
+	printf("Device descriptor:\n");
+	usb_dump_standard_descriptor(stdout, get_indent(0), "\n",
+	    descriptor, size);
 }
 
@@ -83,55 +114,8 @@
 }
 
-void dump_standard_device_descriptor(usb_standard_device_descriptor_t *d)
-{
-	printf("Standard device descriptor:\n");
-
-	printf(INDENT "bLength = %d\n", d->length);
-	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
-	printf(INDENT "bcdUSB = %d (" BCD_FMT ")\n", d->usb_spec_version,
-	    BCD_ARGS(d->usb_spec_version));
-	printf(INDENT "bDeviceClass = 0x%02x\n", d->device_class);
-	printf(INDENT "bDeviceSubClass = 0x%02x\n", d->device_subclass);
-	printf(INDENT "bDeviceProtocol = 0x%02x\n", d->device_protocol);
-	printf(INDENT "bMaxPacketSize0 = %d\n", d->max_packet_size);
-	printf(INDENT "idVendor = %d\n", d->vendor_id);
-	printf(INDENT "idProduct = %d\n", d->product_id);
-	printf(INDENT "bcdDevice = %d\n", d->device_version);
-	printf(INDENT "iManufacturer = %d\n", d->str_manufacturer);
-	printf(INDENT "iProduct = %d\n", d->str_product);
-	printf(INDENT "iSerialNumber = %d\n", d->str_serial_number);
-	printf(INDENT "bNumConfigurations = %d\n", d->configuration_count);
-}
-
-void dump_standard_configuration_descriptor(
-    int index, usb_standard_configuration_descriptor_t *d)
-{
-	bool self_powered = d->attributes & 64;
-	bool remote_wakeup = d->attributes & 32;
-	
-	printf("Standard configuration descriptor #%d\n", index);
-	printf(INDENT "bLength = %d\n", d->length);
-	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
-	printf(INDENT "wTotalLength = %d\n", d->total_length);
-	printf(INDENT "bNumInterfaces = %d\n", d->interface_count);
-	printf(INDENT "bConfigurationValue = %d\n", d->configuration_number);
-	printf(INDENT "iConfiguration = %d\n", d->str_configuration);
-	printf(INDENT "bmAttributes = %d [%s%s%s]\n", d->attributes,
-	    self_powered ? "self-powered" : "",
-	    (self_powered & remote_wakeup) ? ", " : "",
-	    remote_wakeup ? "remote-wakeup" : "");
-	printf(INDENT "MaxPower = %d (%dmA)\n", d->max_power,
-	    2 * d->max_power);
-	// printf(INDENT " = %d\n", d->);
-}
-
 static void dump_tree_descriptor(uint8_t *descriptor, size_t depth)
 {
 	if (descriptor == NULL) {
 		return;
-	}
-	while (depth > 0) {
-		printf("  ");
-		depth--;
 	}
 	int type = (int) *(descriptor + 1);
@@ -151,5 +135,7 @@
 #undef _TYPE
 	}
-	printf("0x%02x (%s)\n", type, name);
+	printf("%s%s (0x%02X):\n", get_indent(depth), name, type);
+	usb_dump_standard_descriptor(stdout, get_indent(depth), "\n",
+	    descriptor, descriptor[0]);
 }
 
@@ -172,5 +158,5 @@
 	uint8_t *ptr = data->data;
 	printf("Descriptor tree:\n");
-	dump_tree_internal(parser, data, ptr, 1);
+	dump_tree_internal(parser, data, ptr, 0);
 }
 
Index: uspace/app/usbinfo/info.c
===================================================================
--- uspace/app/usbinfo/info.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/usbinfo/info.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,19 +27,50 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbinfo
  * @{
  */
 /**
  * @file
- * @brief
+ * Dumping of generic device properties.
  */
 #include <stdio.h>
 #include <str_error.h>
 #include <errno.h>
-#include <usb/usbdrv.h>
+#include <usb/pipes.h>
+#include <usb/recognise.h>
+#include <usb/request.h>
 #include "usbinfo.h"
 
-int dump_device(int hc_phone, usb_address_t address)
+int dump_device(devman_handle_t hc_handle, usb_address_t address)
 {
+	int rc;
+	usb_device_connection_t wire;
+	usb_endpoint_pipe_t ctrl_pipe;
+
+	/*
+	 * Initialize pipes.
+	 */
+	rc = usb_device_connection_initialize(&wire, hc_handle, address);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed to create connection to the device: %s.\n",
+		    str_error(rc));
+		goto leave;
+	}
+	rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe, &wire);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed to create default control pipe: %s.\n",
+		    str_error(rc));
+		goto leave;
+	}
+	rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed to start session on control pipe: %s.\n",
+		    str_error(rc));
+		goto leave;
+	}
+
 	/*
 	 * Dump information about possible match ids.
@@ -47,10 +78,10 @@
 	match_id_list_t match_id_list;
 	init_match_ids(&match_id_list);
-	int rc = usb_drv_create_device_match_ids(hc_phone, &match_id_list, address);
+	rc = usb_device_create_match_ids(&ctrl_pipe, &match_id_list);
 	if (rc != EOK) {
 		fprintf(stderr,
 		    NAME ": failed to fetch match ids of the device: %s.\n",
 		    str_error(rc));
-		return rc;
+		goto leave;
 	}
 	dump_match_ids(&match_id_list);
@@ -60,17 +91,12 @@
 	 */
 	usb_standard_device_descriptor_t device_descriptor;
-	usb_dprintf(NAME, 1,
-	    "usb_drv_req_get_device_descriptor(%d, %d, %p)\n",
-	    hc_phone, (int) address, &device_descriptor);
-
-	rc = usb_drv_req_get_device_descriptor(hc_phone, address,
-	    &device_descriptor);
+	rc = usb_request_get_device_descriptor(&ctrl_pipe, &device_descriptor);
 	if (rc != EOK) {
 		fprintf(stderr,
 		    NAME ": failed to fetch standard device descriptor: %s.\n",
 		    str_error(rc));
-		return rc;
-	}
-	dump_standard_device_descriptor(&device_descriptor);
+		goto leave;
+	}
+	dump_usb_descriptor((uint8_t *)&device_descriptor, sizeof(device_descriptor));
 
 	/*
@@ -79,26 +105,16 @@
 	usb_standard_configuration_descriptor_t config_descriptor;
 	int config_index = 0;
-	usb_dprintf(NAME, 1,
-	    "usb_drv_req_get_bare_configuration_descriptor(%d, %d, %d, %p)\n",
-	    hc_phone, (int) address, config_index, &config_descriptor);
-
-	rc = usb_drv_req_get_bare_configuration_descriptor(hc_phone, address,
-	    config_index, &config_descriptor );
+	rc = usb_request_get_bare_configuration_descriptor(&ctrl_pipe,
+	    config_index, &config_descriptor);
 	if (rc != EOK) {
 		fprintf(stderr,
 		    NAME ": failed to fetch standard configuration descriptor: %s.\n",
 		    str_error(rc));
-		return rc;
-	}
-	dump_standard_configuration_descriptor(config_index,
-	    &config_descriptor);
+		goto leave;
+	}
+	//dump_standard_configuration_descriptor(config_index, &config_descriptor);
 
 	void *full_config_descriptor = malloc(config_descriptor.total_length);
-	usb_dprintf(NAME, 1,
-	    "usb_drv_req_get_full_configuration_descriptor(%d, %d, %d, %p, %zu)\n",
-	    hc_phone, (int) address, config_index,
-	    full_config_descriptor, config_descriptor.total_length);
-
-	rc = usb_drv_req_get_full_configuration_descriptor(hc_phone, address,
+	rc = usb_request_get_full_configuration_descriptor(&ctrl_pipe,
 	    config_index,
 	    full_config_descriptor, config_descriptor.total_length, NULL);
@@ -107,13 +123,76 @@
 		    NAME ": failed to fetch full configuration descriptor: %s.\n",
 		    str_error(rc));
-		return rc;
-	}
-	dump_buffer("Full configuration descriptor:",
-	    full_config_descriptor, config_descriptor.total_length);
+		goto leave;
+	}
 
 	dump_descriptor_tree(full_config_descriptor,
 	    config_descriptor.total_length);
 
-	return EOK;
+	/*
+	 * Get supported languages of STRING descriptors.
+	 */
+	l18_win_locales_t *langs;
+	size_t langs_count;
+	rc = usb_request_get_supported_languages(&ctrl_pipe,
+	    &langs, &langs_count);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed to get list of supported languages: %s.\n",
+		    str_error(rc));
+		goto skip_strings;
+	}
+
+	printf("String languages (%zu):", langs_count);
+	size_t i;
+	for (i = 0; i < langs_count; i++) {
+		printf(" 0x%04x", (int) langs[i]);
+	}
+	printf(".\n");
+
+	/*
+	 * Dump all strings in all available langages;
+	 */
+	for (i = 0; i < langs_count; i++) {
+		l18_win_locales_t lang = langs[i];
+
+		printf("%sStrings for language 0x%04x:\n", get_indent(0),
+		    (int) lang);
+
+		/*
+		 * Try all indexes - we will see what pops-up ;-).
+		 * However, to speed things up, we will stop after
+		 * encountering several broken (or nonexistent ones)
+		 * descriptors in line.
+		 */
+		size_t idx;
+		size_t failed_count = 0;
+		for (idx = 1; idx < 0xFF; idx++) {
+			char *string;
+			rc = usb_request_get_string(&ctrl_pipe, idx, lang,
+			    &string);
+			if (rc != EOK) {
+				failed_count++;
+				if (failed_count > 3) {
+					break;
+				}
+				continue;
+			}
+			printf("%sString #%zu: \"%s\"\n", get_indent(1),
+			    idx, string);
+			free(string);
+			failed_count = 0; /* Reset failed counter. */
+		}
+	}
+
+
+skip_strings:
+
+	rc = EOK;
+
+leave:
+	/* Ignoring errors here. */
+	usb_endpoint_pipe_end_session(&ctrl_pipe);
+
+	return rc;
 }
 
Index: uspace/app/usbinfo/main.c
===================================================================
--- uspace/app/usbinfo/main.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/usbinfo/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,10 +27,10 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbinfo
  * @{
  */
 /**
  * @file
- * @brief USB querying.
+ * USB querying.
  */
 
@@ -43,5 +43,4 @@
 #include <devman.h>
 #include <devmap.h>
-#include <usb/usbdrv.h>
 #include "usbinfo.h"
 
@@ -77,72 +76,36 @@
 }
 
-static int set_new_host_controller(int *phone, const char *path)
+static int get_host_controller_handle(const char *path,
+    devman_handle_t *hc_handle)
 {
 	int rc;
-	int tmp_phone;
 
-	if (path[0] != '/') {
-		int hc_class_index = (int) strtol(path, NULL, 10);
-		char *dev_path;
-		rc = asprintf(&dev_path, "class/usbhc\\%d", hc_class_index);
-		if (rc < 0) {
-			internal_error(rc);
-			return rc;
-		}
-		devmap_handle_t handle;
-		rc = devmap_device_get_handle(dev_path, &handle, 0);
-		if (rc < 0) {
-			fprintf(stderr,
-			    NAME ": failed getting handle of `devman://%s'.\n",
-			    dev_path);
-			free(dev_path);
-			return rc;
-		}
-		tmp_phone = devmap_device_connect(handle, 0);
-		if (tmp_phone < 0) {
-			fprintf(stderr,
-			    NAME ": could not connect to `%s'.\n",
-			    dev_path);
-			free(dev_path);
-			return tmp_phone;
-		}
-		free(dev_path);
-	} else {
-		devman_handle_t handle;
-		rc = devman_device_get_handle(path, &handle, 0);
-		if (rc != EOK) {
-			fprintf(stderr,
-			    NAME ": failed getting handle of `devmap::/%s'.\n",
-			    path);
-			return rc;
-		}
-		tmp_phone = devman_device_connect(handle, 0);
-		if (tmp_phone < 0) {
-			fprintf(stderr,
-			    NAME ": could not connect to `%s'.\n",
-			    path);
-			return tmp_phone;
-		}
+	if (str_cmp(path, "uhci") == 0) {
+		path = "/hw/pci0/00:01.2/uhci";
 	}
 
-	*phone = tmp_phone;
+	devman_handle_t handle;
+	rc = devman_device_get_handle(path, &handle, 0);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed getting handle of `devman::/%s'.\n",
+		    path);
+		return rc;
+	}
+	*hc_handle = handle;
 
 	return EOK;
 }
 
-static int connect_with_address(int hc_phone, const char *str_address)
+static int get_device_address(const char *str_address, usb_address_t *address)
 {
-	usb_address_t address = (usb_address_t) strtol(str_address, NULL, 0);
-	if ((address < 0) || (address >= USB11_ADDRESS_MAX)) {
+	usb_address_t addr = (usb_address_t) strtol(str_address, NULL, 0);
+	if ((addr < 0) || (addr >= USB11_ADDRESS_MAX)) {
 		fprintf(stderr, NAME ": USB address out of range.\n");
 		return ERANGE;
 	}
 
-	if (hc_phone < 0) {
-		fprintf(stderr, NAME ": no active host controller.\n");
-		return ENOENT;
-	}
-
-	return dump_device(hc_phone, address);
+	*address = addr;
+	return EOK;
 }
 
@@ -150,5 +113,6 @@
 int main(int argc, char *argv[])
 {
-	int hc_phone = -1;
+	devman_handle_t hc_handle = (devman_handle_t) -1;
+	usb_address_t device_address = (usb_address_t) -1;
 
 	if (argc <= 1) {
@@ -175,5 +139,6 @@
 			case 'a':
 			case ACTION_DEVICE_ADDRESS: {
-				int rc = connect_with_address(hc_phone, optarg);
+				int rc = get_device_address(optarg,
+				    &device_address);
 				if (rc != EOK) {
 					return rc;
@@ -184,6 +149,6 @@
 			case 't':
 			case ACTION_HOST_CONTROLLER: {
-				int rc = set_new_host_controller(&hc_phone,
-				    optarg);
+				int rc = get_host_controller_handle(optarg,
+				   &hc_handle);
 				if (rc != EOK) {
 					return rc;
@@ -202,4 +167,12 @@
 	} while (i != -1);
 
+	if ((hc_handle == (devman_handle_t) -1)
+	    || (device_address == (usb_address_t) -1)) {
+		fprintf(stderr, NAME ": no target specified.\n");
+		return EINVAL;
+	}
+
+	dump_device(hc_handle, device_address);
+
 	return 0;
 }
Index: uspace/app/usbinfo/usbinfo.h
===================================================================
--- uspace/app/usbinfo/usbinfo.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/usbinfo/usbinfo.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,9 +27,9 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbinfo
  * @{
  */
 /** @file
- * @brief Common header for usbinfo application.
+ * Common header for usbinfo application.
  */
 #ifndef USBINFO_USBINFO_H_
@@ -44,10 +44,9 @@
 #define NAME "usbinfo"
 
-void dump_buffer(const char *, const uint8_t *, size_t);
+void dump_buffer(const char *, size_t, const uint8_t *, size_t);
+const char *get_indent(size_t);
 void dump_match_ids(match_id_list_t *matches);
-void dump_standard_device_descriptor(usb_standard_device_descriptor_t *);
-void dump_standard_configuration_descriptor(int, 
-    usb_standard_configuration_descriptor_t *);
-int dump_device(int, usb_address_t);
+void dump_usb_descriptor(uint8_t *, size_t);
+int dump_device(devman_handle_t, usb_address_t);
 void dump_descriptor_tree(uint8_t *, size_t);
 
Index: uspace/app/virtusbhub/Makefile
===================================================================
--- uspace/app/virtusbhub/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/app/virtusbhub/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2011 Vojtech Horky
+# 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.
+#
+
+USPACE_PREFIX = ../..
+# acronym for virtual USB hub
+# (it is really annoying to write long names)
+BINARY = vuh
+
+LIBS = $(LIBUSB_PREFIX)/libusb.a $(LIBUSBVIRT_PREFIX)/libusbvirt.a
+EXTRA_CFLAGS = -DSTANDALONE_HUB \
+	-DHUB_PORT_COUNT=10 \
+	-I$(LIBUSB_PREFIX)/include -I$(LIBUSBVIRT_PREFIX)/include -I$(LIBDRV_PREFIX)/include
+
+SOURCES = \
+	main.c \
+	$(STOLEN_VHC_SOURCES)
+
+STOLEN_VHC_SOURCES = \
+	vhc_hub/hub.c \
+	vhc_hub/virthub.c \
+	vhc_hub/virthubops.c 
+STOLEN_VHC_HEADERS = \
+	vhc_hub/hub.h \
+	vhc_hub/virthub.h
+
+PRE_DEPEND = $(STOLEN_VHC_SOURCES) $(STOLEN_VHC_HEADERS)
+
+EXTRA_CLEAN = $(STOLEN_VHC_SOURCES) $(STOLEN_VHC_HEADERS)
+
+HUB_IN_VHC = $(USPACE_PREFIX)/drv/vhc/hub
+
+include $(USPACE_PREFIX)/Makefile.common
+
+vhc_hub/%.h: $(HUB_IN_VHC)/%.h
+	ln -sfn ../$(HUB_IN_VHC)/$*.h $@
+vhc_hub/%.c: $(HUB_IN_VHC)/%.c
+	ln -sfn ../$(HUB_IN_VHC)/$*.c $@
Index: uspace/app/virtusbhub/main.c
===================================================================
--- uspace/app/virtusbhub/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/app/virtusbhub/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 usbvirthub
+ * @{
+ */
+/**
+ * @file
+ * @brief Virtual USB hub.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+#include <usb/classes/hub.h>
+#include <usbvirt/device.h>
+#include <usbvirt/hub.h>
+
+#include "vhc_hub/virthub.h"
+
+#define NAME "vuh"
+
+static usbvirt_device_t hub_device;
+
+#define VERBOSE_SLEEP(sec, msg, ...) \
+	do { \
+		char _status[HUB_PORT_COUNT + 2]; \
+		printf(NAME ": doing nothing for %zu seconds...\n", \
+		    (size_t) (sec)); \
+		fibril_sleep((sec)); \
+		virthub_get_status(&hub_device, _status, HUB_PORT_COUNT + 1); \
+		printf(NAME ": " msg " [%s]\n" #__VA_ARGS__, _status); \
+	} while (0)
+
+static void fibril_sleep(size_t sec)
+{
+	while (sec-- > 0) {
+		async_usleep(1000*1000);
+	}
+}
+
+static int dev1 = 1;
+
+int main(int argc, char * argv[])
+{
+	int rc;
+
+	printf(NAME ": virtual USB hub.\n");
+
+	rc = virthub_init(&hub_device);
+	if (rc != EOK) {
+		printf(NAME ": Unable to start communication with VHCD (%s).\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	while (true) {
+		VERBOSE_SLEEP(8, "will pretend device plug-in...");
+		virthub_connect_device(&hub_device, &dev1);
+
+		VERBOSE_SLEEP(8, "will pretend device un-plug...");
+		virthub_disconnect_device(&hub_device, &dev1);
+	}
+
+	usbvirt_disconnect(&hub_device);
+	
+	return 0;
+}
+
+
+/** @}
+ */
Index: uspace/app/virtusbkbd/descriptor.h
===================================================================
--- uspace/app/virtusbkbd/descriptor.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/virtusbkbd/descriptor.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbvirtkbd
  * @{
  */
Index: uspace/app/virtusbkbd/items.h
===================================================================
--- uspace/app/virtusbkbd/items.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/virtusbkbd/items.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbvirtkbd
  * @{
  */
Index: uspace/app/virtusbkbd/kbdconfig.c
===================================================================
--- uspace/app/virtusbkbd/kbdconfig.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/virtusbkbd/kbdconfig.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbvirtkbd
  * @{
  */
@@ -61,5 +61,5 @@
 	.endpoint_count = 1,
 	.interface_class = USB_CLASS_HID,
-	.interface_subclass = 0,
+	.interface_subclass = USB_HID_SUBCLASS_BOOT,
 	.interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
 	.str_interface = 0
Index: uspace/app/virtusbkbd/kbdconfig.h
===================================================================
--- uspace/app/virtusbkbd/kbdconfig.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/virtusbkbd/kbdconfig.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbvirtkbd
  * @{
  */
Index: uspace/app/virtusbkbd/keys.c
===================================================================
--- uspace/app/virtusbkbd/keys.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/virtusbkbd/keys.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbvirtkbd
  * @{
  */
Index: uspace/app/virtusbkbd/keys.h
===================================================================
--- uspace/app/virtusbkbd/keys.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/virtusbkbd/keys.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbvirtkbd
  * @{
  */
@@ -40,5 +40,5 @@
 
 /** Maximum number of keys that can be pressed simultaneously. */
-#define KB_MAX_KEYS_AT_ONCE 4
+#define KB_MAX_KEYS_AT_ONCE 6
 
 /** Key code type. */
Index: uspace/app/virtusbkbd/report.h
===================================================================
--- uspace/app/virtusbkbd/report.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/virtusbkbd/report.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbvirtkbd
  * @{
  */
Index: uspace/app/virtusbkbd/stdreq.c
===================================================================
--- uspace/app/virtusbkbd/stdreq.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/virtusbkbd/stdreq.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbvirtkbd
  * @{
  */
Index: uspace/app/virtusbkbd/stdreq.h
===================================================================
--- uspace/app/virtusbkbd/stdreq.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/virtusbkbd/stdreq.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbvirtkbd
  * @{
  */
Index: uspace/app/virtusbkbd/virtusbkbd.c
===================================================================
--- uspace/app/virtusbkbd/virtusbkbd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/app/virtusbkbd/virtusbkbd.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup usbvirtkbd
  * @{
  */
@@ -271,8 +271,8 @@
 	printf("%s: Simulating keyboard events...\n", NAME);
 	fibril_sleep(10);
-	while (1) {
+	//while (1) {
 		kb_process_events(&status, keyboard_events, keyboard_events_count,
 			on_keyboard_change);
-	}
+	//}
 	
 	printf("%s: Terminating...\n", NAME);
Index: uspace/doc/doxygroups.h
===================================================================
--- uspace/doc/doxygroups.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/doc/doxygroups.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -176,2 +176,76 @@
 	 * @brief Library for creating USB devices drivers.
 	 */
+
+	/**
+	 * @defgroup usbvirt USB virtualization
+	 * @ingroup usb
+	 * @brief Support for virtual USB devices.
+	 */
+
+		/**
+		 * @defgroup libusbvirt USB virtualization library
+		 * @ingroup usbvirt
+		 * @brief Library for creating virtual USB devices.
+		 */
+
+		/**
+		 * @defgroup drvusbvhc Virtual USB host controller
+		 * @ingroup usbvirt
+		 * @brief Driver simulating work of USB host controller.
+		 */
+
+		/**
+		 * @defgroup usbvirthub Virtual USB hub
+		 * @ingroup usbvirt
+		 * @brief Extra virtual USB hub for virtual host controller.
+		 * @details
+		 * Some of the sources are shared with virtual host controller,
+		 * see @ref drvusbvhc for the rest of the files.
+		 */
+
+		/**
+		 * @defgroup usbvirtkbd Virtual USB keybaord
+		 * @ingroup usbvirt
+		 * @brief Virtual USB keyboard for virtual host controller.
+		 */
+
+	/**
+	 * @defgroup usbinfo USB info application
+	 * @ingroup usb
+	 * @brief Application for querying USB devices.
+	 * @details
+	 * The intended usage of this application is to query new USB devices
+	 * for their descriptors etc. to simplify driver writing.
+	 */
+
+	/**
+	 * @defgroup drvusbmid USB multi interface device driver
+	 * @ingroup usb
+	 * @brief USB multi interface device driver
+	 * @details
+	 * This driver serves as a mini hub (or bus) driver for devices
+	 * that have the class defined at interface level (those devices
+	 * usually have several interfaces).
+	 *
+	 * The term multi interface device driver (MID) was borrowed
+	 * Solaris operating system.
+	 */
+
+	/**
+	 * @defgroup drvusbhub USB hub driver
+	 * @ingroup usb
+	 * @brief USB hub driver.
+	 */
+
+	/**
+	 * @defgroup drvusbhid USB HID driver
+	 * @ingroup usb
+	 * @brief USB driver for HID devices.
+	 */
+
+	/**
+	 * @defgroup drvusbuhci UHCI driver
+	 * @ingroup usb
+	 * @brief Driver for USB host controller UHCI.
+	 */
+
Index: uspace/drv/isa/isa.c
===================================================================
--- uspace/drv/isa/isa.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/isa/isa.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -43,4 +44,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <str_error.h>
 #include <ctype.h>
 #include <macros.h>
@@ -50,5 +52,5 @@
 #include <sys/stat.h>
 
-#include <driver.h>
+#include <ddf/driver.h>
 #include <ops/hw_res.h>
 
@@ -58,24 +60,25 @@
 
 #define NAME "isa"
-#define CHILD_DEV_CONF_PATH "/drv/isa/isa.dev"
+#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
+
+/** Obtain soft-state pointer from function node pointer */
+#define ISA_FUN(fnode) ((isa_fun_t *) ((fnode)->driver_data))
 
 #define ISA_MAX_HW_RES 4
 
-typedef struct isa_child_data {
+typedef struct isa_fun {
+	ddf_fun_t *fnode;
 	hw_resource_list_t hw_resources;
-} isa_child_data_t;
-
-static hw_resource_list_t *isa_get_child_resources(device_t *dev)
-{
-	isa_child_data_t *dev_data;
-
-	dev_data = (isa_child_data_t *)dev->driver_data;
-	if (dev_data == NULL)
-		return NULL;
-
-	return &dev_data->hw_resources;
-}
-
-static bool isa_enable_child_interrupt(device_t *dev)
+} isa_fun_t;
+
+static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
+{
+	isa_fun_t *fun = ISA_FUN(fnode);
+	assert(fun != NULL);
+
+	return &fun->hw_resources;
+}
+
+static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
 {
 	// TODO
@@ -84,12 +87,12 @@
 }
 
-static hw_res_ops_t isa_child_hw_res_ops = {
-	&isa_get_child_resources,
-	&isa_enable_child_interrupt
+static hw_res_ops_t isa_fun_hw_res_ops = {
+	&isa_get_fun_resources,
+	&isa_enable_fun_interrupt
 };
 
-static device_ops_t isa_child_dev_ops;
-
-static int isa_add_device(device_t *dev);
+static ddf_dev_ops_t isa_fun_ops;
+
+static int isa_add_device(ddf_dev_t *dev);
 
 /** The isa device driver's standard operations */
@@ -104,33 +107,22 @@
 };
 
-
-static isa_child_data_t *create_isa_child_data() 
-{
-	isa_child_data_t *data;
-
-	data = (isa_child_data_t *) malloc(sizeof(isa_child_data_t));
-	if (data != NULL)
-		memset(data, 0, sizeof(isa_child_data_t));
-
-	return data;
-}
-
-static device_t *create_isa_child_dev()
-{
-	device_t *dev = create_device();
-	if (dev == NULL)
+static isa_fun_t *isa_fun_create(ddf_dev_t *dev, const char *name)
+{
+	isa_fun_t *fun = calloc(1, sizeof(isa_fun_t));
+	if (fun == NULL)
 		return NULL;
 
-	isa_child_data_t *data = create_isa_child_data();
-	if (data == NULL) {
-		delete_device(dev);
+	ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL) {
+		free(fun);
 		return NULL;
 	}
 
-	dev->driver_data = data;
-	return dev;
-}
-
-static char *read_dev_conf(const char *conf_path)
+	fun->fnode = fnode;
+	fnode->driver_data = fun;
+	return fun;
+}
+
+static char *fun_conf_read(const char *conf_path)
 {
 	bool suc = false;
@@ -151,5 +143,5 @@
 	lseek(fd, 0, SEEK_SET);	
 	if (len == 0) {
-		printf(NAME ": read_dev_conf error: configuration file '%s' "
+		printf(NAME ": fun_conf_read error: configuration file '%s' "
 		    "is empty.\n", conf_path);
 		goto cleanup;
@@ -158,10 +150,10 @@
 	buf = malloc(len + 1);
 	if (buf == NULL) {
-		printf(NAME ": read_dev_conf error: memory allocation failed.\n");
+		printf(NAME ": fun_conf_read error: memory allocation failed.\n");
 		goto cleanup;
 	}
 
 	if (0 >= read(fd, buf, len)) {
-		printf(NAME ": read_dev_conf error: unable to read file '%s'.\n",
+		printf(NAME ": fun_conf_read error: unable to read file '%s'.\n",
 		    conf_path);
 		goto cleanup;
@@ -249,10 +241,8 @@
 }
 
-static void isa_child_set_irq(device_t *dev, int irq)
-{
-	isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
-
-	size_t count = data->hw_resources.count;
-	hw_resource_t *resources = data->hw_resources.resources;
+static void isa_fun_set_irq(isa_fun_t *fun, int irq)
+{
+	size_t count = fun->hw_resources.count;
+	hw_resource_t *resources = fun->hw_resources.resources;
 
 	if (count < ISA_MAX_HW_RES) {
@@ -260,16 +250,15 @@
 		resources[count].res.interrupt.irq = irq;
 
-		data->hw_resources.count++;
-
-		printf(NAME ": added irq 0x%x to device %s\n", irq, dev->name);
-	}
-}
-
-static void isa_child_set_io_range(device_t *dev, size_t addr, size_t len)
-{
-	isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
-
-	size_t count = data->hw_resources.count;
-	hw_resource_t *resources = data->hw_resources.resources;
+		fun->hw_resources.count++;
+
+		printf(NAME ": added irq 0x%x to function %s\n", irq,
+		    fun->fnode->name);
+	}
+}
+
+static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
+{
+	size_t count = fun->hw_resources.count;
+	hw_resource_t *resources = fun->hw_resources.resources;
 
 	if (count < ISA_MAX_HW_RES) {
@@ -279,30 +268,30 @@
 		resources[count].res.io_range.endianness = LITTLE_ENDIAN;
 
-		data->hw_resources.count++;
+		fun->hw_resources.count++;
 
 		printf(NAME ": added io range (addr=0x%x, size=0x%x) to "
-		    "device %s\n", (unsigned int) addr, (unsigned int) len,
-		    dev->name);
-	}
-}
-
-static void get_dev_irq(device_t *dev, char *val)
+		    "function %s\n", (unsigned int) addr, (unsigned int) len,
+		    fun->fnode->name);
+	}
+}
+
+static void fun_parse_irq(isa_fun_t *fun, char *val)
 {
 	int irq = 0;
 	char *end = NULL;
 
-	val = skip_spaces(val);	
+	val = skip_spaces(val);
 	irq = (int)strtol(val, &end, 0x10);
 
 	if (val != end)
-		isa_child_set_irq(dev, irq);
-}
-
-static void get_dev_io_range(device_t *dev, char *val)
+		isa_fun_set_irq(fun, irq);
+}
+
+static void fun_parse_io_range(isa_fun_t *fun, char *val)
 {
 	size_t addr, len;
 	char *end = NULL;
 
-	val = skip_spaces(val);	
+	val = skip_spaces(val);
 	addr = strtol(val, &end, 0x10);
 
@@ -310,5 +299,5 @@
 		return;
 
-	val = skip_spaces(end);	
+	val = skip_spaces(end);
 	len = strtol(val, &end, 0x10);
 
@@ -316,5 +305,5 @@
 		return;
 
-	isa_child_set_io_range(dev, addr, len);
+	isa_fun_set_io_range(fun, addr, len);
 }
 
@@ -331,45 +320,38 @@
 }
 
-static void get_dev_match_id(device_t *dev, char *val)
+static void fun_parse_match_id(isa_fun_t *fun, char *val)
 {
 	char *id = NULL;
 	int score = 0;
 	char *end = NULL;
-
-	val = skip_spaces(val);	
+	int rc;
+
+	val = skip_spaces(val);
 
 	score = (int)strtol(val, &end, 10);
 	if (val == end) {
 		printf(NAME " : error - could not read match score for "
-		    "device %s.\n", dev->name);
+		    "function %s.\n", fun->fnode->name);
 		return;
 	}
 
-	match_id_t *match_id = create_match_id();
-	if (match_id == NULL) {
-		printf(NAME " : failed to allocate match id for device %s.\n",
-		    dev->name);
-		return;
-	}
-
-	val = skip_spaces(end);	
+	val = skip_spaces(end);
 	get_match_id(&id, val);
 	if (id == NULL) {
 		printf(NAME " : error - could not read match id for "
-		    "device %s.\n", dev->name);
-		delete_match_id(match_id);
+		    "function %s.\n", fun->fnode->name);
 		return;
 	}
 
-	match_id->id = id;
-	match_id->score = score;
-
-	printf(NAME ": adding match id '%s' with score %d to device %s\n", id,
-	    score, dev->name);
-	add_match_id(&dev->match_ids, match_id);
-}
-
-static bool read_dev_prop(device_t *dev, char *line, const char *prop,
-    void (*read_fn)(device_t *, char *))
+	printf(NAME ": adding match id '%s' with score %d to function %s\n", id,
+	    score, fun->fnode->name);
+
+	rc = ddf_fun_add_match_id(fun->fnode, id, score);
+	if (rc != EOK)
+		printf(NAME ": error adding match ID: %s\n", str_error(rc));
+}
+
+static bool prop_parse(isa_fun_t *fun, char *line, const char *prop,
+    void (*read_fn)(isa_fun_t *, char *))
 {
 	size_t proplen = str_size(prop);
@@ -378,5 +360,5 @@
 		line += proplen;
 		line = skip_spaces(line);
-		(*read_fn)(dev, line);
+		(*read_fn)(fun, line);
 
 		return true;
@@ -386,12 +368,12 @@
 }
 
-static void get_dev_prop(device_t *dev, char *line)
+static void fun_prop_parse(isa_fun_t *fun, char *line)
 {
 	/* Skip leading spaces. */
 	line = skip_spaces(line);
 
-	if (!read_dev_prop(dev, line, "io_range", &get_dev_io_range) &&
-	    !read_dev_prop(dev, line, "irq", &get_dev_irq) &&
-	    !read_dev_prop(dev, line, "match", &get_dev_match_id))
+	if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
+	    !prop_parse(fun, line, "irq", &fun_parse_irq) &&
+	    !prop_parse(fun, line, "match", &fun_parse_match_id))
 	{
 	    printf(NAME " error undefined device property at line '%s'\n",
@@ -400,19 +382,18 @@
 }
 
-static void child_alloc_hw_res(device_t *dev)
-{
-	isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
-	data->hw_resources.resources = 
+static void fun_hw_res_alloc(isa_fun_t *fun)
+{
+	fun->hw_resources.resources = 
 	    (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
 }
 
-static char *read_isa_dev_info(char *dev_conf, device_t *parent)
+static char *isa_fun_read_info(char *fun_conf, ddf_dev_t *dev)
 {
 	char *line;
-	char *dev_name = NULL;
+	char *fun_name = NULL;
 
 	/* Skip empty lines. */
 	while (true) {
-		line = str_get_line(dev_conf, &dev_conf);
+		line = str_get_line(fun_conf, &fun_conf);
 
 		if (line == NULL) {
@@ -426,22 +407,20 @@
 
 	/* Get device name. */
-	dev_name = get_device_name(line);
-	if (dev_name == NULL)
+	fun_name = get_device_name(line);
+	if (fun_name == NULL)
 		return NULL;
 
-	device_t *dev = create_isa_child_dev();
-	if (dev == NULL) {
-		free(dev_name);
+	isa_fun_t *fun = isa_fun_create(dev, fun_name);
+	if (fun == NULL) {
+		free(fun_name);
 		return NULL;
 	}
 
-	dev->name = dev_name;
-
 	/* Allocate buffer for the list of hardware resources of the device. */
-	child_alloc_hw_res(dev);
+	fun_hw_res_alloc(fun);
 
 	/* Get properties of the device (match ids, irq and io range). */
 	while (true) {
-		line = str_get_line(dev_conf, &dev_conf);
+		line = str_get_line(fun_conf, &fun_conf);
 
 		if (line_empty(line)) {
@@ -454,46 +433,58 @@
 		 * and store it in the device structure.
 		 */
-		get_dev_prop(dev, line);
-
-		//printf(NAME ": next line ='%s'\n", dev_conf);
-		//printf(NAME ": current line ='%s'\n", line);
+		fun_prop_parse(fun, line);
 	}
 
 	/* Set device operations to the device. */
-	dev->ops = &isa_child_dev_ops;
-
-	printf(NAME ": child_device_register(dev, parent); device is %s.\n",
-	    dev->name);
-	child_device_register(dev, parent);
-
-	return dev_conf;
-}
-
-static void parse_dev_conf(char *conf, device_t *parent)
+	fun->fnode->ops = &isa_fun_ops;
+
+	printf(NAME ": Binding function %s.\n", fun->fnode->name);
+
+	/* XXX Handle error */
+	(void) ddf_fun_bind(fun->fnode);
+
+	return fun_conf;
+}
+
+static void fun_conf_parse(char *conf, ddf_dev_t *dev)
 {
 	while (conf != NULL && *conf != '\0') {
-		conf = read_isa_dev_info(conf, parent);
-	}
-}
-
-static void add_legacy_children(device_t *parent)
-{
-	char *dev_conf;
-
-	dev_conf = read_dev_conf(CHILD_DEV_CONF_PATH);
-	if (dev_conf != NULL) {
-		parse_dev_conf(dev_conf, parent);
-		free(dev_conf);
-	}
-}
-
-static int isa_add_device(device_t *dev)
+		conf = isa_fun_read_info(conf, dev);
+	}
+}
+
+static void isa_functions_add(ddf_dev_t *dev)
+{
+	char *fun_conf;
+
+	fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
+	if (fun_conf != NULL) {
+		fun_conf_parse(fun_conf, dev);
+		free(fun_conf);
+	}
+}
+
+static int isa_add_device(ddf_dev_t *dev)
 {
 	printf(NAME ": isa_add_device, device handle = %d\n",
 	    (int) dev->handle);
 
-	/* Add child devices. */
-	add_legacy_children(dev);
-	printf(NAME ": finished the enumeration of legacy devices\n");
+	/* Make the bus device more visible. Does not do anything. */
+	printf(NAME ": adding a 'ctl' function\n");
+
+	ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl");
+	if (ctl == NULL) {
+		printf(NAME ": Error creating control function.\n");
+		return EXDEV;
+	}
+
+	if (ddf_fun_bind(ctl) != EOK) {
+		printf(NAME ": Error binding control function.\n");
+		return EXDEV;
+	}
+
+	/* Add functions as specified in the configuration file. */
+	isa_functions_add(dev);
+	printf(NAME ": finished the enumeration of legacy functions\n");
 
 	return EOK;
@@ -502,5 +493,5 @@
 static void isa_init() 
 {
-	isa_child_dev_ops.interfaces[HW_RES_DEV_IFACE] = &isa_child_hw_res_ops;
+	isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
 }
 
@@ -509,5 +500,5 @@
 	printf(NAME ": HelenOS ISA bus driver\n");
 	isa_init();
-	return driver_main(&isa_driver);
+	return ddf_driver_main(&isa_driver);
 }
 
@@ -515,3 +506,2 @@
  * @}
  */
- 
Index: uspace/drv/ns8250/ns8250.c
===================================================================
--- uspace/drv/ns8250/ns8250.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/ns8250/ns8250.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -52,5 +53,6 @@
 #include <libarch/ddi.h>
 
-#include <driver.h>
+#include <ddf/driver.h>
+#include <ddf/interrupt.h>
 #include <ops/char_dev.h>
 
@@ -67,4 +69,10 @@
 #define MAX_BAUD_RATE 115200
 #define DLAB_MASK (1 << 7)
+
+/** Obtain soft-state structure from function node */
+#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
+
+/** Obtain soft-state structure from device node */
+#define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data))
 
 /** The number of bits of one data unit send by the serial port. */
@@ -85,5 +93,9 @@
 
 /** The driver data for the serial port devices. */
-typedef struct ns8250_dev_data {
+typedef struct ns8250 {
+	/** DDF device node */
+	ddf_dev_t *dev;
+	/** DDF function node */
+	ddf_fun_t *fun;
 	/** Is there any client conntected to the device? */
 	bool client_connected;
@@ -98,30 +110,30 @@
 	/** The fibril mutex for synchronizing the access to the device. */
 	fibril_mutex_t mutex;
-} ns8250_dev_data_t;
-
-/** Create driver data for a device.
- *
- * @return		The driver data.
- */
-static ns8250_dev_data_t *create_ns8250_dev_data(void)
-{
-	ns8250_dev_data_t *data;
-	
-	data = (ns8250_dev_data_t *) malloc(sizeof(ns8250_dev_data_t));
-	if (NULL != data) {
-		memset(data, 0, sizeof(ns8250_dev_data_t));
-		fibril_mutex_initialize(&data->mutex);
-	}
-	return data;
-}
-
-/** Delete driver data.
- *
- * @param data		The driver data structure.
- */
-static void delete_ns8250_dev_data(ns8250_dev_data_t *data)
-{
-	if (data != NULL)
-		free(data);
+} ns8250_t;
+
+/** Create per-device soft-state structure.
+ *
+ * @return	Pointer to soft-state structure.
+ */
+static ns8250_t *ns8250_new(void)
+{
+	ns8250_t *ns;
+	
+	ns = (ns8250_t *) calloc(1, sizeof(ns8250_t));
+	if (ns == NULL)
+		return NULL;
+	
+	fibril_mutex_initialize(&ns->mutex);
+	return ns;
+}
+
+/** Delete soft-state structure.
+ *
+ * @param ns	The driver data structure.
+ */
+static void ns8250_delete(ns8250_t *ns)
+{
+	assert(ns != NULL);
+	free(ns);
 }
 
@@ -171,5 +183,5 @@
 /** Read data from the serial port device.
  *
- * @param dev		The serial port device.
+ * @param fun		The serial port function
  * @param buf		The ouput buffer for read data.
  * @param count		The number of bytes to be read.
@@ -178,15 +190,15 @@
  *			error number otherwise.
  */
-static int ns8250_read(device_t *dev, char *buf, size_t count)
-{
+static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count)
+{
+	ns8250_t *ns = NS8250(fun);
 	int ret = EOK;
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	
-	fibril_mutex_lock(&data->mutex);
-	while (!buf_is_empty(&data->input_buffer) && (size_t)ret < count) {
-		buf[ret] = (char)buf_pop_front(&data->input_buffer);
+	
+	fibril_mutex_lock(&ns->mutex);
+	while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
+		buf[ret] = (char)buf_pop_front(&ns->input_buffer);
 		ret++;
 	}
-	fibril_mutex_unlock(&data->mutex);
+	fibril_mutex_unlock(&ns->mutex);
 	
 	return ret;
@@ -195,33 +207,33 @@
 /** Write a character to the serial port.
  *
- * @param data		The serial port device's driver data.
- * @param c		The character to be written.
- */
-static inline void ns8250_putchar(ns8250_dev_data_t *data, uint8_t c)
-{
-	fibril_mutex_lock(&data->mutex);
-	ns8250_write_8(data->port, c);
-	fibril_mutex_unlock(&data->mutex);
+ * @param ns		Serial port device
+ * @param c		The character to be written
+ */
+static inline void ns8250_putchar(ns8250_t *ns, uint8_t c)
+{
+	fibril_mutex_lock(&ns->mutex);
+	ns8250_write_8(ns->port, c);
+	fibril_mutex_unlock(&ns->mutex);
 }
 
 /** Write data to the serial port.
  *
- * @param dev		The serial port device.
- * @param buf		The data to be written.
- * @param count		The number of bytes to be written.
- * @return		Zero on success.
- */
-static int ns8250_write(device_t *dev, char *buf, size_t count) 
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
+ * @param fun		The serial port function
+ * @param buf		The data to be written
+ * @param count		The number of bytes to be written
+ * @return		Zero on success
+ */
+static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
+{
+	ns8250_t *ns = NS8250(fun);
 	size_t idx;
 	
 	for (idx = 0; idx < count; idx++)
-		ns8250_putchar(data, (uint8_t) buf[idx]);
+		ns8250_putchar(ns, (uint8_t) buf[idx]);
 	
 	return 0;
 }
 
-static device_ops_t ns8250_dev_ops;
+static ddf_dev_ops_t ns8250_dev_ops;
 
 /** The character interface's callbacks. */
@@ -231,5 +243,5 @@
 };
 
-static int ns8250_add_device(device_t *dev);
+static int ns8250_add_device(ddf_dev_t *dev);
 
 /** The serial port device driver's standard operations. */
@@ -244,18 +256,13 @@
 };
 
-/** Clean up the serial port device structure.
- *
- * @param dev		The device structure.
- */
-static void ns8250_dev_cleanup(device_t *dev)
-{
-	if (dev->driver_data != NULL) {
-		delete_ns8250_dev_data((ns8250_dev_data_t*) dev->driver_data);
-		dev->driver_data = NULL;
-	}
-	
-	if (dev->parent_phone > 0) {
-		ipc_hangup(dev->parent_phone);
-		dev->parent_phone = 0;
+/** Clean up the serial port soft-state
+ *
+ * @param ns		Serial port device
+ */
+static void ns8250_dev_cleanup(ns8250_t *ns)
+{
+	if (ns->dev->parent_phone > 0) {
+		async_hangup(ns->dev->parent_phone);
+		ns->dev->parent_phone = 0;
 	}
 }
@@ -263,18 +270,16 @@
 /** Enable the i/o ports of the device.
  *
- * @param dev		The serial port device.
- * @return		True on success, false otherwise.
- */
-static bool ns8250_pio_enable(device_t *dev)
-{
-	printf(NAME ": ns8250_pio_enable %s\n", dev->name);
-	
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+ * @param ns		Serial port device
+ * @return		True on success, false otherwise
+ */
+static bool ns8250_pio_enable(ns8250_t *ns)
+{
+	printf(NAME ": ns8250_pio_enable %s\n", ns->dev->name);
 	
 	/* Gain control over port's registers. */
-	if (pio_enable((void *)(uintptr_t) data->io_addr, REG_COUNT,
-	    (void **) &data->port)) {
+	if (pio_enable((void *)(uintptr_t) ns->io_addr, REG_COUNT,
+	    (void **) &ns->port)) {
 		printf(NAME ": error - cannot gain the port %#" PRIx32 " for device "
-		    "%s.\n", data->io_addr, dev->name);
+		    "%s.\n", ns->io_addr, ns->dev->name);
 		return false;
 	}
@@ -285,13 +290,12 @@
 /** Probe the serial port device for its presence.
  *
- * @param dev		The serial port device.
- * @return		True if the device is present, false otherwise.
- */
-static bool ns8250_dev_probe(device_t *dev)
-{
-	printf(NAME ": ns8250_dev_probe %s\n", dev->name);
-	
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	ioport8_t *port_addr = data->port;
+ * @param ns		Serial port device
+ * @return		True if the device is present, false otherwise
+ */
+static bool ns8250_dev_probe(ns8250_t *ns)
+{
+	printf(NAME ": ns8250_dev_probe %s\n", ns->dev->name);
+	
+	ioport8_t *port_addr = ns->port;
 	bool res = true;
 	uint8_t olddata;
@@ -310,5 +314,5 @@
 	
 	if (!res)
-		printf(NAME ": device %s is not present.\n", dev->name);
+		printf(NAME ": device %s is not present.\n", ns->dev->name);
 	
 	return res;
@@ -317,10 +321,10 @@
 /** Initialize serial port device.
  *
- * @param dev		The serial port device.
- * @return		Zero on success, negative error number otherwise.
- */
-static int ns8250_dev_initialize(device_t *dev)
-{
-	printf(NAME ": ns8250_dev_initialize %s\n", dev->name);
+ * @param ns		Serial port device
+ * @return		Zero on success, negative error number otherwise
+ */
+static int ns8250_dev_initialize(ns8250_t *ns)
+{
+	printf(NAME ": ns8250_dev_initialize %s\n", ns->dev->name);
 	
 	int ret = EOK;
@@ -329,25 +333,19 @@
 	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
 	
-	/* Allocate driver data for the device. */
-	ns8250_dev_data_t *data = create_ns8250_dev_data();
-	if (data == NULL)
-		return ENOMEM;
-	dev->driver_data = data;
-	
 	/* Connect to the parent's driver. */
-	dev->parent_phone = devman_parent_device_connect(dev->handle,
+	ns->dev->parent_phone = devman_parent_device_connect(ns->dev->handle,
 	    IPC_FLAG_BLOCKING);
-	if (dev->parent_phone < 0) {
+	if (ns->dev->parent_phone < 0) {
 		printf(NAME ": failed to connect to the parent driver of the "
-		    "device %s.\n", dev->name);
-		ret = dev->parent_phone;
+		    "device %s.\n", ns->dev->name);
+		ret = ns->dev->parent_phone;
 		goto failed;
 	}
 	
 	/* Get hw resources. */
-	ret = hw_res_get_resource_list(dev->parent_phone, &hw_resources);
+	ret = hw_res_get_resource_list(ns->dev->parent_phone, &hw_resources);
 	if (ret != EOK) {
 		printf(NAME ": failed to get hw resources for the device "
-		    "%s.\n", dev->name);
+		    "%s.\n", ns->dev->name);
 		goto failed;
 	}
@@ -362,15 +360,15 @@
 		switch (res->type) {
 		case INTERRUPT:
-			data->irq = res->res.interrupt.irq;
+			ns->irq = res->res.interrupt.irq;
 			irq = true;
 			printf(NAME ": the %s device was asigned irq = 0x%x.\n",
-			    dev->name, data->irq);
+			    ns->dev->name, ns->irq);
 			break;
 			
 		case IO_RANGE:
-			data->io_addr = res->res.io_range.address;
+			ns->io_addr = res->res.io_range.address;
 			if (res->res.io_range.size < REG_COUNT) {
 				printf(NAME ": i/o range assigned to the device "
-				    "%s is too small.\n", dev->name);
+				    "%s is too small.\n", ns->dev->name);
 				ret = ELIMIT;
 				goto failed;
@@ -378,5 +376,5 @@
 			ioport = true;
 			printf(NAME ": the %s device was asigned i/o address = "
-			    "0x%x.\n", dev->name, data->io_addr);
+			    "0x%x.\n", ns->dev->name, ns->io_addr);
 			break;
 			
@@ -388,5 +386,5 @@
 	if (!irq || !ioport) {
 		printf(NAME ": missing hw resource(s) for the device %s.\n",
-		    dev->name);
+		    ns->dev->name);
 		ret = ENOENT;
 		goto failed;
@@ -397,5 +395,5 @@
 	
 failed:
-	ns8250_dev_cleanup(dev);
+	ns8250_dev_cleanup(ns);
 	hw_res_clean_resource_list(&hw_resources);
 	return ret;
@@ -404,10 +402,10 @@
 /** Enable interrupts on the serial port device.
  *
- * Interrupt when data is received.
+ * Interrupt when data is received
  *
  * @param port		The base address of the serial port device's ports.
  */
 static inline void ns8250_port_interrupts_enable(ioport8_t *port)
-{	
+{
 	pio_write_8(port + 1, 0x1);	/* Interrupt when data received. */
 	pio_write_8(port + 4, 0xB);
@@ -416,5 +414,5 @@
 /** Disable interrupts on the serial port device.
  *
- * @param port		The base address of the serial port device's ports.
+ * @param port		The base address of the serial port device's ports
  */
 static inline void ns8250_port_interrupts_disable(ioport8_t *port)
@@ -425,13 +423,11 @@
 /** Enable interrupts for the serial port device.
  *
- * @param dev		The device.
- * @return		Zero on success, negative error number otherwise.
- */
-static int ns8250_interrupt_enable(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	
+ * @param ns		Serial port device
+ * @return		Zero on success, negative error number otherwise
+ */
+static int ns8250_interrupt_enable(ns8250_t *ns)
+{
 	/* Enable interrupt on the serial port. */
-	ns8250_port_interrupts_enable(data->port);
+	ns8250_port_interrupts_enable(ns->port);
 	
 	return EOK;
@@ -618,10 +614,9 @@
  * Set the default parameters of the serial communication.
  *
- * @param dev		The serial port device.
- */
-static void ns8250_initialize_port(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
-	ioport8_t *port = data->port;
+ * @param ns		Serial port device
+ */
+static void ns8250_initialize_port(ns8250_t *ns)
+{
+	ioport8_t *port = ns->port;
 	
 	/* Disable interrupts. */
@@ -643,14 +638,13 @@
  * buffer.
  *
- * @param dev		The serial port device.
- */
-static void ns8250_read_from_device(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	ioport8_t *port = data->port;
+ * @param ns		Serial port device
+ */
+static void ns8250_read_from_device(ns8250_t *ns)
+{
+	ioport8_t *port = ns->port;
 	bool cont = true;
 	
 	while (cont) {
-		fibril_mutex_lock(&data->mutex);
+		fibril_mutex_lock(&ns->mutex);
 		
 		cont = ns8250_received(port);
@@ -658,17 +652,17 @@
 			uint8_t val = ns8250_read_8(port);
 			
-			if (data->client_connected) {
-				if (!buf_push_back(&data->input_buffer, val)) {
+			if (ns->client_connected) {
+				if (!buf_push_back(&ns->input_buffer, val)) {
 					printf(NAME ": buffer overflow on "
-					    "%s.\n", dev->name);
+					    "%s.\n", ns->dev->name);
 				} else {
 					printf(NAME ": the character %c saved "
 					    "to the buffer of %s.\n",
-					    val, dev->name);
+					    val, ns->dev->name);
 				}
 			}
 		}
 		
-		fibril_mutex_unlock(&data->mutex);
+		fibril_mutex_unlock(&ns->mutex);
 		fibril_yield();
 	}
@@ -682,83 +676,107 @@
  * @param dev		The serial port device.
  */
-static inline void ns8250_interrupt_handler(device_t *dev, ipc_callid_t iid,
+static inline void ns8250_interrupt_handler(ddf_dev_t *dev, ipc_callid_t iid,
     ipc_call_t *icall)
 {
-	ns8250_read_from_device(dev);
+	ns8250_read_from_device(NS8250_FROM_DEV(dev));
 }
 
 /** Register the interrupt handler for the device.
  *
+ * @param ns		Serial port device
+ */
+static inline int ns8250_register_interrupt_handler(ns8250_t *ns)
+{
+	return register_interrupt_handler(ns->dev, ns->irq,
+	    ns8250_interrupt_handler, NULL);
+}
+
+/** Unregister the interrupt handler for the device.
+ *
+ * @param ns		Serial port device
+ */
+static inline int ns8250_unregister_interrupt_handler(ns8250_t *ns)
+{
+	return unregister_interrupt_handler(ns->dev, ns->irq);
+}
+
+/** The add_device callback method of the serial port driver.
+ *
+ * Probe and initialize the newly added device.
+ *
  * @param dev		The serial port device.
  */
-static inline int ns8250_register_interrupt_handler(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	
-	return register_interrupt_handler(dev, data->irq,
-	    ns8250_interrupt_handler, NULL);
-}
-
-/** Unregister the interrupt handler for the device.
- *
- * @param dev		The serial port device.
- */
-static inline int ns8250_unregister_interrupt_handler(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	
-	return unregister_interrupt_handler(dev, data->irq);
-}
-
-/** The add_device callback method of the serial port driver.
- *
- * Probe and initialize the newly added device.
- *
- * @param dev		The serial port device.
- */
-static int ns8250_add_device(device_t *dev)
-{
+static int ns8250_add_device(ddf_dev_t *dev)
+{
+	ns8250_t *ns = NULL;
+	ddf_fun_t *fun = NULL;
+	bool need_cleanup = false;
+	int rc;
+	
 	printf(NAME ": ns8250_add_device %s (handle = %d)\n",
 	    dev->name, (int) dev->handle);
 	
-	int res = ns8250_dev_initialize(dev);
-	if (res != EOK)
-		return res;
-	
-	if (!ns8250_pio_enable(dev)) {
-		ns8250_dev_cleanup(dev);
-		return EADDRNOTAVAIL;
+	/* Allocate soft-state for the device */
+	ns = ns8250_new();
+	if (ns == NULL) {
+		rc = ENOMEM;
+		goto fail;
+	}
+	
+	ns->dev = dev;
+	dev->driver_data = ns;
+	
+	rc = ns8250_dev_initialize(ns);
+	if (rc != EOK)
+		goto fail;
+	
+	need_cleanup = true;
+	
+	if (!ns8250_pio_enable(ns)) {
+		rc = EADDRNOTAVAIL;
+		goto fail;
 	}
 	
 	/* Find out whether the device is present. */
-	if (!ns8250_dev_probe(dev)) {
-		ns8250_dev_cleanup(dev);
-		return ENOENT;
+	if (!ns8250_dev_probe(ns)) {
+		rc = ENOENT;
+		goto fail;
 	}
 	
 	/* Serial port initialization (baud rate etc.). */
-	ns8250_initialize_port(dev);
+	ns8250_initialize_port(ns);
 	
 	/* Register interrupt handler. */
-	if (ns8250_register_interrupt_handler(dev) != EOK) {
+	if (ns8250_register_interrupt_handler(ns) != EOK) {
 		printf(NAME ": failed to register interrupt handler.\n");
-		ns8250_dev_cleanup(dev);
-		return res;
+		rc = EADDRNOTAVAIL;
+		goto fail;
 	}
 	
 	/* Enable interrupt. */
-	res = ns8250_interrupt_enable(dev);
-	if (res != EOK) {
+	rc = ns8250_interrupt_enable(ns);
+	if (rc != EOK) {
 		printf(NAME ": failed to enable the interrupt. Error code = "
-		    "%d.\n", res);
-		ns8250_dev_cleanup(dev);
-		ns8250_unregister_interrupt_handler(dev);
-		return res;
+		    "%d.\n", rc);
+		goto fail;
+	}
+	
+	fun = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun == NULL) {
+		printf(NAME ": error creating function.\n");
+		goto fail;
 	}
 	
 	/* Set device operations. */
-	dev->ops = &ns8250_dev_ops;
-	
-	add_device_to_class(dev, "serial");
+	fun->ops = &ns8250_dev_ops;
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function.\n");
+		goto fail;
+	}
+
+	ns->fun = fun;
+	
+	ddf_fun_add_to_class(fun, "serial");
 	
 	printf(NAME ": the %s device has been successfully initialized.\n",
@@ -766,4 +784,12 @@
 	
 	return EOK;
+fail:
+	if (fun != NULL)
+		ddf_fun_destroy(fun);
+	if (need_cleanup)
+		ns8250_dev_cleanup(ns);
+	if (ns != NULL)
+		ns8250_delete(ns);
+	return rc;
 }
 
@@ -775,7 +801,7 @@
  * @param dev		The device.
  */
-static int ns8250_open(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
+static int ns8250_open(ddf_fun_t *fun)
+{
+	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
 	int res;
 	
@@ -788,5 +814,5 @@
 	}
 	fibril_mutex_unlock(&data->mutex);
-
+	
 	return res;
 }
@@ -799,7 +825,7 @@
  * @param dev		The device.
  */
-static void ns8250_close(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
+static void ns8250_close(ddf_fun_t *fun)
+{
+	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
 	
 	fibril_mutex_lock(&data->mutex);
@@ -823,8 +849,8 @@
  */
 static void
-ns8250_get_props(device_t *dev, unsigned int *baud_rate, unsigned int *parity,
+ns8250_get_props(ddf_dev_t *dev, unsigned int *baud_rate, unsigned int *parity,
     unsigned int *word_length, unsigned int* stop_bits)
 {
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
+	ns8250_t *data = (ns8250_t *) dev->driver_data;
 	ioport8_t *port = data->port;
 	
@@ -850,5 +876,5 @@
  * @param stop_bits	The number of stop bits to be used.
  */
-static int ns8250_set_props(device_t *dev, unsigned int baud_rate,
+static int ns8250_set_props(ddf_dev_t *dev, unsigned int baud_rate,
     unsigned int parity, unsigned int word_length, unsigned int stop_bits)
 {
@@ -857,5 +883,5 @@
 	    stop_bits);
 	
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
+	ns8250_t *data = (ns8250_t *) dev->driver_data;
 	ioport8_t *port = data->port;
 	int ret;
@@ -877,5 +903,5 @@
  * Configure the parameters of the serial communication.
  */
-static void ns8250_default_handler(device_t *dev, ipc_callid_t callid,
+static void ns8250_default_handler(ddf_fun_t *fun, ipc_callid_t callid,
     ipc_call_t *call)
 {
@@ -886,7 +912,7 @@
 	switch (method) {
 	case SERIAL_GET_COM_PROPS:
-		ns8250_get_props(dev, &baud_rate, &parity, &word_length,
+		ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
 		    &stop_bits);
-		ipc_answer_4(callid, EOK, baud_rate, parity, word_length,
+		async_answer_4(callid, EOK, baud_rate, parity, word_length,
 		    stop_bits);
 		break;
@@ -897,11 +923,11 @@
 		word_length = IPC_GET_ARG3(*call);
 		stop_bits = IPC_GET_ARG4(*call);
-		ret = ns8250_set_props(dev, baud_rate, parity, word_length,
+		ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length,
 		    stop_bits);
-		ipc_answer_0(callid, ret);
+		async_answer_0(callid, ret);
 		break;
 		
 	default:
-		ipc_answer_0(callid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 	}
 }
@@ -925,5 +951,5 @@
 	printf(NAME ": HelenOS serial port driver\n");
 	ns8250_init();
-	return driver_main(&ns8250_driver);
+	return ddf_driver_main(&ns8250_driver);
 }
 
Index: uspace/drv/pciintel/pci.c
===================================================================
--- uspace/drv/pciintel/pci.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/pciintel/pci.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -44,9 +45,14 @@
 #include <ctype.h>
 #include <macros.h>
-
-#include <driver.h>
+#include <str_error.h>
+
+#include <ddf/driver.h>
 #include <devman.h>
 #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>
@@ -61,35 +67,73 @@
 	((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
 
-static hw_resource_list_t *pciintel_get_child_resources(device_t *dev)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	
-	if (dev_data == NULL)
+/** Obtain PCI function soft-state from DDF function node */
+#define PCI_FUN(fnode) ((pci_fun_t *) (fnode)->driver_data)
+
+/** Obtain PCI bus soft-state from DDF device node */
+#define PCI_BUS(dnode) ((pci_bus_t *) (dnode)->driver_data)
+
+/** Obtain PCI bus soft-state from function soft-state */
+#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
+
+static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
+{
+	pci_fun_t *fun = PCI_FUN(fnode);
+	
+	if (fun == NULL)
 		return NULL;
-	return &dev_data->hw_resources;
-}
-
-static bool pciintel_enable_child_interrupt(device_t *dev)
-{
-	/* TODO */
-	
-	return false;
-}
-
-static hw_res_ops_t pciintel_child_hw_res_ops = {
-	&pciintel_get_child_resources,
-	&pciintel_enable_child_interrupt
+	return &fun->hw_resources;
+}
+
+static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
+{
+	/* This is an old ugly way, copied from ne2000 driver */
+	assert(fnode);
+	pci_fun_t *dev_data = (pci_fun_t *) fnode->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;
+}
+
+static hw_res_ops_t pciintel_hw_res_ops = {
+	&pciintel_get_resources,
+	&pciintel_enable_interrupt
 };
 
-static device_ops_t pci_child_ops;
-
-static int pci_add_device(device_t *);
-
-/** The pci bus driver's standard operations. */
+static ddf_dev_ops_t pci_fun_ops;
+
+static int pci_add_device(ddf_dev_t *);
+
+/** PCI bus driver standard operations */
 static driver_ops_t pci_ops = {
 	.add_device = &pci_add_device
 };
 
-/** The pci bus driver structure. */
+/** PCI bus driver structure */
 static driver_t pci_driver = {
 	.name = NAME,
@@ -97,43 +141,33 @@
 };
 
-typedef struct pciintel_bus_data {
-	uint32_t conf_io_addr;
-	void *conf_data_port;
-	void *conf_addr_port;
-	fibril_mutex_t conf_mutex;
-} pci_bus_data_t;
-
-static pci_bus_data_t *create_pci_bus_data(void)
-{
-	pci_bus_data_t *bus_data;
-	
-	bus_data = (pci_bus_data_t *) malloc(sizeof(pci_bus_data_t));
-	if (bus_data != NULL) {
-		memset(bus_data, 0, sizeof(pci_bus_data_t));
-		fibril_mutex_initialize(&bus_data->conf_mutex);
-	}
-
-	return bus_data;
-}
-
-static void delete_pci_bus_data(pci_bus_data_t *bus_data)
-{
-	free(bus_data);
-}
-
-static void pci_conf_read(device_t *dev, int reg, uint8_t *buf, size_t len)
-{
-	assert(dev->parent != NULL);
-	
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data;
-	
-	fibril_mutex_lock(&bus_data->conf_mutex);
+static pci_bus_t *pci_bus_new(void)
+{
+	pci_bus_t *bus;
+	
+	bus = (pci_bus_t *) calloc(1, sizeof(pci_bus_t));
+	if (bus == NULL)
+		return NULL;
+	
+	fibril_mutex_initialize(&bus->conf_mutex);
+	return bus;
+}
+
+static void pci_bus_delete(pci_bus_t *bus)
+{
+	assert(bus != NULL);
+	free(bus);
+}
+
+static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
+{
+	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	
+	fibril_mutex_lock(&bus->conf_mutex);
 	
 	uint32_t conf_addr;
-	conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg);
-	void *addr = bus_data->conf_data_port + (reg & 3);
-	
-	pio_write_32(bus_data->conf_addr_port, conf_addr);
+	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
+	void *addr = bus->conf_data_port + (reg & 3);
+	
+	pio_write_32(bus->conf_addr_port, conf_addr);
 	
 	switch (len) {
@@ -149,21 +183,18 @@
 	}
 	
-	fibril_mutex_unlock(&bus_data->conf_mutex);
-}
-
-static void pci_conf_write(device_t *dev, int reg, uint8_t *buf, size_t len)
-{
-	assert(dev->parent != NULL);
-	
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data;
-	
-	fibril_mutex_lock(&bus_data->conf_mutex);
+	fibril_mutex_unlock(&bus->conf_mutex);
+}
+
+static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
+{
+	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	
+	fibril_mutex_lock(&bus->conf_mutex);
 	
 	uint32_t conf_addr;
-	conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg);
-	void *addr = bus_data->conf_data_port + (reg & 3);
-	
-	pio_write_32(bus_data->conf_addr_port, conf_addr);
+	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
+	void *addr = bus->conf_data_port + (reg & 3);
+	
+	pio_write_32(bus->conf_addr_port, conf_addr);
 	
 	switch (len) {
@@ -179,66 +210,69 @@
 	}
 	
-	fibril_mutex_unlock(&bus_data->conf_mutex);
-}
-
-uint8_t pci_conf_read_8(device_t *dev, int reg)
+	fibril_mutex_unlock(&bus->conf_mutex);
+}
+
+uint8_t pci_conf_read_8(pci_fun_t *fun, int reg)
 {
 	uint8_t res;
-	pci_conf_read(dev, reg, &res, 1);
+	pci_conf_read(fun, reg, &res, 1);
 	return res;
 }
 
-uint16_t pci_conf_read_16(device_t *dev, int reg)
+uint16_t pci_conf_read_16(pci_fun_t *fun, int reg)
 {
 	uint16_t res;
-	pci_conf_read(dev, reg, (uint8_t *) &res, 2);
+	pci_conf_read(fun, reg, (uint8_t *) &res, 2);
 	return res;
 }
 
-uint32_t pci_conf_read_32(device_t *dev, int reg)
+uint32_t pci_conf_read_32(pci_fun_t *fun, int reg)
 {
 	uint32_t res;
-	pci_conf_read(dev, reg, (uint8_t *) &res, 4);
+	pci_conf_read(fun, reg, (uint8_t *) &res, 4);
 	return res;
 }
 
-void pci_conf_write_8(device_t *dev, int reg, uint8_t val)
-{
-	pci_conf_write(dev, reg, (uint8_t *) &val, 1);
-}
-
-void pci_conf_write_16(device_t *dev, int reg, uint16_t val)
-{
-	pci_conf_write(dev, reg, (uint8_t *) &val, 2);
-}
-
-void pci_conf_write_32(device_t *dev, int reg, uint32_t val)
-{
-	pci_conf_write(dev, reg, (uint8_t *) &val, 4);
-}
-
-void create_pci_match_ids(device_t *dev)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	match_id_t *match_id = NULL;
+void pci_conf_write_8(pci_fun_t *fun, int reg, uint8_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 1);
+}
+
+void pci_conf_write_16(pci_fun_t *fun, int reg, uint16_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 2);
+}
+
+void pci_conf_write_32(pci_fun_t *fun, int reg, uint32_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 4);
+}
+
+void pci_fun_create_match_ids(pci_fun_t *fun)
+{
 	char *match_id_str;
-	
-	match_id = create_match_id();
-	if (match_id != NULL) {
-		asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
-		    dev_data->vendor_id, dev_data->device_id);
-		match_id->id = match_id_str;
-		match_id->score = 90;
-		add_match_id(&dev->match_ids, match_id);
-	}
-
+	int rc;
+	
+	asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
+	    fun->vendor_id, fun->device_id);
+
+	if (match_id_str == NULL) {
+		printf(NAME ": out of memory creating match ID.\n");
+		return;
+	}
+
+	rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90);
+	if (rc != EOK) {
+		printf(NAME ": error adding match ID: %s\n",
+		    str_error(rc));
+	}
+	
 	/* TODO add more ids (with subsys ids, using class id etc.) */
 }
 
-void
-pci_add_range(device_t *dev, uint64_t range_addr, size_t range_size, bool io)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	hw_resource_list_t *hw_res_list = &dev_data->hw_resources;
+void pci_add_range(pci_fun_t *fun, uint64_t range_addr, size_t range_size,
+    bool io)
+{
+	hw_resource_list_t *hw_res_list = &fun->hw_resources;
 	hw_resource_t *hw_resources =  hw_res_list->resources;
 	size_t count = hw_res_list->count;
@@ -265,11 +299,11 @@
  * address add it to the devices hw resource list.
  *
- * @param dev	The pci device.
+ * @param fun	PCI function
  * @param addr	The address of the BAR in the PCI configuration address space of
- *		the device.
- * @return	The addr the address of the BAR which should be read next.
+ *		the device
+ * @return	The addr the address of the BAR which should be read next
  */
-int pci_read_bar(device_t *dev, int addr)
-{	
+int pci_read_bar(pci_fun_t *fun, int addr)
+{
 	/* Value of the BAR */
 	uint32_t val, mask;
@@ -285,10 +319,15 @@
 	
 	/* Get the value of the BAR. */
-	val = pci_conf_read_32(dev, addr);
+	val = pci_conf_read_32(fun, addr);
+
+#define IO_MASK  (~0x3)
+#define MEM_MASK (~0xf)
 	
 	io = (bool) (val & 1);
 	if (io) {
 		addrw64 = false;
+		mask = IO_MASK;
 	} else {
+		mask = MEM_MASK;
 		switch ((val >> 1) & 3) {
 		case 0:
@@ -305,15 +344,15 @@
 	
 	/* Get the address mask. */
-	pci_conf_write_32(dev, addr, 0xffffffff);
-	mask = pci_conf_read_32(dev, addr);
+	pci_conf_write_32(fun, addr, 0xffffffff);
+	mask &= pci_conf_read_32(fun, addr);
 	
 	/* Restore the original value. */
-	pci_conf_write_32(dev, addr, val);
-	val = pci_conf_read_32(dev, addr);
+	pci_conf_write_32(fun, addr, val);
+	val = pci_conf_read_32(fun, addr);
 	
 	range_size = pci_bar_mask_to_size(mask);
 	
 	if (addrw64) {
-		range_addr = ((uint64_t)pci_conf_read_32(dev, addr + 4) << 32) |
+		range_addr = ((uint64_t)pci_conf_read_32(fun, addr + 4) << 32) |
 		    (val & 0xfffffff0);
 	} else {
@@ -322,10 +361,10 @@
 	
 	if (range_addr != 0) {
-		printf(NAME ": device %s : ", dev->name);
+		printf(NAME ": function %s : ", fun->fnode->name);
 		printf("address = %" PRIx64, range_addr);
 		printf(", size = %x\n", (unsigned int) range_size);
 	}
 	
-	pci_add_range(dev, range_addr, range_size, io);
+	pci_add_range(fun, range_addr, range_size, io);
 	
 	if (addrw64)
@@ -335,8 +374,7 @@
 }
 
-void pci_add_interrupt(device_t *dev, int irq)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	hw_resource_list_t *hw_res_list = &dev_data->hw_resources;
+void pci_add_interrupt(pci_fun_t *fun, int irq)
+{
+	hw_resource_list_t *hw_res_list = &fun->hw_resources;
 	hw_resource_t *hw_resources = hw_res_list->resources;
 	size_t count = hw_res_list->count;
@@ -350,40 +388,40 @@
 	hw_res_list->count++;
 	
-	printf(NAME ": device %s uses irq %x.\n", dev->name, irq);
-}
-
-void pci_read_interrupt(device_t *dev)
-{
-	uint8_t irq = pci_conf_read_8(dev, PCI_BRIDGE_INT_LINE);
+	printf(NAME ": function %s uses irq %x.\n", fun->fnode->name, irq);
+}
+
+void pci_read_interrupt(pci_fun_t *fun)
+{
+	uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
 	if (irq != 0xff)
-		pci_add_interrupt(dev, irq);
+		pci_add_interrupt(fun, irq);
 }
 
 /** Enumerate (recursively) and register the devices connected to a pci bus.
  *
- * @param parent	The host-to-pci bridge device.
- * @param bus_num	The bus number.
+ * @param bus		Host-to-PCI bridge
+ * @param bus_num	Bus number
  */
-void pci_bus_scan(device_t *parent, int bus_num) 
-{
-	device_t *dev = create_device();
-	pci_dev_data_t *dev_data = create_pci_dev_data();
-	dev->driver_data = dev_data;
-	dev->parent = parent;
+void pci_bus_scan(pci_bus_t *bus, int bus_num) 
+{
+	ddf_fun_t *fnode;
+	pci_fun_t *fun;
 	
 	int child_bus = 0;
 	int dnum, fnum;
 	bool multi;
-	uint8_t header_type; 
+	uint8_t header_type;
+	
+	fun = pci_fun_new(bus);
 	
 	for (dnum = 0; dnum < 32; dnum++) {
 		multi = true;
 		for (fnum = 0; multi && fnum < 8; fnum++) {
-			init_pci_dev_data(dev_data, bus_num, dnum, fnum);
-			dev_data->vendor_id = pci_conf_read_16(dev,
+			pci_fun_init(fun, bus_num, dnum, fnum);
+			fun->vendor_id = pci_conf_read_16(fun,
 			    PCI_VENDOR_ID);
-			dev_data->device_id = pci_conf_read_16(dev,
+			fun->device_id = pci_conf_read_16(fun,
 			    PCI_DEVICE_ID);
-			if (dev_data->vendor_id == 0xffff) {
+			if (fun->vendor_id == 0xffff) {
 				/*
 				 * The device is not present, go on scanning the
@@ -396,5 +434,5 @@
 			}
 			
-			header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE);
+			header_type = pci_conf_read_8(fun, PCI_HEADER_TYPE);
 			if (fnum == 0) {
 				/* Is the device multifunction? */
@@ -404,22 +442,36 @@
 			header_type = header_type & 0x7F;
 			
-			create_pci_dev_name(dev);
-			
-			pci_alloc_resource_list(dev);
-			pci_read_bars(dev);
-			pci_read_interrupt(dev);
-			
-			dev->ops = &pci_child_ops;
-			
-			printf(NAME ": adding new child device %s.\n",
-			    dev->name);
-			
-			create_pci_match_ids(dev);
-			
-			if (child_device_register(dev, parent) != EOK) {
-				pci_clean_resource_list(dev);
-				clean_match_ids(&dev->match_ids);
-				free((char *) dev->name);
-				dev->name = NULL;
+			char *fun_name = pci_fun_create_name(fun);
+			if (fun_name == NULL) {
+				printf(NAME ": out of memory.\n");
+				return;
+			}
+			
+			fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
+			if (fnode == NULL) {
+				printf(NAME ": error creating function.\n");
+				return;
+			}
+			
+			free(fun_name);
+			fun->fnode = fnode;
+			
+			pci_alloc_resource_list(fun);
+			pci_read_bars(fun);
+			pci_read_interrupt(fun);
+			
+			fnode->ops = &pci_fun_ops;
+			fnode->driver_data = fun;
+			
+			printf(NAME ": adding new function %s.\n",
+			    fnode->name);
+			
+			pci_fun_create_match_ids(fun);
+			
+			if (ddf_fun_bind(fnode) != EOK) {
+				pci_clean_resource_list(fun);
+				clean_match_ids(&fnode->match_ids);
+				free((char *) fnode->name);
+				fnode->name = NULL;
 				continue;
 			}
@@ -427,58 +479,59 @@
 			if (header_type == PCI_HEADER_TYPE_BRIDGE ||
 			    header_type == PCI_HEADER_TYPE_CARDBUS) {
-				child_bus = pci_conf_read_8(dev,
+				child_bus = pci_conf_read_8(fun,
 				    PCI_BRIDGE_SEC_BUS_NUM);
 				printf(NAME ": device is pci-to-pci bridge, "
 				    "secondary bus number = %d.\n", bus_num);
 				if (child_bus > bus_num)
-					pci_bus_scan(parent, child_bus);
+					pci_bus_scan(bus, child_bus);
 			}
 			
-			/* Alloc new aux. dev. structure. */
-			dev = create_device();
-			dev_data = create_pci_dev_data();
-			dev->driver_data = dev_data;
-			dev->parent = parent;
+			fun = pci_fun_new(bus);
 		}
 	}
 	
-	if (dev_data->vendor_id == 0xffff) {
-		delete_device(dev);
-		/* Free the auxiliary device structure. */
-		delete_pci_dev_data(dev_data);
-	}
-}
-
-static int pci_add_device(device_t *dev)
-{
+	if (fun->vendor_id == 0xffff) {
+		/* Free the auxiliary function structure. */
+		pci_fun_delete(fun);
+	}
+}
+
+static int pci_add_device(ddf_dev_t *dnode)
+{
+	pci_bus_t *bus = NULL;
+	ddf_fun_t *ctl = NULL;
+	bool got_res = false;
 	int rc;
-
+	
 	printf(NAME ": pci_add_device\n");
-	
-	pci_bus_data_t *bus_data = create_pci_bus_data();
-	if (bus_data == NULL) {
+	dnode->parent_phone = -1;
+	
+	bus = pci_bus_new();
+	if (bus == NULL) {
 		printf(NAME ": pci_add_device allocation failed.\n");
-		return ENOMEM;
-	}
-	
-	dev->parent_phone = devman_parent_device_connect(dev->handle,
+		rc = ENOMEM;
+		goto fail;
+	}
+	bus->dnode = dnode;
+	dnode->driver_data = bus;
+	
+	dnode->parent_phone = devman_parent_device_connect(dnode->handle,
 	    IPC_FLAG_BLOCKING);
-	if (dev->parent_phone < 0) {
+	if (dnode->parent_phone < 0) {
 		printf(NAME ": pci_add_device failed to connect to the "
 		    "parent's driver.\n");
-		delete_pci_bus_data(bus_data);
-		return dev->parent_phone;
+		rc = dnode->parent_phone;
+		goto fail;
 	}
 	
 	hw_resource_list_t hw_resources;
 	
-	rc = hw_res_get_resource_list(dev->parent_phone, &hw_resources);
+	rc = hw_res_get_resource_list(dnode->parent_phone, &hw_resources);
 	if (rc != EOK) {
 		printf(NAME ": pci_add_device failed to get hw resources for "
 		    "the device.\n");
-		delete_pci_bus_data(bus_data);
-		ipc_hangup(dev->parent_phone);
-		return rc;
-	}	
+		goto fail;
+	}
+	got_res = true;
 	
 	printf(NAME ": conf_addr = %" PRIx64 ".\n",
@@ -489,92 +542,113 @@
 	assert(hw_resources.resources[0].res.io_range.size == 8);
 	
-	bus_data->conf_io_addr =
+	bus->conf_io_addr =
 	    (uint32_t) hw_resources.resources[0].res.io_range.address;
 	
-	if (pio_enable((void *)(uintptr_t)bus_data->conf_io_addr, 8,
-	    &bus_data->conf_addr_port)) {
+	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 8,
+	    &bus->conf_addr_port)) {
 		printf(NAME ": failed to enable configuration ports.\n");
-		delete_pci_bus_data(bus_data);
-		ipc_hangup(dev->parent_phone);
+		rc = EADDRNOTAVAIL;
+		goto fail;
+	}
+	bus->conf_data_port = (char *) bus->conf_addr_port + 4;
+	
+	/* Make the bus device more visible. It has no use yet. */
+	printf(NAME ": adding a 'ctl' function\n");
+	
+	ctl = ddf_fun_create(bus->dnode, fun_exposed, "ctl");
+	if (ctl == NULL) {
+		printf(NAME ": error creating control function.\n");
+		rc = ENOMEM;
+		goto fail;
+	}
+	
+	rc = ddf_fun_bind(ctl);
+	if (rc != EOK) {
+		printf(NAME ": error binding control function.\n");
+		goto fail;
+	}
+	
+	/* Enumerate functions. */
+	printf(NAME ": scanning the bus\n");
+	pci_bus_scan(bus, 0);
+	
+	hw_res_clean_resource_list(&hw_resources);
+	
+	return EOK;
+	
+fail:
+	if (bus != NULL)
+		pci_bus_delete(bus);
+	if (dnode->parent_phone >= 0)
+		async_hangup(dnode->parent_phone);
+	if (got_res)
 		hw_res_clean_resource_list(&hw_resources);
-		return EADDRNOTAVAIL;
-	}
-	bus_data->conf_data_port = (char *) bus_data->conf_addr_port + 4;
-	
-	dev->driver_data = bus_data;
-	
-	/* Enumerate child devices. */
-	printf(NAME ": scanning the bus\n");
-	pci_bus_scan(dev, 0);
-	
-	hw_res_clean_resource_list(&hw_resources);
-	
-	return EOK;
+	if (ctl != NULL)
+		ddf_fun_destroy(ctl);
+
+	return rc;
 }
 
 static void pciintel_init(void)
 {
-	pci_child_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_child_hw_res_ops;
-}
-
-pci_dev_data_t *create_pci_dev_data(void)
-{
-	pci_dev_data_t *res = (pci_dev_data_t *) malloc(sizeof(pci_dev_data_t));
-	
-	if (res != NULL)
-		memset(res, 0, sizeof(pci_dev_data_t));
-	return res;
-}
-
-void init_pci_dev_data(pci_dev_data_t *dev_data, int bus, int dev, int fn)
-{
-	dev_data->bus = bus;
-	dev_data->dev = dev;
-	dev_data->fn = fn;
-}
-
-void delete_pci_dev_data(pci_dev_data_t *dev_data)
-{
-	if (dev_data != NULL) {
-		hw_res_clean_resource_list(&dev_data->hw_resources);
-		free(dev_data);
-	}
-}
-
-void create_pci_dev_name(device_t *dev)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
+	pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
+}
+
+pci_fun_t *pci_fun_new(pci_bus_t *bus)
+{
+	pci_fun_t *fun;
+	
+	fun = (pci_fun_t *) calloc(1, sizeof(pci_fun_t));
+	if (fun == NULL)
+		return NULL;
+
+	fun->busptr = bus;
+	return fun;
+}
+
+void pci_fun_init(pci_fun_t *fun, int bus, int dev, int fn)
+{
+	fun->bus = bus;
+	fun->dev = dev;
+	fun->fn = fn;
+}
+
+void pci_fun_delete(pci_fun_t *fun)
+{
+	assert(fun != NULL);
+	hw_res_clean_resource_list(&fun->hw_resources);
+	free(fun);
+}
+
+char *pci_fun_create_name(pci_fun_t *fun)
+{
 	char *name = NULL;
 	
-	asprintf(&name, "%02x:%02x.%01x", dev_data->bus, dev_data->dev,
-	    dev_data->fn);
-	dev->name = name;
-}
-
-bool pci_alloc_resource_list(device_t *dev)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
-	
-	dev_data->hw_resources.resources =
+	asprintf(&name, "%02x:%02x.%01x", fun->bus, fun->dev,
+	    fun->fn);
+	return name;
+}
+
+bool pci_alloc_resource_list(pci_fun_t *fun)
+{
+	fun->hw_resources.resources =
 	    (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
-	return dev_data->hw_resources.resources != NULL;
-}
-
-void pci_clean_resource_list(device_t *dev)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	
-	if (dev_data->hw_resources.resources != NULL) {
-		free(dev_data->hw_resources.resources);
-		dev_data->hw_resources.resources = NULL;
-	}
-}
-
-/** Read the base address registers (BARs) of the device and adds the addresses
- * to its hw resource list.
+	return fun->hw_resources.resources != NULL;
+}
+
+void pci_clean_resource_list(pci_fun_t *fun)
+{
+	if (fun->hw_resources.resources != NULL) {
+		free(fun->hw_resources.resources);
+		fun->hw_resources.resources = NULL;
+	}
+}
+
+/** Read the base address registers (BARs) of the function and add the addresses
+ * to its HW resource list.
  *
- * @param dev the pci device.
+ * @param fun	PCI function
  */
-void pci_read_bars(device_t *dev)
+void pci_read_bars(pci_fun_t *fun)
 {
 	/*
@@ -585,10 +659,11 @@
 	
 	while (addr <= PCI_BASE_ADDR_5)
-		addr = pci_read_bar(dev, addr);
+		addr = pci_read_bar(fun, addr);
 }
 
 size_t pci_bar_mask_to_size(uint32_t mask)
 {
-	return ((mask & 0xfffffff0) ^ 0xffffffff) + 1;
+	size_t size = mask & ~(mask - 1);
+	return size;
 }
 
@@ -597,5 +672,5 @@
 	printf(NAME ": HelenOS pci bus driver (intel method 1).\n");
 	pciintel_init();
-	return driver_main(&pci_driver);
+	return ddf_driver_main(&pci_driver);
 }
 
Index: uspace/drv/pciintel/pci.h
===================================================================
--- uspace/drv/pciintel/pci.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/pciintel/pci.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,13 +37,22 @@
 #define PCI_H_
 
-#include <stdlib.h>
-#include <driver.h>
-#include <malloc.h>
-
+#include <ddf/driver.h>
 #include "pci_regs.h"
 
 #define PCI_MAX_HW_RES 8
 
-typedef struct pci_dev_data {
+typedef struct pciintel_bus {
+	/** DDF device node */
+	ddf_dev_t *dnode;
+	uint32_t conf_io_addr;
+	void *conf_data_port;
+	void *conf_addr_port;
+	fibril_mutex_t conf_mutex;
+} pci_bus_t;
+
+typedef struct pci_fun_data {
+	pci_bus_t *busptr;
+	ddf_fun_t *fnode;
+
 	int bus;
 	int dev;
@@ -51,31 +61,31 @@
 	int device_id;
 	hw_resource_list_t hw_resources;
-} pci_dev_data_t;
+} pci_fun_t;
 
-extern void create_pci_match_ids(device_t *);
+extern void pci_fun_create_match_ids(pci_fun_t *);
 
-extern uint8_t pci_conf_read_8(device_t *, int);
-extern uint16_t pci_conf_read_16(device_t *, int);
-extern uint32_t pci_conf_read_32(device_t *, int);
-extern void pci_conf_write_8(device_t *, int, uint8_t);
-extern void pci_conf_write_16(device_t *, int, uint16_t);
-extern void pci_conf_write_32(device_t *, int, uint32_t);
+extern uint8_t pci_conf_read_8(pci_fun_t *, int);
+extern uint16_t pci_conf_read_16(pci_fun_t *, int);
+extern uint32_t pci_conf_read_32(pci_fun_t *, int);
+extern void pci_conf_write_8(pci_fun_t *, int, uint8_t);
+extern void pci_conf_write_16(pci_fun_t *, int, uint16_t);
+extern void pci_conf_write_32(pci_fun_t *, int, uint32_t);
 
-extern void pci_add_range(device_t *, uint64_t, size_t, bool);
-extern int pci_read_bar(device_t *, int);
-extern void pci_read_interrupt(device_t *);
-extern void pci_add_interrupt(device_t *, int);
+extern void pci_add_range(pci_fun_t *, uint64_t, size_t, bool);
+extern int pci_read_bar(pci_fun_t *, int);
+extern void pci_read_interrupt(pci_fun_t *);
+extern void pci_add_interrupt(pci_fun_t *, int);
 
-extern void pci_bus_scan(device_t *, int);
+extern pci_fun_t *pci_fun_new(pci_bus_t *);
+extern void pci_fun_init(pci_fun_t *, int, int, int);
+extern void pci_fun_delete(pci_fun_t *);
+extern char *pci_fun_create_name(pci_fun_t *);
 
-extern pci_dev_data_t *create_pci_dev_data(void);
-extern void init_pci_dev_data(pci_dev_data_t *, int, int, int);
-extern void delete_pci_dev_data(pci_dev_data_t *);
-extern void create_pci_dev_name(device_t *);
+extern void pci_bus_scan(pci_bus_t *, int);
 
-extern bool pci_alloc_resource_list(device_t *);
-extern void pci_clean_resource_list(device_t *);
+extern bool pci_alloc_resource_list(pci_fun_t *);
+extern void pci_clean_resource_list(pci_fun_t *);
 
-extern void pci_read_bars(device_t *);
+extern void pci_read_bars(pci_fun_t *);
 extern size_t pci_bar_mask_to_size(uint32_t);
 
Index: uspace/drv/root/root.c
===================================================================
--- uspace/drv/root/root.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/root/root.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -2,4 +2,5 @@
  * Copyright (c) 2010 Lenka Trochtova
  * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -44,4 +45,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <str_error.h>
 #include <ctype.h>
 #include <macros.h>
@@ -49,5 +51,5 @@
 #include <sysinfo.h>
 
-#include <driver.h>
+#include <ddf/driver.h>
 #include <devman.h>
 #include <ipc/devman.h>
@@ -55,13 +57,13 @@
 #define NAME "root"
 
-#define PLATFORM_DEVICE_NAME "hw"
-#define PLATFORM_DEVICE_MATCH_ID_FMT "platform/%s"
-#define PLATFORM_DEVICE_MATCH_SCORE 100
-
-#define VIRTUAL_DEVICE_NAME "virt"
-#define VIRTUAL_DEVICE_MATCH_ID "rootvirt"
-#define VIRTUAL_DEVICE_MATCH_SCORE 100
-
-static int root_add_device(device_t *dev);
+#define PLATFORM_FUN_NAME "hw"
+#define PLATFORM_FUN_MATCH_ID_FMT "platform/%s"
+#define PLATFORM_FUN_MATCH_SCORE 100
+
+#define VIRTUAL_FUN_NAME "virt"
+#define VIRTUAL_FUN_MATCH_ID "rootvirt"
+#define VIRTUAL_FUN_MATCH_SCORE 100
+
+static int root_add_device(ddf_dev_t *dev);
 
 /** The root device driver's standard operations. */
@@ -76,36 +78,60 @@
 };
 
-/** Create the device which represents the root of virtual device tree.
- *
- * @param parent Parent of the newly created device.
- * @return Error code.
- */
-static int add_virtual_root_child(device_t *parent)
-{
-	printf(NAME ": adding new child for virtual devices.\n");
-	printf(NAME ":   device node is `%s' (%d %s)\n", VIRTUAL_DEVICE_NAME,
-	    VIRTUAL_DEVICE_MATCH_SCORE, VIRTUAL_DEVICE_MATCH_ID);
-
-	int res = child_device_register_wrapper(parent, VIRTUAL_DEVICE_NAME,
-	    VIRTUAL_DEVICE_MATCH_ID, VIRTUAL_DEVICE_MATCH_SCORE,
-	    NULL);
-
-	return res;
-}
-
-/** Create the device which represents the root of HW device tree.
- *
- * @param parent	Parent of the newly created device.
- * @return 0 on success, negative error number otherwise.
- */
-static int add_platform_child(device_t *parent)
+/** Create the function which represents the root of virtual device tree.
+ *
+ * @param dev	Device
+ * @return	EOK on success or negative error code
+ */
+static int add_virtual_root_fun(ddf_dev_t *dev)
+{
+	const char *name = VIRTUAL_FUN_NAME;
+	ddf_fun_t *fun;
+	int rc;
+
+	printf(NAME ": adding new function for virtual devices.\n");
+	printf(NAME ":   function node is `%s' (%d %s)\n", name,
+	    VIRTUAL_FUN_MATCH_SCORE, VIRTUAL_FUN_MATCH_ID);
+
+	fun = ddf_fun_create(dev, fun_inner, name);
+	if (fun == NULL) {
+		printf(NAME ": error creating function %s\n", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, VIRTUAL_FUN_MATCH_ID,
+	    VIRTUAL_FUN_MATCH_SCORE);
+	if (rc != EOK) {
+		printf(NAME ": error adding match IDs to function %s\n", name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function %s: %s\n", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Create the function which represents the root of HW device tree.
+ *
+ * @param dev	Device
+ * @return	EOK on success or negative error code
+ */
+static int add_platform_fun(ddf_dev_t *dev)
 {
 	char *match_id;
 	char *platform;
 	size_t platform_size;
-	int res;
+
+	const char *name = PLATFORM_FUN_NAME;
+	ddf_fun_t *fun;
+	int rc;
 
 	/* Get platform name from sysinfo. */
-
 	platform = sysinfo_get_data("platform", &platform_size);
 	if (platform == NULL) {
@@ -124,20 +150,36 @@
 
 	/* Construct match ID. */
-
-	if (asprintf(&match_id, PLATFORM_DEVICE_MATCH_ID_FMT, platform) == -1) {
+	if (asprintf(&match_id, PLATFORM_FUN_MATCH_ID_FMT, platform) == -1) {
 		printf(NAME ": Memory allocation failed.\n");
 		return ENOMEM;
 	}
 
-	/* Add child. */
-
-	printf(NAME ": adding new child for platform device.\n");
-	printf(NAME ":   device node is `%s' (%d %s)\n", PLATFORM_DEVICE_NAME,
-	    PLATFORM_DEVICE_MATCH_SCORE, match_id);
-
-	res = child_device_register_wrapper(parent, PLATFORM_DEVICE_NAME,
-	    match_id, PLATFORM_DEVICE_MATCH_SCORE, NULL);
-
-	return res;
+	/* Add function. */
+	printf(NAME ": adding platform function\n");
+	printf(NAME ":   function node is `%s' (%d %s)\n", PLATFORM_FUN_NAME,
+	    PLATFORM_FUN_MATCH_SCORE, match_id);
+
+	fun = ddf_fun_create(dev, fun_inner, name);
+	if (fun == NULL) {
+		printf(NAME ": error creating function %s\n", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, PLATFORM_FUN_MATCH_SCORE);
+	if (rc != EOK) {
+		printf(NAME ": error adding match IDs to function %s\n", name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function %s: %s\n", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	return EOK;
 }
 
@@ -147,9 +189,9 @@
  *			of HW and pseudo devices).
  */
-static int root_add_device(device_t *dev)
+static int root_add_device(ddf_dev_t *dev)
 {
 	printf(NAME ": root_add_device, device handle=%" PRIun "\n",
 	    dev->handle);
-	
+
 	/*
 	 * Register virtual devices root.
@@ -157,11 +199,11 @@
 	 * vital for the system.
 	 */
-	add_virtual_root_child(dev);
+	add_virtual_root_fun(dev);
 
 	/* Register root device's children. */
-	int res = add_platform_child(dev);
+	int res = add_platform_fun(dev);
 	if (EOK != res)
 		printf(NAME ": failed to add child device for platform.\n");
-	
+
 	return res;
 }
@@ -170,5 +212,5 @@
 {
 	printf(NAME ": HelenOS root device driver\n");
-	return driver_main(&root_driver);
+	return ddf_driver_main(&root_driver);
 }
 
Index: uspace/drv/rootpc/rootpc.c
===================================================================
--- uspace/drv/rootpc/rootpc.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/rootpc/rootpc.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -46,5 +46,5 @@
 #include <macros.h>
 
-#include <driver.h>
+#include <ddf/driver.h>
 #include <devman.h>
 #include <ipc/devman.h>
@@ -55,9 +55,12 @@
 #define NAME "rootpc"
 
-typedef struct rootpc_child_dev_data {
+/** Obtain function soft-state from DDF function node */
+#define ROOTPC_FUN(fnode) ((rootpc_fun_t *) (fnode)->driver_data)
+
+typedef struct rootpc_fun {
 	hw_resource_list_t hw_resources;
-} rootpc_child_dev_data_t;
-
-static int rootpc_add_device(device_t *dev);
+} rootpc_fun_t;
+
+static int rootpc_add_device(ddf_dev_t *dev);
 static void root_pc_init(void);
 
@@ -82,5 +85,5 @@
 };
 
-static rootpc_child_dev_data_t pci_data = {
+static rootpc_fun_t pci_data = {
 	.hw_resources = {
 		1,
@@ -89,16 +92,13 @@
 };
 
-static hw_resource_list_t *rootpc_get_child_resources(device_t *dev)
-{
-	rootpc_child_dev_data_t *data;
-	
-	data = (rootpc_child_dev_data_t *) dev->driver_data;
-	if (NULL == data)
-		return NULL;
-	
-	return &data->hw_resources;
-}
-
-static bool rootpc_enable_child_interrupt(device_t *dev)
+static hw_resource_list_t *rootpc_get_resources(ddf_fun_t *fnode)
+{
+	rootpc_fun_t *fun = ROOTPC_FUN(fnode);
+	
+	assert(fun != NULL);
+	return &fun->hw_resources;
+}
+
+static bool rootpc_enable_interrupt(ddf_fun_t *fun)
 {
 	/* TODO */
@@ -107,64 +107,63 @@
 }
 
-static hw_res_ops_t child_hw_res_ops = {
-	&rootpc_get_child_resources,
-	&rootpc_enable_child_interrupt
+static hw_res_ops_t fun_hw_res_ops = {
+	&rootpc_get_resources,
+	&rootpc_enable_interrupt
 };
 
 /* Initialized in root_pc_init() function. */
-static device_ops_t rootpc_child_ops;
+static ddf_dev_ops_t rootpc_fun_ops;
 
 static bool
-rootpc_add_child(device_t *parent, const char *name, const char *str_match_id,
-    rootpc_child_dev_data_t *drv_data)
-{
-	printf(NAME ": adding new child device '%s'.\n", name);
-	
-	device_t *child = NULL;
+rootpc_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
+    rootpc_fun_t *fun)
+{
+	printf(NAME ": adding new function '%s'.\n", name);
+	
+	ddf_fun_t *fnode = NULL;
 	match_id_t *match_id = NULL;
 	
 	/* Create new device. */
-	child = create_device();
-	if (NULL == child)
+	fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL)
 		goto failure;
 	
-	child->name = name;
-	child->driver_data = drv_data;
+	fnode->driver_data = fun;
 	
 	/* Initialize match id list */
 	match_id = create_match_id();
-	if (NULL == match_id)
+	if (match_id == NULL)
 		goto failure;
 	
 	match_id->id = str_match_id;
 	match_id->score = 100;
-	add_match_id(&child->match_ids, match_id);
+	add_match_id(&fnode->match_ids, match_id);
 	
 	/* Set provided operations to the device. */
-	child->ops = &rootpc_child_ops;
-	
-	/* Register child device. */
-	if (EOK != child_device_register(child, parent))
+	fnode->ops = &rootpc_fun_ops;
+	
+	/* Register function. */
+	if (ddf_fun_bind(fnode) != EOK) {
+		printf(NAME ": error binding function %s.\n", name);
 		goto failure;
+	}
 	
 	return true;
 	
 failure:
-	if (NULL != match_id)
+	if (match_id != NULL)
 		match_id->id = NULL;
 	
-	if (NULL != child) {
-		child->name = NULL;
-		delete_device(child);
-	}
-	
-	printf(NAME ": failed to add child device '%s'.\n", name);
+	if (fnode != NULL)
+		ddf_fun_destroy(fnode);
+	
+	printf(NAME ": failed to add function '%s'.\n", name);
 	
 	return false;
 }
 
-static bool rootpc_add_children(device_t *dev)
-{
-	return rootpc_add_child(dev, "pci0", "intel_pci", &pci_data);
+static bool rootpc_add_functions(ddf_dev_t *dev)
+{
+	return rootpc_add_fun(dev, "pci0", "intel_pci", &pci_data);
 }
 
@@ -175,12 +174,12 @@
  * @return		Zero on success, negative error number otherwise.
  */
-static int rootpc_add_device(device_t *dev)
+static int rootpc_add_device(ddf_dev_t *dev)
 {
 	printf(NAME ": rootpc_add_device, device handle = %d\n",
 	    (int)dev->handle);
 	
-	/* Register child devices. */
-	if (!rootpc_add_children(dev)) {
-		printf(NAME ": failed to add child devices for PC platform.\n");
+	/* Register functions. */
+	if (!rootpc_add_functions(dev)) {
+		printf(NAME ": failed to add functions for PC platform.\n");
 	}
 	
@@ -190,5 +189,5 @@
 static void root_pc_init(void)
 {
-	rootpc_child_ops.interfaces[HW_RES_DEV_IFACE] = &child_hw_res_ops;
+	rootpc_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
 }
 
@@ -197,5 +196,5 @@
 	printf(NAME ": HelenOS PC platform driver\n");
 	root_pc_init();
-	return driver_main(&rootpc_driver);
+	return ddf_driver_main(&rootpc_driver);
 }
 
Index: uspace/drv/rootvirt/devices.def
===================================================================
--- uspace/drv/rootvirt/devices.def	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/rootvirt/devices.def	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -22,4 +22,5 @@
 },
 #endif
+#ifdef CONFIG_RUN_VIRTUAL_USB_HC
 /* Virtual USB host controller. */
 {
@@ -27,2 +28,3 @@
 	.match_id = "usb&hc=vhc"
 },
+#endif
Index: uspace/drv/rootvirt/rootvirt.c
===================================================================
--- uspace/drv/rootvirt/rootvirt.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/rootvirt/rootvirt.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,20 +39,20 @@
 #include <errno.h>
 #include <str_error.h>
-#include <driver.h>
+#include <ddf/driver.h>
 
 #define NAME "rootvirt"
 
-/** Virtual device entry. */
+/** Virtual function entry */
 typedef struct {
-	/** Device name. */
+	/** Function name */
 	const char *name;
-	/** Device match id. */
+	/** Function match ID */
 	const char *match_id;
-} virtual_device_t;
+} virtual_function_t;
 
-/** List of existing virtual devices. */
-virtual_device_t virtual_devices[] = {
+/** List of existing virtual functions */
+virtual_function_t virtual_functions[] = {
 #include "devices.def"
-	/* Terminating item. */
+	/* Terminating item */
 	{
 		.name = NULL,
@@ -61,8 +61,8 @@
 };
 
-static int add_device(device_t *dev);
+static int rootvirt_add_device(ddf_dev_t *dev);
 
 static driver_ops_t rootvirt_ops = {
-	.add_device = &add_device
+	.add_device = &rootvirt_add_device
 };
 
@@ -72,30 +72,45 @@
 };
 
-/** Add child device.
+/** Add function to the virtual device.
  *
- * @param parent Parent device.
- * @param virt_dev Virtual device to add.
- * @return Error code.
+ * @param vdev		The virtual device
+ * @param vfun		Virtual function description
+ * @return		EOK on success or negative error code.
  */
-static int add_child(device_t *parent, virtual_device_t *virt_dev)
+static int rootvirt_add_fun(ddf_dev_t *vdev, virtual_function_t *vfun)
 {
-	printf(NAME ": registering child device `%s' (match \"%s\")\n",
-	    virt_dev->name, virt_dev->match_id);
+	ddf_fun_t *fun;
+	int rc;
 
-	int rc = child_device_register_wrapper(parent, virt_dev->name,
-	    virt_dev->match_id, 10, NULL);
+	printf(NAME ": registering function `%s' (match \"%s\")\n",
+	    vfun->name, vfun->match_id);
 
-	if (rc == EOK) {
-		printf(NAME ": registered child device `%s'\n",
-		    virt_dev->name);
-	} else {
-		printf(NAME ": failed to register child device `%s': %s\n",
-		    virt_dev->name, str_error(rc));
+	fun = ddf_fun_create(vdev, fun_inner, vfun->name);
+	if (fun == NULL) {
+		printf(NAME ": error creating function %s\n", vfun->name);
+		return ENOMEM;
 	}
 
-	return rc;
+	rc = ddf_fun_add_match_id(fun, vfun->match_id, 10);
+	if (rc != EOK) {
+		printf(NAME ": error adding match IDs to function %s\n",
+		    vfun->name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function %s: %s\n", vfun->name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	printf(NAME ": registered child device `%s'\n", vfun->name);
+	return EOK;
 }
 
-static int add_device(device_t *dev)
+static int rootvirt_add_device(ddf_dev_t *dev)
 {
 	static int instances = 0;
@@ -109,15 +124,14 @@
 	}
 
-	printf(NAME ": add_device(name=\"%s\", handle=%d)\n",
-	    dev->name, (int)dev->handle);
-	
+	printf(NAME ": add_device(handle=%d)\n", (int)dev->handle);
+
 	/*
-	 * Go through all virtual devices and try to add them.
+	 * Go through all virtual functions and try to add them.
 	 * We silently ignore failures.
 	 */
-	virtual_device_t *virt_dev = virtual_devices;
-	while (virt_dev->name != NULL) {
-		(void) add_child(dev, virt_dev);
-		virt_dev++;
+	virtual_function_t *vfun = virtual_functions;
+	while (vfun->name != NULL) {
+		(void) rootvirt_add_fun(dev, vfun);
+		vfun++;
 	}
 
@@ -128,5 +142,5 @@
 {
 	printf(NAME ": HelenOS virtual devices root driver\n");
-	return driver_main(&rootvirt_driver);
+	return ddf_driver_main(&rootvirt_driver);
 }
 
Index: uspace/drv/test1/char.c
===================================================================
--- uspace/drv/test1/char.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/test1/char.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,10 +37,10 @@
 #include "test1.h"
 
-static int impl_char_read(device_t *dev, char *buf, size_t count) {
+static int impl_char_read(ddf_fun_t *fun, char *buf, size_t count) {
 	memset(buf, 0, count);
 	return count;
 }
 
-static int imp_char_write(device_t *dev, char *buf, size_t count) {
+static int imp_char_write(ddf_fun_t *fun, char *buf, size_t count) {
 	return count;
 }
@@ -51,5 +51,5 @@
 };
 
-device_ops_t char_device_ops = {
+ddf_dev_ops_t char_device_ops = {
 	.interfaces[CHAR_DEV_IFACE] = &char_dev_ops
 };
Index: uspace/drv/test1/test1.c
===================================================================
--- uspace/drv/test1/test1.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/test1/test1.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,13 +34,15 @@
 #include <errno.h>
 #include <str_error.h>
+#include <ddf/driver.h>
+
 #include "test1.h"
 
-static int add_device(device_t *dev);
+static int test1_add_device(ddf_dev_t *dev);
 
 static driver_ops_t driver_ops = {
-	.add_device = &add_device
+	.add_device = &test1_add_device
 };
 
-static driver_t the_driver = {
+static driver_t test1_driver = {
 	.name = NAME,
 	.driver_ops = &driver_ops
@@ -55,19 +57,35 @@
  * @param score Device match score.
  */
-static void register_child_verbose(device_t *parent, const char *message,
+static int register_fun_verbose(ddf_dev_t *parent, const char *message,
     const char *name, const char *match_id, int match_score)
 {
-	printf(NAME ": registering child device `%s': %s.\n",
-	   name, message);
+	ddf_fun_t *fun;
+	int rc;
 
-	int rc = child_device_register_wrapper(parent, name,
-	    match_id, match_score, NULL);
+	printf(NAME ": registering function `%s': %s.\n", name, message);
 
-	if (rc == EOK) {
-		printf(NAME ": registered child device `%s'.\n", name);
-	} else {
-		printf(NAME ": failed to register child `%s' (%s).\n",
-		    name, str_error(rc));
+	fun = ddf_fun_create(parent, fun_inner, name);
+	if (fun == NULL) {
+		printf(NAME ": error creating function %s\n", name);
+		return ENOMEM;
 	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, match_score);
+	if (rc != EOK) {
+		printf(NAME ": error adding match IDs to function %s\n", name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function %s: %s\n", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	printf(NAME ": registered child device `%s'\n", name);
+	return EOK;
 }
 
@@ -89,19 +107,34 @@
  * @return Error code reporting success of the operation.
  */
-static int add_device(device_t *dev)
+static int test1_add_device(ddf_dev_t *dev)
 {
+	ddf_fun_t *fun_a;
+	int rc;
+
 	printf(NAME ": add_device(name=\"%s\", handle=%d)\n",
 	    dev->name, (int) dev->handle);
 
-	add_device_to_class(dev, "virtual");
+	fun_a = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun_a == NULL) {
+		printf(NAME ": error creating function 'a'.\n");
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_bind(fun_a);
+	if (rc != EOK) {
+		printf(NAME ": error binding function 'a'.\n");
+		return rc;
+	}
+
+	ddf_fun_add_to_class(fun_a, "virtual");
 
 	if (str_cmp(dev->name, "null") == 0) {
-		dev->ops = &char_device_ops;
-		add_device_to_class(dev, "virt-null");
-	} else if (dev->parent == NULL) {
-		register_child_verbose(dev, "cloning myself ;-)", "clone",
+		fun_a->ops = &char_device_ops;
+		ddf_fun_add_to_class(fun_a, "virt-null");
+	} else if (str_cmp(dev->name, "test1") == 0) {
+		(void) register_fun_verbose(dev, "cloning myself ;-)", "clone",
 		    "virtual&test1", 10);
 	} else if (str_cmp(dev->name, "clone") == 0) {
-		register_child_verbose(dev, "run by the same task", "child",
+		(void) register_fun_verbose(dev, "run by the same task", "child",
 		    "virtual&test1&child", 10);
 	}
@@ -115,5 +148,5 @@
 {
 	printf(NAME ": HelenOS test1 virtual device driver\n");
-	return driver_main(&the_driver);
+	return ddf_driver_main(&test1_driver);
 }
 
Index: uspace/drv/test1/test1.h
===================================================================
--- uspace/drv/test1/test1.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/test1/test1.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -32,9 +32,9 @@
 #define DRV_TEST1_TEST1_H_
 
-#include <driver.h>
+#include <ddf/driver.h>
 
 #define NAME "test1"
 
-extern device_ops_t char_device_ops;
+extern ddf_dev_ops_t char_device_ops;
 
 #endif
Index: uspace/drv/test2/test2.c
===================================================================
--- uspace/drv/test2/test2.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/test2/test2.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -31,18 +31,19 @@
 
 #include <assert.h>
+#include <async.h>
 #include <stdio.h>
 #include <errno.h>
 #include <str_error.h>
-#include <driver.h>
+#include <ddf/driver.h>
 
 #define NAME "test2"
 
-static int add_device(device_t *dev);
+static int test2_add_device(ddf_dev_t *dev);
 
 static driver_ops_t driver_ops = {
-	.add_device = &add_device
+	.add_device = &test2_add_device
 };
 
-static driver_t the_driver = {
+static driver_t test2_driver = {
 	.name = NAME,
 	.driver_ops = &driver_ops
@@ -57,53 +58,86 @@
  * @param score Device match score.
  */
-static void register_child_verbose(device_t *parent, const char *message,
+static int register_fun_verbose(ddf_dev_t *parent, const char *message,
     const char *name, const char *match_id, int match_score)
 {
-	printf(NAME ": registering child device `%s': %s.\n",
-	   name, message);
+	ddf_fun_t *fun;
+	int rc;
 
-	int rc = child_device_register_wrapper(parent, name,
-	    match_id, match_score, NULL);
+	printf(NAME ": registering function `%s': %s.\n", name, message);
 
-	if (rc == EOK) {
-		printf(NAME ": registered child device `%s'.\n", name);
-	} else {
-		printf(NAME ": failed to register child `%s' (%s).\n",
-		    name, str_error(rc));
+	fun = ddf_fun_create(parent, fun_inner, name);
+	if (fun == NULL) {
+		printf(NAME ": error creating function %s\n", name);
+		return ENOMEM;
 	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, match_score);
+	if (rc != EOK) {
+		printf(NAME ": error adding match IDs to function %s\n", name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function %s: %s\n", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	printf(NAME ": registered child device `%s'\n", name);
+	return EOK;
 }
 
 /** Add child devices after some sleep.
  *
- * @param arg Parent device structure (device_t *).
+ * @param arg Parent device structure (ddf_dev_t *).
  * @return Always EOK.
  */
 static int postponed_birth(void *arg)
 {
-	device_t *dev = (device_t *) arg;
+	ddf_dev_t *dev = (ddf_dev_t *) arg;
+	ddf_fun_t *fun_a;
+	int rc;
 
 	async_usleep(1000);
 
-	register_child_verbose(dev, "child driven by the same task",
+	(void) register_fun_verbose(dev, "child driven by the same task",
 	    "child", "virtual&test2", 10);
-	register_child_verbose(dev, "child driven by test1",
+	(void) register_fun_verbose(dev, "child driven by test1",
 	    "test1", "virtual&test1", 10);
 
-	add_device_to_class(dev, "virtual");
+	fun_a = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun_a == NULL) {
+		printf(NAME ": error creating function 'a'.\n");
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_bind(fun_a);
+	if (rc != EOK) {
+		printf(NAME ": error binding function 'a'.\n");
+		return rc;
+	}
+
+	ddf_fun_add_to_class(fun_a, "virtual");
 
 	return EOK;
 }
 
-
-static int add_device(device_t *dev)
+static int test2_add_device(ddf_dev_t *dev)
 {
-	printf(NAME ": add_device(name=\"%s\", handle=%d)\n",
+	printf(NAME ": test2_add_device(name=\"%s\", handle=%d)\n",
 	    dev->name, (int) dev->handle);
 
-	if (dev->parent == NULL) {
+	if (str_cmp(dev->name, "child") != 0) {
 		fid_t postpone = fibril_create(postponed_birth, dev);
+		if (postpone == 0) {
+			printf(NAME ": fibril_create() error\n");
+			return ENOMEM;
+		}
 		fibril_add_ready(postpone);
 	} else {
-		register_child_verbose(dev, "child without available driver",
+		(void) register_fun_verbose(dev, "child without available driver",
 		    "ERROR", "non-existent.match.id", 10);
 	}
@@ -115,5 +149,5 @@
 {
 	printf(NAME ": HelenOS test2 virtual device driver\n");
-	return driver_main(&the_driver);
+	return ddf_driver_main(&test2_driver);
 }
 
Index: uspace/drv/uhci-hcd/Makefile
===================================================================
--- uspace/drv/uhci-hcd/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2010 Vojtech Horky
+# 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.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+BINARY = uhci-hcd
+
+SOURCES = \
+	iface.c \
+	main.c \
+	root_hub.c \
+	transfer_list.c \
+	uhci.c \
+	uhci_struct/transfer_descriptor.c \
+	utils/device_keeper.c \
+	pci.c \
+	batch.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/uhci-hcd/batch.c
===================================================================
--- uspace/drv/uhci-hcd/batch.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/batch.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,361 @@
+/*
+ * 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 <errno.h>
+#include <str_error.h>
+
+#include <usb/debug.h>
+
+#include "batch.h"
+#include "transfer_list.h"
+#include "uhci.h"
+#include "utils/malloc32.h"
+
+#define DEFAULT_ERROR_COUNT 3
+
+static int batch_schedule(batch_t *instance);
+
+static void batch_call_in(batch_t *instance);
+static void batch_call_out(batch_t *instance);
+static void batch_call_in_and_dispose(batch_t *instance);
+static void batch_call_out_and_dispose(batch_t *instance);
+
+
+batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
+    usb_transfer_type_t transfer_type, size_t max_packet_size,
+    usb_speed_t speed, char *buffer, size_t size,
+    char* setup_buffer, size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out, void *arg)
+{
+	assert(func_in == NULL || func_out == NULL);
+	assert(func_in != NULL || func_out != NULL);
+
+	batch_t *instance = malloc(sizeof(batch_t));
+	if (instance == NULL) {
+		usb_log_error("Failed to allocate batch instance.\n");
+		return NULL;
+	}
+
+	instance->qh = queue_head_get();
+	if (instance->qh == NULL) {
+		usb_log_error("Failed to allocate queue head.\n");
+		free(instance);
+		return NULL;
+	}
+
+	instance->packets = (size + max_packet_size - 1) / max_packet_size;
+	if (transfer_type == USB_TRANSFER_CONTROL) {
+		instance->packets += 2;
+	}
+
+	instance->tds = malloc32(sizeof(transfer_descriptor_t) * instance->packets);
+	if (instance->tds == NULL) {
+		usb_log_error("Failed to allocate transfer descriptors.\n");
+		queue_head_dispose(instance->qh);
+		free(instance);
+		return NULL;
+	}
+	bzero(instance->tds, sizeof(transfer_descriptor_t) * instance->packets);
+
+	const size_t transport_size = max_packet_size * instance->packets;
+
+	instance->transport_buffer =
+	   (size > 0) ? malloc32(transport_size) : NULL;
+	if ((size > 0) && (instance->transport_buffer == NULL)) {
+		usb_log_error("Failed to allocate device accessible buffer.\n");
+		queue_head_dispose(instance->qh);
+		free32(instance->tds);
+		free(instance);
+		return NULL;
+	}
+
+	instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL;
+	if ((setup_size > 0) && (instance->setup_buffer == NULL)) {
+		usb_log_error("Failed to allocate device accessible setup buffer.\n");
+		queue_head_dispose(instance->qh);
+		free32(instance->tds);
+		free32(instance->transport_buffer);
+		free(instance);
+		return NULL;
+	}
+	if (instance->setup_buffer) {
+		memcpy(instance->setup_buffer, setup_buffer, setup_size);
+	}
+
+	instance->max_packet_size = max_packet_size;
+
+	link_initialize(&instance->link);
+
+	instance->target = target;
+	instance->transfer_type = transfer_type;
+
+	if (func_out)
+		instance->callback_out = func_out;
+	if (func_in)
+		instance->callback_in = func_in;
+
+	instance->buffer = buffer;
+	instance->buffer_size = size;
+	instance->setup_size = setup_size;
+	instance->fun = fun;
+	instance->arg = arg;
+	instance->speed = speed;
+
+	queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
+	usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
+	    instance, target.address, target.endpoint);
+	return instance;
+}
+/*----------------------------------------------------------------------------*/
+bool batch_is_complete(batch_t *instance)
+{
+	assert(instance);
+	usb_log_debug2("Batch(%p) checking %d packet(s) for completion.\n",
+	    instance, instance->packets);
+	instance->transfered_size = 0;
+	size_t i = 0;
+	for (;i < instance->packets; ++i) {
+		if (transfer_descriptor_is_active(&instance->tds[i])) {
+			return false;
+		}
+		instance->error = transfer_descriptor_status(&instance->tds[i]);
+		if (instance->error != EOK) {
+			if (i > 0)
+				instance->transfered_size -= instance->setup_size;
+			usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
+			  instance, i, instance->tds[i].status);
+			return true;
+		}
+		instance->transfered_size +=
+		    transfer_descriptor_actual_size(&instance->tds[i]);
+	}
+	instance->transfered_size -= instance->setup_size;
+	return true;
+}
+/*----------------------------------------------------------------------------*/
+void batch_control_write(batch_t *instance)
+{
+	assert(instance);
+
+	/* we are data out, we are supposed to provide data */
+	memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
+
+	const bool low_speed = instance->speed == USB_SPEED_LOW;
+	int toggle = 0;
+	/* setup stage */
+	transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
+	    instance->setup_size, toggle, false, low_speed,
+	    instance->target, USB_PID_SETUP, instance->setup_buffer,
+	    &instance->tds[1]);
+
+	/* data stage */
+	size_t i = 1;
+	for (;i < instance->packets - 1; ++i) {
+		char *data =
+		    instance->transport_buffer + ((i - 1) * instance->max_packet_size);
+		toggle = 1 - toggle;
+
+		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+		    instance->max_packet_size, toggle++, false, low_speed,
+		    instance->target, USB_PID_OUT, data, &instance->tds[i + 1]);
+	}
+
+	/* status stage */
+	i = instance->packets - 1;
+	transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+	    0, 1, false, low_speed, instance->target, USB_PID_IN, NULL, NULL);
+
+	instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
+	usb_log_debug2("Control write last TD status: %x.\n",
+		instance->tds[i].status);
+
+	instance->next_step = batch_call_out_and_dispose;
+	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_control_read(batch_t *instance)
+{
+	assert(instance);
+
+	const bool low_speed = instance->speed == USB_SPEED_LOW;
+	int toggle = 0;
+	/* setup stage */
+	transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
+	    instance->setup_size, toggle, false, low_speed, instance->target,
+	    USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
+
+	/* data stage */
+	size_t i = 1;
+	for (;i < instance->packets - 1; ++i) {
+		char *data =
+		    instance->transport_buffer + ((i - 1) * instance->max_packet_size);
+		toggle = 1 - toggle;
+
+		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+		    instance->max_packet_size, toggle, false, low_speed,
+				instance->target, USB_PID_IN, data, &instance->tds[i + 1]);
+	}
+
+	/* status stage */
+	i = instance->packets - 1;
+	transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+	    0, 1, false, low_speed, instance->target, USB_PID_OUT, NULL, NULL);
+
+	instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
+	usb_log_debug2("Control read last TD status: %x.\n",
+		instance->tds[i].status);
+
+	instance->next_step = batch_call_in_and_dispose;
+	usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_interrupt_in(batch_t *instance)
+{
+	assert(instance);
+
+	const bool low_speed = instance->speed == USB_SPEED_LOW;
+	int toggle = 1;
+	size_t i = 0;
+	for (;i < instance->packets; ++i) {
+		char *data =
+		    instance->transport_buffer + (i  * instance->max_packet_size);
+		transfer_descriptor_t *next = (i + 1) < instance->packets ?
+		    &instance->tds[i + 1] : NULL;
+		toggle = 1 - toggle;
+
+		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+		    instance->max_packet_size, toggle, false, low_speed,
+		    instance->target, USB_PID_IN, data, next);
+	}
+
+	instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
+
+	instance->next_step = batch_call_in_and_dispose;
+	usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_interrupt_out(batch_t *instance)
+{
+	assert(instance);
+
+	memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
+
+	const bool low_speed = instance->speed == USB_SPEED_LOW;
+	int toggle = 1;
+	size_t i = 0;
+	for (;i < instance->packets; ++i) {
+		char *data =
+		    instance->transport_buffer + (i  * instance->max_packet_size);
+		transfer_descriptor_t *next = (i + 1) < instance->packets ?
+		    &instance->tds[i + 1] : NULL;
+		toggle = 1 - toggle;
+
+		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
+		    instance->max_packet_size, toggle++, false, low_speed,
+		    instance->target, USB_PID_OUT, data, next);
+	}
+
+	instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
+
+	instance->next_step = batch_call_out_and_dispose;
+	usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_call_in(batch_t *instance)
+{
+	assert(instance);
+	assert(instance->callback_in);
+
+	memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size);
+
+	int err = instance->error;
+	usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n",
+	    instance, instance->transfer_type, str_error(err), err,
+	    instance->transfered_size);
+
+	instance->callback_in(instance->fun,
+	    err, instance->transfered_size,
+	    instance->arg);
+}
+/*----------------------------------------------------------------------------*/
+void batch_call_out(batch_t *instance)
+{
+	assert(instance);
+	assert(instance->callback_out);
+
+	int err = instance->error;
+	usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n",
+	    instance, instance->transfer_type, str_error(err), err);
+	instance->callback_out(instance->fun,
+	    err, instance->arg);
+}
+/*----------------------------------------------------------------------------*/
+void batch_call_in_and_dispose(batch_t *instance)
+{
+	assert(instance);
+	batch_call_in(instance);
+	usb_log_debug("Batch(%p) disposing.\n", instance);
+	free32(instance->tds);
+	free32(instance->qh);
+	free32(instance->setup_buffer);
+	free32(instance->transport_buffer);
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+void batch_call_out_and_dispose(batch_t *instance)
+{
+	assert(instance);
+	batch_call_out(instance);
+	usb_log_debug("Batch(%p) disposing.\n", instance);
+	free32(instance->tds);
+	free32(instance->qh);
+	free32(instance->setup_buffer);
+	free32(instance->transport_buffer);
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+int batch_schedule(batch_t *instance)
+{
+	assert(instance);
+	uhci_t *hc = fun_to_uhci(instance->fun);
+	assert(hc);
+	return uhci_schedule(hc, instance);
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/batch.h
===================================================================
--- uspace/drv/uhci-hcd/batch.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/batch.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,101 @@
+/*
+ * 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_BATCH_H
+#define DRV_UHCI_BATCH_H
+
+#include <adt/list.h>
+
+#include <usbhc_iface.h>
+#include <usb/usb.h>
+
+#include "uhci_struct/transfer_descriptor.h"
+#include "uhci_struct/queue_head.h"
+
+typedef struct batch
+{
+	link_t link;
+	usb_speed_t speed;
+	usb_target_t target;
+	usb_transfer_type_t transfer_type;
+	union {
+		usbhc_iface_transfer_in_callback_t callback_in;
+		usbhc_iface_transfer_out_callback_t callback_out;
+	};
+	void *arg;
+	char *transport_buffer;
+	char *setup_buffer;
+	size_t setup_size;
+	char *buffer;
+	size_t buffer_size;
+	size_t max_packet_size;
+	size_t packets;
+	size_t transfered_size;
+	int error;
+	ddf_fun_t *fun;
+	queue_head_t *qh;
+	transfer_descriptor_t *tds;
+	void (*next_step)(struct batch*);
+} batch_t;
+
+batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
+    usb_transfer_type_t transfer_type, size_t max_packet_size,
+    usb_speed_t speed, char *buffer, size_t size,
+		char *setup_buffer, size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out, void *arg);
+
+bool batch_is_complete(batch_t *instance);
+
+void batch_control_write(batch_t *instance);
+
+void batch_control_read(batch_t *instance);
+
+void batch_interrupt_in(batch_t *instance);
+
+void batch_interrupt_out(batch_t *instance);
+
+/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
+void batch_control_setup_old(batch_t *instance);
+
+void batch_control_write_data_old(batch_t *instance);
+
+void batch_control_read_data_old(batch_t *instance);
+
+void batch_control_write_status_old(batch_t *instance);
+
+void batch_control_read_status_old(batch_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/iface.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, 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 <ddf/driver.h>
+#include <remote_usbhc.h>
+
+#include <usb/debug.h>
+
+#include <errno.h>
+
+#include "iface.h"
+#include "uhci.h"
+#include "utils/device_keeper.h"
+
+/*----------------------------------------------------------------------------*/
+static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	usb_log_debug("Default address request with speed %d.\n", speed);
+	device_keeper_reserve_default(&hc->device_manager, speed);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int release_default_address(ddf_fun_t *fun)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	usb_log_debug("Default address release.\n");
+	device_keeper_release_default(&hc->device_manager);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int request_address(ddf_fun_t *fun, usb_speed_t speed,
+    usb_address_t *address)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	assert(address);
+
+	usb_log_debug("Address request with speed %d.\n", speed);
+	*address = device_keeper_request(&hc->device_manager, speed);
+	usb_log_debug("Address request with result: %d.\n", *address);
+	if (*address <= 0)
+	  return *address;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int bind_address(
+  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	usb_log_debug("Address bind %d-%d.\n", address, handle);
+	device_keeper_bind(&hc->device_manager, address, handle);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int release_address(ddf_fun_t *fun, usb_address_t address)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	usb_log_debug("Address release %d.\n", address);
+	device_keeper_release(&hc->device_manager, address);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
+    size_t max_packet_size, void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
+
+	usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n",
+	    target.address, target.endpoint, size, max_packet_size);
+
+	batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
+	    max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_interrupt_out(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
+    size_t max_packet_size, void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
+	usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n",
+	    target.address, target.endpoint, size, max_packet_size);
+
+	batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
+	    max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_interrupt_in(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int control_write(ddf_fun_t *fun, usb_target_t target,
+    size_t max_packet_size,
+    void *setup_data, size_t setup_size, void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
+	usb_log_debug("Control WRITE %d:%d %zu(%zu).\n",
+	    target.address, target.endpoint, size, max_packet_size);
+
+	batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
+	    max_packet_size, speed, data, size, setup_data, setup_size,
+	    NULL, callback, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_control_write(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int control_read(ddf_fun_t *fun, usb_target_t target,
+    size_t max_packet_size,
+    void *setup_data, size_t setup_size, void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
+
+	usb_log_debug("Control READ %d:%d %zu(%zu).\n",
+	    target.address, target.endpoint, size, max_packet_size);
+	batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
+	    max_packet_size, speed, data, size, setup_data, setup_size, callback,
+	    NULL, arg);
+	if (!batch)
+		return ENOMEM;
+	batch_control_read(batch);
+	return EOK;
+}
+
+
+/*----------------------------------------------------------------------------*/
+usbhc_iface_t uhci_iface = {
+	.reserve_default_address = reserve_default_address,
+	.release_default_address = release_default_address,
+	.request_address = request_address,
+	.bind_address = bind_address,
+	.release_address = release_address,
+
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+
+	.control_read = control_read,
+	.control_write = control_write,
+};
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/iface.h
===================================================================
--- uspace/drv/uhci-hcd/iface.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/iface.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * 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_IFACE_H
+#define DRV_UHCI_IFACE_H
+
+#include <usbhc_iface.h>
+
+extern usbhc_iface_t uhci_iface;
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/main.c
===================================================================
--- uspace/drv/uhci-hcd/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, 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 <ddf/driver.h>
+#include <ddf/interrupt.h>
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <device/hw_res.h>
+
+#include <errno.h>
+
+#include <usb/debug.h>
+
+#include "iface.h"
+#include "pci.h"
+#include "root_hub.h"
+#include "uhci.h"
+
+#define NAME "uhci-hcd"
+
+static int uhci_add_device(ddf_dev_t *device);
+
+/*----------------------------------------------------------------------------*/
+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(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	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(ddf_dev_t *device)
+{
+	assert(device);
+
+	usb_log_info("uhci_add_device() called\n");
+
+	uintptr_t io_reg_base = 0;
+	size_t io_reg_size = 0;
+	int irq = 0;
+
+	int ret =
+	    pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
+
+	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));
+	ret = (uhci_hc != NULL) ? EOK : ENOMEM;
+	CHECK_RET_RETURN(ret, "Failed to allocate memory for uhci hcd driver.\n");
+
+	ret = uhci_init(uhci_hc, device, (void*)io_reg_base, io_reg_size);
+	if (ret != EOK) {
+		usb_log_error("Failed to init uhci-hcd.\n");
+		free(uhci_hc);
+		return ret;
+	}
+
+	/*
+	 * We might free uhci_hc, but that does not matter since no one
+	 * else would access driver_data anyway.
+	 */
+	device->driver_data = uhci_hc;
+	ret = register_interrupt_handler(device, irq, irq_handler,
+	    &uhci_hc->interrupt_code);
+	if (ret != EOK) {
+		usb_log_error("Failed to register interrupt handler.\n");
+		uhci_fini(uhci_hc);
+		free(uhci_hc);
+		return ret;
+	}
+
+	ddf_fun_t *rh;
+	ret = setup_root_hub(&rh, device);
+	if (ret != EOK) {
+		usb_log_error("Failed to setup uhci root hub.\n");
+		uhci_fini(uhci_hc);
+		free(uhci_hc);
+		return ret;
+	}
+	rh->driver_data = uhci_hc->ddf_instance;
+
+	ret = ddf_fun_bind(rh);
+	if (ret != EOK) {
+		usb_log_error("Failed to register root hub.\n");
+		uhci_fini(uhci_hc);
+		free(uhci_hc);
+		free(rh);
+		return ret;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int main(int argc, char *argv[])
+{
+	sleep(3);
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+
+	return ddf_driver_main(&uhci_driver);
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/pci.c
===================================================================
--- uspace/drv/uhci-hcd/pci.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/pci.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 drvusbuhci
+ * @{
+ */
+/**
+ * @file
+ * PCI related functions needed by the UHCI driver.
+ */
+#include <errno.h>
+#include <assert.h>
+#include <devman.h>
+#include <device/hw_res.h>
+
+#include <usb/debug.h>
+
+#include "pci.h"
+
+/** Get address of registers and IRQ for given device.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] io_reg_address Base address of the I/O range.
+ * @param[out] io_reg_size Size of the I/O range.
+ * @param[out] irq_no IRQ assigned to the device.
+ * @return Error code.
+ */
+int pci_get_my_registers(ddf_dev_t *dev,
+    uintptr_t *io_reg_address, size_t *io_reg_size,
+    int *irq_no)
+{
+	assert(dev != NULL);
+
+	int parent_phone = devman_parent_device_connect(dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	int rc;
+
+	hw_resource_list_t hw_resources;
+	rc = hw_res_get_resource_list(parent_phone, &hw_resources);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	uintptr_t io_address = 0;
+	size_t io_size = 0;
+	bool io_found = false;
+
+	int irq = 0;
+	bool irq_found = false;
+
+	size_t i;
+	for (i = 0; i < hw_resources.count; i++) {
+		hw_resource_t *res = &hw_resources.resources[i];
+		switch (res->type) {
+			case INTERRUPT:
+				irq = res->res.interrupt.irq;
+				irq_found = true;
+				usb_log_debug2("Found interrupt: %d.\n", irq);
+				break;
+			case IO_RANGE:
+				io_address = res->res.io_range.address;
+				io_size = res->res.io_range.size;
+				usb_log_debug2("Found io: %llx %zu.\n",
+				    res->res.io_range.address, res->res.io_range.size);
+				io_found = true;
+				break;
+			default:
+				break;
+		}
+	}
+
+	if (!io_found) {
+		rc = ENOENT;
+		goto leave;
+	}
+
+	if (!irq_found) {
+		rc = ENOENT;
+		goto leave;
+	}
+
+	*io_reg_address = io_address;
+	*io_reg_size = io_size;
+	*irq_no = irq;
+
+	rc = EOK;
+leave:
+	async_hangup(parent_phone);
+
+	return rc;
+}
+/*----------------------------------------------------------------------------*/
+int pci_enable_interrupts(ddf_dev_t *device)
+{
+	int parent_phone = devman_parent_device_connect(device->handle,
+	    IPC_FLAG_BLOCKING);
+	bool enabled = hw_res_enable_interrupt(parent_phone);
+	async_hangup(parent_phone);
+	return enabled ? EOK : EIO;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/pci.h
===================================================================
--- uspace/drv/uhci-hcd/pci.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/pci.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_PCI_H
+#define DRV_UHCI_PCI_H
+
+#include <ddf/driver.h>
+
+int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int pci_enable_interrupts(ddf_dev_t *);
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/uhci-hcd/root_hub.c
===================================================================
--- uspace/drv/uhci-hcd/root_hub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/root_hub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,153 @@
+/*
+ * 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 <assert.h>
+#include <errno.h>
+#include <str_error.h>
+#include <stdio.h>
+#include <ops/hw_res.h>
+
+#include <usb_iface.h>
+#include <usb/debug.h>
+
+#include "root_hub.h"
+#include "uhci.h"
+
+/*----------------------------------------------------------------------------*/
+static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
+    devman_handle_t *handle)
+{
+	ddf_fun_t *hc_fun = root_hub_fun->driver_data;
+	assert(hc_fun != NULL);
+
+	*handle = hc_fun->handle;
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int usb_iface_get_address_rh_impl(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	assert(fun);
+	ddf_fun_t *hc_fun = fun->driver_data;
+	assert(hc_fun);
+	uhci_t *hc = fun_to_uhci(hc_fun);
+	assert(hc);
+
+	usb_address_t addr = device_keeper_find(&hc->device_manager,
+	    handle);
+	if (addr < 0) {
+		return addr;
+	}
+
+	if (address != NULL) {
+		*address = addr;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+usb_iface_t usb_iface_root_hub_fun_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_rh_impl,
+	.get_address = usb_iface_get_address_rh_impl
+};
+/*----------------------------------------------------------------------------*/
+static hw_resource_list_t *get_resource_list(ddf_fun_t *dev)
+{
+	assert(dev);
+	ddf_fun_t *hc_ddf_instance = dev->driver_data;
+	assert(hc_ddf_instance);
+	uhci_t *hc = hc_ddf_instance->driver_data;
+	assert(hc);
+
+	//TODO: fix memory leak
+	hw_resource_list_t *resource_list = malloc(sizeof(hw_resource_list_t));
+	assert(resource_list);
+	resource_list->count = 1;
+	resource_list->resources = malloc(sizeof(hw_resource_t));
+	assert(resource_list->resources);
+	resource_list->resources[0].type = IO_RANGE;
+	resource_list->resources[0].res.io_range.address =
+	    ((uintptr_t)hc->registers) + 0x10; // see UHCI design guide
+	resource_list->resources[0].res.io_range.size = 4;
+	resource_list->resources[0].res.io_range.endianness = LITTLE_ENDIAN;
+
+	return resource_list;
+}
+/*----------------------------------------------------------------------------*/
+static hw_res_ops_t hw_res_iface = {
+	.get_resource_list = get_resource_list,
+	.enable_interrupt = NULL
+};
+/*----------------------------------------------------------------------------*/
+static ddf_dev_ops_t root_hub_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface_root_hub_fun_impl,
+	.interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
+};
+/*----------------------------------------------------------------------------*/
+int setup_root_hub(ddf_fun_t **fun, ddf_dev_t *hc)
+{
+	assert(fun);
+	assert(hc);
+	int ret;
+
+	ddf_fun_t *hub = ddf_fun_create(hc, fun_inner, "root-hub");
+	if (!hub) {
+		usb_log_error("Failed to create root hub device structure.\n");
+		return ENOMEM;
+	}
+
+	char *match_str;
+	ret = asprintf(&match_str, "usb&uhci&root-hub");
+	if (ret < 0) {
+		usb_log_error("Failed to create root hub match string.\n");
+		ddf_fun_destroy(hub);
+		return ENOMEM;
+	}
+
+	ret = ddf_fun_add_match_id(hub, match_str, 100);
+	if (ret != EOK) {
+		usb_log_error("Failed(%d) to add root hub match id: %s\n",
+		    ret, str_error(ret));
+		ddf_fun_destroy(hub);
+		return ret;
+	}
+
+	hub->ops = &root_hub_ops;
+
+	*fun = hub;
+	return EOK;
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/root_hub.h
===================================================================
--- uspace/drv/uhci-hcd/root_hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/root_hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_ROOT_HUB_H
+#define DRV_UHCI_ROOT_HUB_H
+
+#include <ddf/driver.h>
+
+int setup_root_hub(ddf_fun_t **device, ddf_dev_t *hc);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,156 @@
+/*
+ * 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 <errno.h>
+
+#include <usb/debug.h>
+
+#include "transfer_list.h"
+
+int transfer_list_init(transfer_list_t *instance, const char *name)
+{
+	assert(instance);
+	instance->next = NULL;
+	instance->name = name;
+	instance->queue_head = queue_head_get();
+	if (!instance->queue_head) {
+		usb_log_error("Failed to allocate queue head.\n");
+		return ENOMEM;
+	}
+	instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head);
+
+	queue_head_init(instance->queue_head);
+	list_initialize(&instance->batch_list);
+	fibril_mutex_initialize(&instance->guard);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
+{
+	assert(instance);
+	assert(next);
+	if (!instance->queue_head)
+		return;
+	queue_head_append_qh(instance->queue_head, next->queue_head_pa);
+	instance->queue_head->element = instance->queue_head->next_queue;
+}
+/*----------------------------------------------------------------------------*/
+void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name);
+
+	uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
+	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
+	pa |= LINK_POINTER_QUEUE_HEAD_FLAG;
+
+	batch->qh->next_queue = instance->queue_head->next_queue;
+
+	fibril_mutex_lock(&instance->guard);
+
+	if (instance->queue_head->element == instance->queue_head->next_queue) {
+		/* there is nothing scheduled */
+		list_append(&batch->link, &instance->batch_list);
+		instance->queue_head->element = pa;
+		usb_log_debug("Batch(%p) added to queue %s first.\n",
+			batch, instance->name);
+		fibril_mutex_unlock(&instance->guard);
+		return;
+	}
+	/* now we can be sure that there is someting scheduled */
+	assert(!list_empty(&instance->batch_list));
+	batch_t *first = list_get_instance(
+	          instance->batch_list.next, batch_t, link);
+	batch_t *last = list_get_instance(
+	    instance->batch_list.prev, batch_t, link);
+	queue_head_append_qh(last->qh, pa);
+	list_append(&batch->link, &instance->batch_list);
+	usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
+		batch, instance->name, first );
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+static void transfer_list_remove_batch(
+    transfer_list_t *instance, batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	assert(instance->queue_head);
+	assert(batch->qh);
+	usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name);
+
+	/* I'm the first one here */
+	if (batch->link.prev == &instance->batch_list) {
+		usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n",
+			batch, instance->name, batch->qh->next_queue);
+		instance->queue_head->element = batch->qh->next_queue;
+	} else {
+		usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n",
+			batch, instance->name, batch->qh->next_queue);
+		batch_t *prev = list_get_instance(batch->link.prev, batch_t, link);
+		prev->qh->next_queue = batch->qh->next_queue;
+	}
+	list_remove(&batch->link);
+}
+/*----------------------------------------------------------------------------*/
+void transfer_list_remove_finished(transfer_list_t *instance)
+{
+	assert(instance);
+
+	LIST_INITIALIZE(done);
+
+	fibril_mutex_lock(&instance->guard);
+	link_t *current = instance->batch_list.next;
+	while (current != &instance->batch_list) {
+		link_t *next = current->next;
+		batch_t *batch = list_get_instance(current, batch_t, link);
+
+		if (batch_is_complete(batch)) {
+			transfer_list_remove_batch(instance, batch);
+			list_append(current, &done);
+		}
+		current = next;
+	}
+	fibril_mutex_unlock(&instance->guard);
+
+	while (!list_empty(&done)) {
+		link_t *item = done.next;
+		list_remove(item);
+		batch_t *batch = list_get_instance(item, batch_t, link);
+		batch->next_step(batch);
+	}
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/transfer_list.h
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/transfer_list.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,68 @@
+/*
+ * 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_TRANSFER_LIST_H
+#define DRV_UHCI_TRANSFER_LIST_H
+
+#include <fibril_synch.h>
+
+#include "uhci_struct/queue_head.h"
+
+#include "batch.h"
+
+typedef struct transfer_list
+{
+	fibril_mutex_t guard;
+	queue_head_t *queue_head;
+	uint32_t queue_head_pa;
+	struct transfer_list *next;
+	const char *name;
+	link_t batch_list;
+} transfer_list_t;
+
+int transfer_list_init(transfer_list_t *instance, const char *name);
+
+void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
+
+static inline void transfer_list_fini(transfer_list_t *instance)
+{
+	assert(instance);
+	queue_head_dispose(instance->queue_head);
+}
+void transfer_list_remove_finished(transfer_list_t *instance);
+
+void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/transfers.c
===================================================================
--- uspace/drv/uhci-hcd/transfers.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/transfers.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * 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.
+ */
+#include <usb/hcdhubd.h>
+#include <errno.h>
+
+#include "uhci.h"
+
+static int enqueue_transfer_out(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)
+{
+	printf(NAME ": transfer OUT [%d.%d (%s); %zu]\n",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
+	    size);
+
+	return ENOTSUP;
+}
+
+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)
+{
+	printf(NAME ": transfer SETUP [%d.%d (%s); %zu]\n",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
+	    size);
+
+	return ENOTSUP;
+}
+
+static int enqueue_transfer_in(device_t *dev,
+    usb_target_t target, usb_transfer_type_t transfer_type,
+    void *buffer, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	printf(NAME ": transfer IN [%d.%d (%s); %zu]\n",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
+	    size);
+
+	return ENOTSUP;
+}
+
+
+static int get_address(device_t *dev, devman_handle_t handle,
+    usb_address_t *address)
+{
+	return ENOTSUP;
+}
+
+static int interrupt_out(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_out(dev, target, USB_TRANSFER_INTERRUPT,
+	    data, size,
+	    callback, arg);
+}
+
+static int interrupt_in(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	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,
+    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,
+    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);
+}
+
+static int control_read_setup(device_t *dev, usb_target_t target,
+    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,
+    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);
+}
+
+
+usbhc_iface_t uhci_iface = {
+	.tell_address = get_address,
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+	.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/uhci-hcd.ma
===================================================================
--- uspace/drv/uhci-hcd/uhci-hcd.ma	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/uhci-hcd.ma	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,21 @@
+10 pci/ven=8086&dev=7020
+10 pci/ven=8086&dev=7112
+
+10 pci/ven=8086&dev=27c8
+10 pci/ven=8086&dev=27c9
+10 pci/ven=8086&dev=27ca
+10 pci/ven=8086&dev=27cb
+
+
+10 pci/ven=8086&dev=2830
+10 pci/ven=8086&dev=2831
+10 pci/ven=8086&dev=2832
+10 pci/ven=8086&dev=2834
+10 pci/ven=8086&dev=2835
+
+10 pci/ven=8086&dev=2934
+10 pci/ven=8086&dev=2935
+10 pci/ven=8086&dev=2936
+10 pci/ven=8086&dev=2937
+10 pci/ven=8086&dev=2938
+10 pci/ven=8086&dev=2939
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,414 @@
+/*
+ * 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 <errno.h>
+#include <str_error.h>
+#include <adt/list.h>
+#include <libarch/ddi.h>
+
+#include <usb/debug.h>
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+#include <usb_iface.h>
+
+#include "uhci.h"
+#include "iface.h"
+
+static irq_cmd_t uhci_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_16,
+		.addr = NULL, /* patched for every instance */
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_PIO_WRITE_16,
+		.addr = NULL, /* pathed for every instance */
+		.value = 0x1f
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static int usb_iface_get_address(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+
+	usb_address_t addr = device_keeper_find(&hc->device_manager,
+	    handle);
+	if (addr < 0) {
+		return addr;
+	}
+
+	if (address != NULL) {
+		*address = addr;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static usb_iface_t hc_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle_hc_impl,
+	.get_address = usb_iface_get_address
+};
+/*----------------------------------------------------------------------------*/
+static ddf_dev_ops_t uhci_ops = {
+	.interfaces[USB_DEV_IFACE] = &hc_usb_iface,
+	.interfaces[USBHC_DEV_IFACE] = &uhci_iface,
+};
+
+static int uhci_init_transfer_lists(uhci_t *instance);
+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, ddf_dev_t *dev, void *regs, size_t reg_size)
+{
+	assert(reg_size >= sizeof(regs_t));
+	int ret;
+
+#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		if (instance->ddf_instance) \
+			ddf_fun_destroy(instance->ddf_instance); \
+		return ret; \
+	} else (void) 0
+
+	/*
+	 * Create UHCI function.
+	 */
+	instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci");
+	ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FUN_RETURN(ret, "Failed to create UHCI device function.\n");
+
+	instance->ddf_instance->ops = &uhci_ops;
+	instance->ddf_instance->driver_data = instance;
+
+	ret = ddf_fun_bind(instance->ddf_instance);
+	CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to bind UHCI device function: %s.\n",
+	    ret, str_error(ret));
+
+	/* allow access to hc control registers */
+	regs_t *io;
+	ret = pio_enable(regs, reg_size, (void**)&io);
+	CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to gain access to registers at %p: %s.\n",
+	    ret, str_error(ret), io);
+	instance->registers = io;
+	usb_log_debug("Device registers at %p(%u) accessible.\n", io, reg_size);
+
+	ret = uhci_init_mem_structures(instance);
+	CHECK_RET_DEST_FUN_RETURN(ret, "Failed to initialize UHCI 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);
+
+	usb_log_info("Started UHCI driver.\n");
+	return EOK;
+#undef CHECK_RET_DEST_FUN_RETURN
+}
+/*----------------------------------------------------------------------------*/
+void uhci_init_hw(uhci_t *instance)
+{
+	/* reset everything, who knows what touched it before us */
+	pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
+	async_usleep(10000); /* 10ms according to USB spec */
+	pio_write_16(&instance->registers->usbcmd, 0);
+
+	/* reset hc, all states and counters */
+	pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET);
+	while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0)
+		{ async_usleep(10); }
+
+	/* 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);
+}
+/*----------------------------------------------------------------------------*/
+int uhci_init_mem_structures(uhci_t *instance)
+{
+	assert(instance);
+#define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		if (instance->interrupt_code.cmds != NULL) \
+			free(instance->interrupt_code.cmds); \
+		return ret; \
+	} else (void) 0
+
+	/* init interrupt code */
+	instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
+	int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n");
+
+	{
+		irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
+		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.cmdcount =
+				sizeof(uhci_cmds) / sizeof(irq_cmd_t);
+	}
+
+	/* init transfer lists */
+	ret = uhci_init_transfer_lists(instance);
+	CHECK_RET_DEST_CMDS_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_DEST_CMDS_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 */
+	const uint32_t queue =
+	  instance->transfers_interrupt.queue_head_pa
+	  | LINK_POINTER_QUEUE_HEAD_FLAG;
+
+	unsigned i = 0;
+	for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
+		instance->frame_list[i] = queue;
+	}
+
+	/* init address keeper(libusb) */
+	device_keeper_init(&instance->device_manager);
+	usb_log_debug("Initialized device manager.\n");
+
+	return EOK;
+#undef CHECK_RET_DEST_CMDS_RETURN
+}
+/*----------------------------------------------------------------------------*/
+int uhci_init_transfer_lists(uhci_t *instance)
+{
+	assert(instance);
+#define CHECK_RET_CLEAR_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		transfer_list_fini(&instance->transfers_bulk_full); \
+		transfer_list_fini(&instance->transfers_control_full); \
+		transfer_list_fini(&instance->transfers_control_slow); \
+		transfer_list_fini(&instance->transfers_interrupt); \
+		return ret; \
+	} else (void) 0
+
+	/* initialize TODO: check errors */
+	int ret;
+	ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
+	CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
+	ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL");
+	CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
+	ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW");
+	CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
+	ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
+	CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
+
+	transfer_list_set_next(&instance->transfers_control_full,
+		&instance->transfers_bulk_full);
+	transfer_list_set_next(&instance->transfers_control_slow,
+		&instance->transfers_control_full);
+	transfer_list_set_next(&instance->transfers_interrupt,
+		&instance->transfers_control_slow);
+
+	/*FSBR*/
+#ifdef FSBR
+	transfer_list_set_next(&instance->transfers_bulk_full,
+		&instance->transfers_control_full);
+#endif
+
+	instance->transfers[0][USB_TRANSFER_INTERRUPT] =
+	  &instance->transfers_interrupt;
+	instance->transfers[1][USB_TRANSFER_INTERRUPT] =
+	  &instance->transfers_interrupt;
+	instance->transfers[0][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_full;
+	instance->transfers[1][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_slow;
+	instance->transfers[0][USB_TRANSFER_BULK] =
+	  &instance->transfers_bulk_full;
+
+	return EOK;
+#undef CHECK_RET_CLEAR_RETURN
+}
+/*----------------------------------------------------------------------------*/
+int uhci_schedule(uhci_t *instance, batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	const int low_speed = (batch->speed == USB_SPEED_LOW);
+	if (!allowed_usb_packet(
+	    low_speed, batch->transfer_type, batch->max_packet_size)) {
+		usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
+			  low_speed ? "LOW" : "FULL" , batch->transfer_type,
+		    batch->max_packet_size);
+		return ENOTSUP;
+	}
+	/* TODO: check available bandwith here */
+
+	transfer_list_t *list =
+	    instance->transfers[low_speed][batch->transfer_type];
+	assert(list);
+	transfer_list_add_batch(list, batch);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+void uhci_interrupt(uhci_t *instance, uint16_t status)
+{
+	assert(instance);
+//	if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)
+//		return;
+//	usb_log_debug2("UHCI interrupt: %X.\n", status);
+	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);
+}
+/*----------------------------------------------------------------------------*/
+int uhci_interrupt_emulator(void* arg)
+{
+	usb_log_debug("Started interrupt emulator.\n");
+	uhci_t *instance = (uhci_t*)arg;
+	assert(instance);
+
+	while (1) {
+		uint16_t status = pio_read_16(&instance->registers->usbsts);
+		if (status != 0)
+			usb_log_debug2("UHCI status: %x.\n", status);
+		status |= 1;
+		uhci_interrupt(instance, status);
+		pio_write_16(&instance->registers->usbsts, 0x1f);
+		async_usleep(UHCI_CLEANER_TIMEOUT * 5);
+	}
+	return EOK;
+}
+/*---------------------------------------------------------------------------*/
+int uhci_debug_checker(void *arg)
+{
+	uhci_t *instance = (uhci_t*)arg;
+	assert(instance);
+	while (1) {
+		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);
+		if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
+			usb_log_debug2("Command: %X Status: %X Intr: %x\n",
+			    cmd, sts, intr);
+		}
+
+		uintptr_t frame_list =
+		    pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
+		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));
+		}
+		int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
+		usb_log_debug2("Framelist item: %d \n", frnum );
+
+		queue_head_t* qh = instance->transfers_interrupt.queue_head;
+
+		if ((instance->frame_list[frnum] & (~0xf)) != (uintptr_t)addr_to_phys(qh)) {
+			usb_log_debug("Interrupt QH: %p vs. %p.\n",
+				instance->frame_list[frnum] & (~0xf), addr_to_phys(qh));
+		}
+
+		if ((qh->next_queue & (~0xf))
+		  != (uintptr_t)addr_to_phys(instance->transfers_control_slow.queue_head)) {
+			usb_log_debug("Control Slow QH: %p vs. %p.\n", qh->next_queue & (~0xf),
+				addr_to_phys(instance->transfers_control_slow.queue_head));
+		}
+		qh = instance->transfers_control_slow.queue_head;
+
+		if ((qh->next_queue & (~0xf))
+		  != (uintptr_t)addr_to_phys(instance->transfers_control_full.queue_head)) {
+			usb_log_debug("Control Full QH: %p vs. %p.\n", qh->next_queue & (~0xf),
+				addr_to_phys(instance->transfers_control_full.queue_head));\
+		}
+		qh = instance->transfers_control_full.queue_head;
+
+		if ((qh->next_queue & (~0xf))
+		  != (uintptr_t)addr_to_phys(instance->transfers_bulk_full.queue_head)) {
+			usb_log_debug("Bulk QH: %p vs. %p.\n", qh->next_queue & (~0xf),
+				addr_to_phys(instance->transfers_bulk_full.queue_head));
+		}
+/*
+	uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
+	cmd |= UHCI_CMD_RUN_STOP;
+	pio_write_16(&instance->registers->usbcmd, cmd);
+*/
+		async_usleep(UHCI_DEBUGER_TIMEOUT);
+	}
+	return 0;
+}
+/*----------------------------------------------------------------------------*/
+bool allowed_usb_packet(
+	bool low_speed, usb_transfer_type_t transfer, size_t size)
+{
+	/* see USB specification chapter 5.5-5.8 for magic numbers used here */
+	switch(transfer) {
+		case USB_TRANSFER_ISOCHRONOUS:
+			return (!low_speed && size < 1024);
+		case USB_TRANSFER_INTERRUPT:
+			return size <= (low_speed ? 8 : 64);
+		case USB_TRANSFER_CONTROL: /* device specifies its own max size */
+			return (size <= (low_speed ? 8 : 64));
+		case USB_TRANSFER_BULK: /* device specifies its own max size */
+			return (!low_speed && size <= 64);
+	}
+	return false;
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/uhci.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2010 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_UHCI_H
+#define DRV_UHCI_UHCI_H
+
+#include <fibril.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <ddi.h>
+
+#include <usbhc_iface.h>
+
+#include "batch.h"
+#include "transfer_list.h"
+#include "utils/device_keeper.h"
+
+typedef struct uhci_regs {
+	uint16_t usbcmd;
+#define UHCI_CMD_MAX_PACKET (1 << 7)
+#define UHCI_CMD_CONFIGURE  (1 << 6)
+#define UHCI_CMD_DEBUG  (1 << 5)
+#define UHCI_CMD_FORCE_GLOBAL_RESUME  (1 << 4)
+#define UHCI_CMD_FORCE_GLOBAL_SUSPEND  (1 << 3)
+#define UHCI_CMD_GLOBAL_RESET  (1 << 2)
+#define UHCI_CMD_HCRESET  (1 << 1)
+#define UHCI_CMD_RUN_STOP  (1 << 0)
+
+	uint16_t usbsts;
+#define UHCI_STATUS_HALTED (1 << 5)
+#define UHCI_STATUS_PROCESS_ERROR (1 << 4)
+#define UHCI_STATUS_SYSTEM_ERROR (1 << 3)
+#define UHCI_STATUS_RESUME (1 << 2)
+#define UHCI_STATUS_ERROR_INTERRUPT (1 << 1)
+#define UHCI_STATUS_INTERRUPT (1 << 0)
+
+	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;
+	uint8_t sofmod;
+} regs_t;
+
+#define UHCI_FRAME_LIST_COUNT 1024
+#define UHCI_CLEANER_TIMEOUT 10000
+#define UHCI_DEBUGER_TIMEOUT 5000000
+
+typedef struct uhci {
+	device_keeper_t device_manager;
+
+	volatile regs_t *registers;
+
+	link_pointer_t *frame_list;
+
+	transfer_list_t transfers_bulk_full;
+	transfer_list_t transfers_control_full;
+	transfer_list_t transfers_control_slow;
+	transfer_list_t transfers_interrupt;
+
+	transfer_list_t *transfers[2][4];
+
+	irq_code_t interrupt_code;
+
+	fid_t cleaner;
+	fid_t debug_checker;
+
+	ddf_fun_t *ddf_instance;
+} uhci_t;
+
+/* init uhci specifics in device.driver_data */
+int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size);
+
+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(ddf_dev_t *dev)
+	{ return (uhci_t*)dev->driver_data; }
+
+static inline uhci_t * fun_to_uhci(ddf_fun_t *fun)
+	{ return (uhci_t*)fun->driver_data; }
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/uhci_struct/link_pointer.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/link_pointer.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/uhci_struct/link_pointer.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 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_LINK_POINTER_H
+#define DRV_UHCI_LINK_POINTER_H
+
+/* UHCI link pointer, used by many data structures */
+typedef uint32_t link_pointer_t;
+
+#define LINK_POINTER_TERMINATE_FLAG (1 << 0)
+#define LINK_POINTER_QUEUE_HEAD_FLAG (1 << 1)
+#define LINK_POINTER_ZERO_BIT_FLAG (1 << 2)
+#define LINK_POINTER_VERTICAL_FLAG (1 << 2)
+#define LINK_POINTER_RESERVED_FLAG (1 << 3)
+
+#define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/uhci-hcd/uhci_struct/queue_head.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,94 @@
+
+/*
+ * Copyright (c) 2010 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_QH_H
+#define DRV_UHCI_QH_H
+
+/* libc */
+#include <assert.h>
+
+#include "link_pointer.h"
+#include "utils/malloc32.h"
+
+typedef struct queue_head {
+	volatile link_pointer_t next_queue;
+	volatile link_pointer_t element;
+} __attribute__((packed)) queue_head_t;
+
+static inline void queue_head_init(queue_head_t *instance)
+{
+	assert(instance);
+
+	instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
+	instance->next_queue = 0 | LINK_POINTER_TERMINATE_FLAG;
+}
+
+static inline void queue_head_append_qh(queue_head_t *instance, uint32_t pa)
+{
+	if (pa) {
+		instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
+		    | LINK_POINTER_QUEUE_HEAD_FLAG;
+	}
+}
+
+static inline void queue_head_element_qh(queue_head_t *instance, uint32_t pa)
+{
+	if (pa) {
+		instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
+		    | LINK_POINTER_QUEUE_HEAD_FLAG;
+	}
+}
+
+static inline void queue_head_element_td(queue_head_t *instance, uint32_t pa)
+{
+	if (pa) {
+		instance->element = (pa & LINK_POINTER_ADDRESS_MASK);
+	}
+}
+
+static inline queue_head_t * queue_head_get() {
+	queue_head_t *ret = malloc32(sizeof(queue_head_t));
+	if (ret)
+		queue_head_init(ret);
+	return ret;
+}
+
+static inline void queue_head_dispose(queue_head_t *head)
+	{ free32(head); }
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,100 @@
+/*
+ * 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 <errno.h>
+#include <usb/debug.h>
+
+#include "transfer_descriptor.h"
+#include "utils/malloc32.h"
+
+void transfer_descriptor_init(transfer_descriptor_t *instance,
+    int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,
+    usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next)
+{
+	assert(instance);
+
+	instance->next = 0
+	    | LINK_POINTER_VERTICAL_FLAG
+	    | ((next != NULL) ? addr_to_phys(next) : LINK_POINTER_TERMINATE_FLAG);
+
+	instance->status = 0
+	  | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
+		| (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
+	  | TD_STATUS_ERROR_ACTIVE;
+
+	assert(size < 1024);
+	instance->device = 0
+		| (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
+		| (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
+		| ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
+		| ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
+		| ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
+
+	instance->buffer_ptr = 0;
+
+	if (size) {
+		instance->buffer_ptr = (uintptr_t)addr_to_phys(buffer);
+	}
+
+	usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n",
+		instance->next, instance->status, instance->device,
+	  instance->buffer_ptr, buffer);
+}
+/*----------------------------------------------------------------------------*/
+int transfer_descriptor_status(transfer_descriptor_t *instance)
+{
+	assert(instance);
+
+	if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
+		return ESTALL;
+
+	if ((instance->status & TD_STATUS_ERROR_CRC) != 0)
+		return EBADCHECKSUM;
+
+	if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
+		return EAGAIN;
+
+	if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
+		return EIO;
+
+	if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
+		return EAGAIN;
+
+	if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
+		return EAGAIN;
+
+	return EOK;
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2010 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_TRANSFER_DESCRIPTOR_H
+#define DRV_UHCI_TRANSFER_DESCRIPTOR_H
+
+#include <mem.h>
+#include <usb/usb.h>
+
+#include "link_pointer.h"
+
+/** UHCI Transfer Descriptor */
+typedef struct transfer_descriptor {
+	link_pointer_t next;
+
+	volatile uint32_t status;
+
+#define TD_STATUS_RESERVED_MASK 0xc000f800
+#define TD_STATUS_SPD_FLAG ( 1 << 29 )
+#define TD_STATUS_ERROR_COUNT_POS ( 27 )
+#define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
+#define TD_STATUS_ERROR_COUNT_DEFAULT 3
+#define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
+#define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
+#define TD_STATUS_COMPLETE_INTERRUPT_FLAG ( 1 << 24 )
+
+#define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
+#define TD_STATUS_ERROR_STALLED ( 1 << 22 )
+#define TD_STATUS_ERROR_BUFFER ( 1 << 21 )
+#define TD_STATUS_ERROR_BABBLE ( 1 << 20 )
+#define TD_STATUS_ERROR_NAK ( 1 << 19 )
+#define TD_STATUS_ERROR_CRC ( 1 << 18 )
+#define TD_STATUS_ERROR_BIT_STUFF ( 1 << 17 )
+#define TD_STATUS_ERROR_RESERVED ( 1 << 16 )
+#define TD_STATUS_ERROR_POS 16
+#define TD_STATUS_ERROR_MASK ( 0xff )
+
+#define TD_STATUS_ACTLEN_POS 0
+#define TD_STATUS_ACTLEN_MASK 0x7ff
+
+	volatile uint32_t device;
+
+#define TD_DEVICE_MAXLEN_POS 21
+#define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
+#define TD_DEVICE_RESERVED_FLAG ( 1 << 20 )
+#define TD_DEVICE_DATA_TOGGLE_ONE_FLAG ( 1 << 19 )
+#define TD_DEVICE_ENDPOINT_POS 15
+#define TD_DEVICE_ENDPOINT_MASK ( 0xf )
+#define TD_DEVICE_ADDRESS_POS 8
+#define TD_DEVICE_ADDRESS_MASK ( 0x7f )
+#define TD_DEVICE_PID_POS 0
+#define TD_DEVICE_PID_MASK ( 0xff )
+
+	volatile uint32_t buffer_ptr;
+
+	/* there is 16 bytes of data available here, according to UHCI
+	 * Design guide, according to linux kernel the hardware does not care
+	 * we don't use it anyway
+	 */
+} __attribute__((packed)) transfer_descriptor_t;
+
+
+void transfer_descriptor_init(transfer_descriptor_t *instance,
+    int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,
+    usb_target_t target, int pid, void *buffer, transfer_descriptor_t * next);
+
+int transfer_descriptor_status(transfer_descriptor_t *instance);
+
+static inline size_t transfer_descriptor_actual_size(
+    transfer_descriptor_t *instance)
+{
+	assert(instance);
+	return
+	    ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
+}
+
+static inline bool transfer_descriptor_is_active(
+    transfer_descriptor_t *instance)
+{
+	assert(instance);
+	return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/utils/device_keeper.c
===================================================================
--- uspace/drv/uhci-hcd/utils/device_keeper.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/utils/device_keeper.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,154 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <assert.h>
+#include <errno.h>
+
+#include "device_keeper.h"
+
+/*----------------------------------------------------------------------------*/
+void device_keeper_init(device_keeper_t *instance)
+{
+	assert(instance);
+	fibril_mutex_initialize(&instance->guard);
+	fibril_condvar_initialize(&instance->default_address_occupied);
+	instance->last_address = 0;
+	unsigned i = 0;
+	for (; i < USB_ADDRESS_COUNT; ++i) {
+		instance->devices[i].occupied = false;
+		instance->devices[i].handle = 0;
+	}
+}
+/*----------------------------------------------------------------------------*/
+void device_keeper_reserve_default(
+    device_keeper_t *instance, usb_speed_t speed)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	while (instance->devices[USB_ADDRESS_DEFAULT].occupied) {
+		fibril_condvar_wait(&instance->default_address_occupied,
+		    &instance->guard);
+	}
+	instance->devices[USB_ADDRESS_DEFAULT].occupied = true;
+	instance->devices[USB_ADDRESS_DEFAULT].speed = speed;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+void device_keeper_release_default(device_keeper_t *instance)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	instance->devices[USB_ADDRESS_DEFAULT].occupied = false;
+	fibril_mutex_unlock(&instance->guard);
+	fibril_condvar_signal(&instance->default_address_occupied);
+}
+/*----------------------------------------------------------------------------*/
+usb_address_t device_keeper_request(
+    device_keeper_t *instance, usb_speed_t speed)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+
+	usb_address_t new_address = instance->last_address + 1;
+	while (instance->devices[new_address].occupied) {
+		if (new_address == instance->last_address) {
+			fibril_mutex_unlock(&instance->guard);
+			return ENOSPC;
+		}
+		if (new_address == USB11_ADDRESS_MAX)
+			new_address = 1;
+		++new_address;
+	}
+
+	assert(new_address != USB_ADDRESS_DEFAULT);
+	assert(instance->devices[new_address].occupied == false);
+	instance->devices[new_address].occupied = true;
+	instance->devices[new_address].speed = speed;
+	instance->last_address = new_address;
+	fibril_mutex_unlock(&instance->guard);
+	return new_address;
+}
+/*----------------------------------------------------------------------------*/
+void device_keeper_bind(
+    device_keeper_t *instance, usb_address_t address, devman_handle_t handle)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	assert(address > 0);
+	assert(address <= USB11_ADDRESS_MAX);
+	assert(instance->devices[address].occupied);
+	instance->devices[address].handle = handle;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+void device_keeper_release(device_keeper_t *instance, usb_address_t address)
+{
+	assert(instance);
+	assert(address > 0);
+	assert(address <= USB11_ADDRESS_MAX);
+
+	fibril_mutex_lock(&instance->guard);
+	assert(instance->devices[address].occupied);
+	instance->devices[address].occupied = false;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+usb_address_t device_keeper_find(
+    device_keeper_t *instance, devman_handle_t handle)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	usb_address_t address = 1;
+	while (address <= USB11_ADDRESS_MAX) {
+		if (instance->devices[address].handle == handle) {
+			fibril_mutex_unlock(&instance->guard);
+			return address;
+		}
+		++address;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ENOENT;
+}
+/*----------------------------------------------------------------------------*/
+usb_speed_t device_keeper_speed(
+    device_keeper_t *instance, usb_address_t address)
+{
+	assert(instance);
+	assert(address >= 0);
+	assert(address <= USB11_ADDRESS_MAX);
+	return instance->devices[address].speed;
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/utils/device_keeper.h
===================================================================
--- uspace/drv/uhci-hcd/utils/device_keeper.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/utils/device_keeper.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,74 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef UTILS_DEVICE_KEEPER_H
+#define UTILS_DEVICE_KEEPER_H
+#include <devman.h>
+#include <fibril_synch.h>
+#include <usb/usb.h>
+
+#define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1)
+
+struct usb_device_info {
+	usb_speed_t speed;
+	bool occupied;
+	devman_handle_t handle;
+};
+
+typedef struct device_keeper {
+	struct usb_device_info devices[USB_ADDRESS_COUNT];
+	fibril_mutex_t guard;
+	fibril_condvar_t default_address_occupied;
+	usb_address_t last_address;
+} device_keeper_t;
+
+void device_keeper_init(device_keeper_t *instance);
+void device_keeper_reserve_default(
+    device_keeper_t *instance, usb_speed_t speed);
+void device_keeper_release_default(device_keeper_t *instance);
+
+usb_address_t device_keeper_request(
+    device_keeper_t *instance, usb_speed_t speed);
+void device_keeper_bind(
+    device_keeper_t *instance, usb_address_t address, devman_handle_t handle);
+void device_keeper_release(device_keeper_t *instance, usb_address_t address);
+usb_address_t device_keeper_find(
+    device_keeper_t *instance, devman_handle_t handle);
+
+usb_speed_t device_keeper_speed(
+    device_keeper_t *instance, usb_address_t address);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/utils/malloc32.h
===================================================================
--- uspace/drv/uhci-hcd/utils/malloc32.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-hcd/utils/malloc32.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010 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_TRANSLATOR_H
+#define DRV_UHCI_TRANSLATOR_H
+
+#include <usb/usbmem.h>
+
+#include <assert.h>
+#include <malloc.h>
+#include <mem.h>
+#include <as.h>
+
+#define UHCI_STRCUTURES_ALIGNMENT 16
+#define UHCI_REQUIRED_PAGE_SIZE 4096
+
+static inline uintptr_t addr_to_phys(void *addr)
+{
+	uintptr_t result;
+	int ret = as_get_physical_mapping(addr, &result);
+
+	assert(ret == 0);
+	return (result | ((uintptr_t)addr & 0xfff));
+}
+
+static inline void * malloc32(size_t size)
+	{ return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
+
+static inline void * get_page()
+{
+	void * free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
+	assert(free_address);
+	if (free_address == 0)
+		return 0;
+	void* ret =
+	  as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
+		  AS_AREA_READ | AS_AREA_WRITE);
+	if (ret != free_address)
+		return 0;
+	return ret;
+}
+
+static inline void free32(void *addr)
+	{ if (addr) free(addr); }
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/Makefile
===================================================================
--- uspace/drv/uhci-rhd/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-rhd/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2010 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.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+BINARY = uhci-rhd
+
+SOURCES = \
+	main.c \
+	port.c \
+	port_status.c \
+	root_hub.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/uhci-rhd/main.c
===================================================================
--- uspace/drv/uhci-rhd/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-rhd/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, 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 <ddf/driver.h>
+#include <devman.h>
+#include <device/hw_res.h>
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+
+#include <errno.h>
+
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+#define NAME "uhci-rhd"
+static int hc_get_my_registers(ddf_dev_t *dev,
+    uintptr_t *io_reg_address, size_t *io_reg_size);
+
+static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+	assert(fun->driver_data);
+	assert(handle);
+
+	*handle = ((uhci_root_hub_t*)fun->driver_data)->hc_handle;
+
+	return EOK;
+}
+
+static usb_iface_t uhci_rh_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle,
+	.get_address = usb_iface_get_address_hub_impl
+};
+
+static ddf_dev_ops_t uhci_rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface,
+};
+
+static int uhci_rh_add_device(ddf_dev_t *device)
+{
+	if (!device)
+		return ENOTSUP;
+
+	usb_log_debug2("%s called device %d\n", __FUNCTION__, device->handle);
+
+	//device->ops = &uhci_rh_ops;
+	(void) uhci_rh_ops;
+
+	uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t));
+	if (!rh) {
+		usb_log_error("Failed to allocate memory for driver instance.\n");
+		return ENOMEM;
+	}
+
+	uintptr_t io_regs = 0;
+	size_t io_size = 0;
+
+	int ret = hc_get_my_registers(device, &io_regs, &io_size);
+	assert(ret == EOK);
+
+	/* TODO: verify values from hc */
+	usb_log_info("I/O regs at 0x%X (size %zu).\n", io_regs, io_size);
+	ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
+	if (ret != EOK) {
+		usb_log_error("Failed(%d) to initialize driver instance.\n", ret);
+		free(rh);
+		return ret;
+	}
+
+	device->driver_data = rh;
+	usb_log_info("Sucessfully initialized driver instance for device:%d.\n",
+	    device->handle);
+	return EOK;
+}
+
+static driver_ops_t uhci_rh_driver_ops = {
+	.add_device = uhci_rh_add_device,
+};
+
+static driver_t uhci_rh_driver = {
+	.name = NAME,
+	.driver_ops = &uhci_rh_driver_ops
+};
+/*----------------------------------------------------------------------------*/
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	return ddf_driver_main(&uhci_rh_driver);
+}
+/*----------------------------------------------------------------------------*/
+int hc_get_my_registers(ddf_dev_t *dev,
+    uintptr_t *io_reg_address, size_t *io_reg_size)
+{
+	assert(dev != NULL);
+
+	int parent_phone = devman_parent_device_connect(dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	int rc;
+
+	hw_resource_list_t hw_resources;
+	rc = hw_res_get_resource_list(parent_phone, &hw_resources);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	uintptr_t io_address = 0;
+	size_t io_size = 0;
+	bool io_found = false;
+
+	size_t i;
+	for (i = 0; i < hw_resources.count; i++) {
+		hw_resource_t *res = &hw_resources.resources[i];
+		switch (res->type) {
+			case IO_RANGE:
+				io_address = (uintptr_t)
+				    res->res.io_range.address;
+				io_size = res->res.io_range.size;
+				io_found = true;
+				break;
+			default:
+				break;
+		}
+	}
+
+	if (!io_found) {
+		rc = ENOENT;
+		goto leave;
+	}
+
+	if (io_reg_address != NULL) {
+		*io_reg_address = io_address;
+	}
+	if (io_reg_size != NULL) {
+		*io_reg_size = io_size;
+	}
+	rc = EOK;
+leave:
+	async_hangup(parent_phone);
+
+	return rc;
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/port.c
===================================================================
--- uspace/drv/uhci-rhd/port.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-rhd/port.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,260 @@
+/*
+ * 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 <errno.h>
+#include <str_error.h>
+#include <fibril_synch.h>
+
+#include <usb/usb.h>    /* usb_address_t */
+#include <usb/usbdevice.h>
+#include <usb/hub.h>
+#include <usb/request.h>
+#include <usb/debug.h>
+#include <usb/recognise.h>
+
+#include "port.h"
+#include "port_status.h"
+
+static int uhci_port_new_device(uhci_port_t *port, uint16_t status);
+static int uhci_port_remove_device(uhci_port_t *port);
+static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
+static int uhci_port_check(void *port);
+static int new_device_enable_port(int portno, void *arg);
+
+int uhci_port_init(
+  uhci_port_t *port, port_status_t *address, unsigned number,
+  unsigned usec, ddf_dev_t *rh)
+{
+	assert(port);
+	port->address = address;
+	port->number = number;
+	port->wait_period_usec = usec;
+	port->attached_device = 0;
+	port->rh = rh;
+	int rc = usb_hc_connection_initialize_from_device(
+	    &port->hc_connection, rh);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize connection to HC.");
+		return rc;
+	}
+
+	port->checker = fibril_create(uhci_port_check, port);
+	if (port->checker == 0) {
+		usb_log_error("Port(%p - %d): failed to launch root hub fibril.",
+		    port->address, port->number);
+		return ENOMEM;
+	}
+	fibril_add_ready(port->checker);
+	usb_log_debug("Port(%p - %d): Added fibril. %x\n",
+	    port->address, port->number, port->checker);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+void uhci_port_fini(uhci_port_t *port)
+{
+// TODO: destroy fibril
+// TODO: hangup phone
+//	fibril_teardown(port->checker);
+	return;
+}
+/*----------------------------------------------------------------------------*/
+int uhci_port_check(void *port)
+{
+	uhci_port_t *port_instance = port;
+	assert(port_instance);
+//	port_status_write(port_instance->address, 0);
+
+	unsigned count = 0;
+
+	while (1) {
+		async_usleep(port_instance->wait_period_usec);
+
+		/* read register value */
+		port_status_t port_status =
+			port_status_read(port_instance->address);
+
+		/* debug print */
+		static fibril_mutex_t dbg_mtx = FIBRIL_MUTEX_INITIALIZER(dbg_mtx);
+		fibril_mutex_lock(&dbg_mtx);
+		usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n",
+		  port_instance->address, port_instance->number, port_status, count++);
+//		print_port_status(port_status);
+		fibril_mutex_unlock(&dbg_mtx);
+
+		if ((port_status & STATUS_CONNECTED_CHANGED) != 0) {
+			usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
+			    port_instance->address, port_instance->number, port_status);
+
+
+			int rc = usb_hc_connection_open(
+			    &port_instance->hc_connection);
+			if (rc != EOK) {
+				usb_log_error("Port(%p - %d): Failed to connect to HC.",
+				    port_instance->address, port_instance->number);
+				continue;
+			}
+
+			/* remove any old device */
+			if (port_instance->attached_device) {
+				usb_log_debug("Port(%p - %d): Removing device.\n",
+				    port_instance->address, port_instance->number);
+				uhci_port_remove_device(port_instance);
+			}
+
+			if ((port_status & STATUS_CONNECTED) != 0) {
+				/* new device */
+				uhci_port_new_device(port_instance, port_status);
+			} else {
+				/* ack changes by writing one to WC bits */
+				port_status_write(port_instance->address, port_status);
+				usb_log_debug("Port(%p - %d): Change status ACK.\n",
+						port_instance->address, port_instance->number);
+			}
+
+			rc = usb_hc_connection_close(
+			    &port_instance->hc_connection);
+			if (rc != EOK) {
+				usb_log_error("Port(%p - %d): Failed to disconnect from HC.",
+				    port_instance->address, port_instance->number);
+			}
+		}
+	}
+	return EOK;
+}
+
+/** 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_debug2("Port(%p - %d): new_device_enable_port.\n",
+	    port->address, port->number);
+
+	/*
+	 * 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);
+
+
+	/* The hub maintains the reset signal to that port for 10 ms
+	 * (See Section 11.5.1.5)
+	 */
+	{
+		usb_log_debug("Port(%p - %d): Reset Signal start.\n",
+		    port->address, port->number);
+		port_status_t port_status =
+			port_status_read(port->address);
+		port_status |= STATUS_IN_RESET;
+		port_status_write(port->address, port_status);
+		async_usleep(10000);
+		port_status =
+			port_status_read(port->address);
+		port_status &= ~STATUS_IN_RESET;
+		port_status_write(port->address, port_status);
+		usb_log_debug("Port(%p - %d): Reset Signal stop.\n",
+		    port->address, port->number);
+	}
+
+	/* Enable the port. */
+	uhci_port_set_enabled(port, true);
+
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+static int uhci_port_new_device(uhci_port_t *port, uint16_t status)
+{
+	assert(port);
+	assert(usb_hc_connection_is_opened(&port->hc_connection));
+
+	usb_log_info("Port(%p-%d): Detected new device.\n",
+	    port->address, port->number);
+
+	usb_address_t dev_addr;
+	int rc = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
+	    ((status & STATUS_LOW_SPEED) != 0) ? USB_SPEED_LOW : USB_SPEED_FULL,
+	    new_device_enable_port, port->number, port,
+	    &dev_addr, &port->attached_device, NULL, NULL, NULL);
+
+	if (rc != EOK) {
+		usb_log_error("Port(%p-%d): Failed(%d) adding new device: %s.\n",
+		    port->address, port->number, rc, str_error(rc));
+		uhci_port_set_enabled(port, false);
+		return rc;
+	}
+
+	usb_log_info("Port(%p-%d): New device has address %d (handle %zu).\n",
+	    port->address, port->number, dev_addr, port->attached_device);
+
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+static int uhci_port_remove_device(uhci_port_t *port)
+{
+	usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n",
+		port->address, port->number, (unsigned int)port->attached_device);
+//	uhci_port_set_enabled(port, false);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
+{
+	assert(port);
+
+	/* read register value */
+	port_status_t port_status
+		= port_status_read(port->address);
+
+	/* enable port: register write */
+	if (enabled) {
+		port_status |= STATUS_ENABLED;
+	} else {
+		port_status &= ~STATUS_ENABLED;
+	}
+	port_status_write(port->address, port_status);
+
+	usb_log_info("Port(%p-%d): %sabled port.\n",
+		port->address, port->number, enabled ? "En" : "Dis");
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/port.h
===================================================================
--- uspace/drv/uhci-rhd/port.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-rhd/port.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010 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 port driver
+ */
+#ifndef DRV_UHCI_PORT_H
+#define DRV_UHCI_PORT_H
+
+#include <assert.h>
+#include <ddf/driver.h>
+#include <stdint.h>
+#include <usb/usbdevice.h>
+
+#include "port_status.h"
+
+typedef struct uhci_port
+{
+	port_status_t *address;
+	unsigned number;
+	unsigned wait_period_usec;
+	usb_hc_connection_t hc_connection;
+	ddf_dev_t *rh;
+	devman_handle_t attached_device;
+	fid_t checker;
+} uhci_port_t;
+
+int uhci_port_init(
+  uhci_port_t *port, port_status_t *address, unsigned number,
+  unsigned usec, ddf_dev_t *rh);
+
+void uhci_port_fini(uhci_port_t *port);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/port_status.c
===================================================================
--- uspace/drv/uhci-rhd/port_status.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-rhd/port_status.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,72 @@
+/*
+ * 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 <assert.h>
+#include <stdio.h>
+
+#include <usb/debug.h>
+
+#include "port_status.h"
+
+struct flag_name
+{
+	uint16_t flag;
+	const char *name;
+};
+
+static const struct flag_name flags[] =
+{
+	{ STATUS_SUSPEND, "suspended" },
+	{ STATUS_IN_RESET, "in reset" },
+	{ STATUS_LOW_SPEED, "low speed device" },
+	{ STATUS_ALWAYS_ONE, "always 1 bit" },
+	{ STATUS_RESUME, "resume" },
+	{ STATUS_LINE_D_MINUS, "line D- value" },
+	{ STATUS_LINE_D_PLUS, "line D+ value" },
+	{ STATUS_ENABLED_CHANGED, "enabled changed" },
+	{ STATUS_ENABLED, "enabled" },
+	{ STATUS_CONNECTED_CHANGED, "connected changed" },
+	{ STATUS_CONNECTED, "connected" }
+};
+
+void print_port_status(port_status_t value)
+{
+	unsigned i = 0;
+	for (;i < sizeof(flags)/sizeof(struct flag_name); ++i) {
+		usb_log_debug2("\t%s status: %s.\n", flags[i].name,
+		  ((value & flags[i].flag) != 0) ? "YES" : "NO");
+	}
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/port_status.h
===================================================================
--- uspace/drv/uhci-rhd/port_status.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-rhd/port_status.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 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_TD_PORT_STATUS_H
+#define DRV_UHCI_TD_PORT_STATUS_H
+
+#include <libarch/ddi.h> /* pio_read and pio_write */
+
+#include <stdint.h>
+
+typedef uint16_t port_status_t;
+
+#define STATUS_CONNECTED         (1 << 0)
+#define STATUS_CONNECTED_CHANGED (1 << 1)
+#define STATUS_ENABLED           (1 << 2)
+#define STATUS_ENABLED_CHANGED   (1 << 3)
+#define STATUS_LINE_D_PLUS       (1 << 4)
+#define STATUS_LINE_D_MINUS      (1 << 5)
+#define STATUS_RESUME            (1 << 6)
+#define STATUS_ALWAYS_ONE        (1 << 7)
+
+#define STATUS_LOW_SPEED (1 <<  8)
+#define STATUS_IN_RESET  (1 <<  9)
+#define STATUS_SUSPEND   (1 << 12)
+
+static inline port_status_t port_status_read(port_status_t * address)
+	{ return pio_read_16(address); }
+
+static inline void port_status_write(
+  port_status_t *address, port_status_t value)
+	{ pio_write_16(address, value); }
+
+void print_port_status(const port_status_t status);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/root_hub.c
===================================================================
--- uspace/drv/uhci-rhd/root_hub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-rhd/root_hub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,87 @@
+/*
+ * 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 <errno.h>
+#include <stdint.h>
+#include <ddi.h>
+#include <devman.h>
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+int uhci_root_hub_init(
+  uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh)
+{
+	assert(instance);
+	assert(rh);
+	int ret;
+
+	/* allow access to root hub registers */
+	assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT == size);
+	port_status_t *regs;
+	ret = pio_enable(addr, size, (void**)&regs);
+
+	if (ret < 0) {
+		usb_log_error("Failed to gain access to port registers at %p\n", regs);
+		return ret;
+	}
+
+	/* add fibrils for periodic port checks */
+	unsigned i = 0;
+	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
+		/* mind pointer arithmetics */
+		ret = uhci_port_init(
+		  &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
+		if (ret != EOK) {
+			unsigned j = 0;
+			for (;j < i; ++j)
+				uhci_port_fini(&instance->ports[j]);
+			return ret;
+		}
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int uhci_root_hub_fini( uhci_root_hub_t* instance )
+{
+	assert( instance );
+	// TODO:
+	//destroy fibril here
+	//disable access to registers
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/root_hub.h
===================================================================
--- uspace/drv/uhci-rhd/root_hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-rhd/root_hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010 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_ROOT_HUB_H
+#define DRV_UHCI_ROOT_HUB_H
+
+#include <fibril.h>
+#include <ddf/driver.h>
+
+#include "port.h"
+
+#define UHCI_ROOT_HUB_PORT_COUNT 2
+#define ROOT_HUB_WAIT_USEC 5000000 /* 5 seconds */
+
+typedef struct root_hub {
+	uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT];
+	devman_handle_t hc_handle;
+} uhci_root_hub_t;
+
+int uhci_root_hub_init(
+  uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh);
+
+int uhci_root_hub_fini(uhci_root_hub_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/uhci-rhd.ma
===================================================================
--- uspace/drv/uhci-rhd/uhci-rhd.ma	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/uhci-rhd/uhci-rhd.ma	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,1 @@
+10 usb&uhci&root-hub
Index: pace/drv/uhci/Makefile
===================================================================
--- uspace/drv/uhci/Makefile	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,38 +1,0 @@
-#
-# Copyright (c) 2010 Vojtech Horky
-# 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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include
-BINARY = uhci
-
-SOURCES = \
-	main.c \
-	transfers.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/uhci/main.c
===================================================================
--- uspace/drv/uhci/main.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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.
- */
-#include <usb/hcdhubd.h>
-#include <usb_iface.h>
-#include <usb/debug.h>
-#include <errno.h>
-#include <driver.h>
-#include "uhci.h"
-
-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 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 int uhci_add_device(device_t *device)
-{
-	usb_dprintf(NAME, 1, "uhci_add_device() called\n");
-	device->ops = &uhci_ops;
-
-	/*
-	 * We need to announce the presence of our root hub.
-	 */
-	usb_dprintf(NAME, 2, "adding root hub\n");
-	usb_hcd_add_root_hub(device);
-
-	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_dprintf_enable(NAME, 5);
-
-	return driver_main(&uhci_driver);
-}
Index: pace/drv/uhci/transfers.c
===================================================================
--- uspace/drv/uhci/transfers.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,160 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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.
- */
-#include <usb/hcdhubd.h>
-#include <errno.h>
-
-#include "uhci.h"
-
-static int enqueue_transfer_out(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)
-{
-	printf(NAME ": transfer OUT [%d.%d (%s); %zu]\n",
-	    target.address, target.endpoint,
-	    usb_str_transfer_type(transfer_type),
-	    size);
-
-	return ENOTSUP;
-}
-
-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)
-{
-	printf(NAME ": transfer SETUP [%d.%d (%s); %zu]\n",
-	    target.address, target.endpoint,
-	    usb_str_transfer_type(transfer_type),
-	    size);
-
-	return ENOTSUP;
-}
-
-static int enqueue_transfer_in(device_t *dev,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	printf(NAME ": transfer IN [%d.%d (%s); %zu]\n",
-	    target.address, target.endpoint,
-	    usb_str_transfer_type(transfer_type),
-	    size);
-
-	return ENOTSUP;
-}
-
-
-static int get_address(device_t *dev, devman_handle_t handle,
-    usb_address_t *address)
-{
-	return ENOTSUP;
-}
-
-static int interrupt_out(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return enqueue_transfer_out(dev, target, USB_TRANSFER_INTERRUPT,
-	    data, size,
-	    callback, arg);
-}
-
-static int interrupt_in(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	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,
-    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,
-    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);
-}
-
-static int control_read_setup(device_t *dev, usb_target_t target,
-    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,
-    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);
-}
-
-
-usbhc_iface_t uhci_iface = {
-	.tell_address = get_address,
-	.interrupt_out = interrupt_out,
-	.interrupt_in = interrupt_in,
-	.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: pace/drv/uhci/uhci.h
===================================================================
--- uspace/drv/uhci/uhci.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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_UHCI_H
-#define DRV_UHCI_UHCI_H
-
-#include <usbhc_iface.h>
-
-#define NAME "uhci"
-
-usbhc_iface_t uhci_iface;
-
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci/uhci.ma
===================================================================
--- uspace/drv/uhci/uhci.ma	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,2 +1,0 @@
-10 pci/ven=8086&dev=7020
-
Index: uspace/drv/usbhid/Makefile
===================================================================
--- uspace/drv/usbhid/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2010-2011 Vojtech Horky
+# 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.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+BINARY = usbhid
+
+STOLEN_LAYOUT_SOURCES = \
+	layout/us_qwerty.c \
+	layout/us_dvorak.c \
+	layout/cz.c
+
+SOURCES = \
+	main.c \
+	conv.c \
+	hidreq.c \
+	kbddev.c \
+	hiddev.c \
+	$(STOLEN_LAYOUT_SOURCES)
+
+EXTRA_CLEAN = $(STOLEN_LAYOUT_SOURCES)
+
+SRV_KBD = $(USPACE_PREFIX)/srv/hid/kbd
+
+include $(USPACE_PREFIX)/Makefile.common
+
+layout/%.c: $(SRV_KBD)/layout/%.c
+	ln -sfn ../$< $@
Index: uspace/drv/usbhid/conv.c
===================================================================
--- uspace/drv/usbhid/conv.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/conv.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB scancode parser.
+ */
+
+#include <io/keycode.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <usb/debug.h>
+#include "conv.h"
+
+static int scanmap_simple[255] = {
+
+//	[0x29] = KC_BACKTICK,
+
+//	[0x02] = KC_1,
+//	[0x03] = KC_2,
+	[0x04] = KC_A,
+	[0x05] = KC_B,
+	[0x06] = KC_C,
+	[0x07] = KC_D,
+	[0x08] = KC_E,
+	[0x09] = KC_F,
+	[0x0a] = KC_G,
+	[0x0b] = KC_H,
+	[0x0c] = KC_I,
+	[0x0d] = KC_J,
+	[0x0e] = KC_K,
+	[0x0f] = KC_L,
+	[0x10] = KC_M,
+	[0x11] = KC_N,
+	[0x12] = KC_O,
+	[0x13] = KC_P,
+	[0x14] = KC_Q,
+	[0x15] = KC_R,
+	[0x16] = KC_S,
+	[0x17] = KC_T,
+	[0x18] = KC_U,
+	[0x19] = KC_V,
+	[0x1a] = KC_W,
+	[0x1b] = KC_X,
+	[0x1c] = KC_Y,
+	[0x1d] = KC_Z,
+
+	[0x1e] = KC_1,
+	[0x1f] = KC_2,
+	[0x20] = KC_3,
+	[0x21] = KC_4,
+	[0x22] = KC_5,
+	[0x23] = KC_6,
+	[0x24] = KC_7,
+	[0x25] = KC_8,
+	[0x26] = KC_9,
+	[0x27] = KC_0,
+	
+	[0x28] = KC_ENTER,
+	[0x29] = KC_ESCAPE,
+	[0x2a] = KC_BACKSPACE,
+	[0x2b] = KC_TAB,
+	[0x2c] = KC_SPACE,
+
+	[0x2d] = KC_MINUS,  // same as DASH? (- or _)
+	[0x2e] = KC_EQUALS,
+	[0x2f] = KC_LBRACKET,
+	[0x30] = KC_RBRACKET,
+	[0x31] = KC_BACKSLASH,
+	//[0x32] = KC_,	// TODO: HASH??? maybe some as 0x31 - backslash
+	[0x33] = KC_SEMICOLON,
+	[0x34] = KC_QUOTE,  // same as APOSTROPHE? (')
+	[0x35] = KC_BACKTICK,  // same as GRAVE ACCENT?? (`)
+	[0x36] = KC_COMMA,
+	[0x37] = KC_PERIOD,
+	[0x38] = KC_SLASH,
+
+	[0x39] = KC_CAPS_LOCK,
+	
+	[0x3a] = KC_F1,
+	[0x3b] = KC_F2,
+	[0x3c] = KC_F3,
+	[0x3d] = KC_F4,
+	[0x3e] = KC_F5,
+	[0x3f] = KC_F6,
+	[0x40] = KC_F7,
+	[0x41] = KC_F8,
+	[0x42] = KC_F9,
+	[0x43] = KC_F10,
+	[0x44] = KC_F11,
+	[0x45] = KC_F12,
+	
+	[0x46] = KC_PRTSCR,
+	[0x47] = KC_SCROLL_LOCK,
+	[0x48] = KC_PAUSE,
+	[0x49] = KC_INSERT,
+	[0x4a] = KC_HOME,
+	[0x4b] = KC_PAGE_UP,
+	[0x4c] = KC_DELETE,
+	[0x4d] = KC_END,
+	[0x4e] = KC_PAGE_DOWN,
+	[0x4f] = KC_RIGHT,
+	[0x50] = KC_LEFT,
+	[0x51] = KC_DOWN,
+	[0x52] = KC_UP,
+	
+	//[0x64] = // some funny key
+	
+	[0xe0] = KC_LCTRL,
+	[0xe1] = KC_LSHIFT,
+	[0xe2] = KC_LALT,
+	//[0xe3] = KC_L	// TODO: left GUI
+	[0xe4] = KC_RCTRL,
+	[0xe5] = KC_RSHIFT,
+	[0xe6] = KC_RALT,
+	//[0xe7] = KC_R	// TODO: right GUI
+	
+	[0x53] = KC_NUM_LOCK,
+	[0x54] = KC_NSLASH,
+	[0x55] = KC_NTIMES,
+	[0x56] = KC_NMINUS,
+	[0x57] = KC_NPLUS,
+	[0x58] = KC_NENTER,
+	[0x59] = KC_N1,
+	[0x5a] = KC_N2,
+	[0x5b] = KC_N3,
+	[0x5c] = KC_N4,
+	[0x5d] = KC_N5,
+	[0x5e] = KC_N6,
+	[0x5f] = KC_N7,
+	[0x60] = KC_N8,
+	[0x61] = KC_N9,
+	[0x62] = KC_N0,
+	[0x63] = KC_NPERIOD
+	
+};
+
+unsigned int usbhid_parse_scancode(int scancode)
+{
+	unsigned int key;
+	int *map = scanmap_simple;
+	size_t map_length = sizeof(scanmap_simple) / sizeof(int);
+
+	if ((scancode < 0) || ((size_t) scancode >= map_length))
+		return -1;
+
+	key = map[scancode];
+	
+	return key;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/conv.h
===================================================================
--- uspace/drv/usbhid/conv.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/conv.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB scancode parser.
+ */
+
+#ifndef USBHID_CONV_H_
+#define USBHID_CONV_H_
+
+unsigned int usbhid_parse_scancode(int scancode);
+
+#endif /* USBHID_CONV_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/descdump.c
===================================================================
--- uspace/drv/usbhid/descdump.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/descdump.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2010 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * Descriptor dumping.
+ */
+
+#include <usb/classes/hid.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "descdump.h"
+
+/*----------------------------------------------------------------------------*/
+
+#define BYTES_PER_LINE 12
+
+static void dump_buffer(const char *msg, const uint8_t *buffer, size_t length)
+{
+	printf("%s\n", msg);
+
+	size_t i;
+	for (i = 0; i < length; i++) {
+		printf("  0x%02X", buffer[i]);
+		if (((i > 0) && (((i+1) % BYTES_PER_LINE) == 0))
+		    || (i + 1 == length)) {
+			printf("\n");
+		}
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+#define INDENT "  "
+
+void dump_standard_configuration_descriptor(
+    int index, const usb_standard_configuration_descriptor_t *d)
+{
+	bool self_powered = d->attributes & 64;
+	bool remote_wakeup = d->attributes & 32;
+	
+	printf("Standard configuration descriptor #%d\n", index);
+	printf(INDENT "bLength = %d\n", d->length);
+	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
+	printf(INDENT "wTotalLength = %d\n", d->total_length);
+	printf(INDENT "bNumInterfaces = %d\n", d->interface_count);
+	printf(INDENT "bConfigurationValue = %d\n", d->configuration_number);
+	printf(INDENT "iConfiguration = %d\n", d->str_configuration);
+	printf(INDENT "bmAttributes = %d [%s%s%s]\n", d->attributes,
+	    self_powered ? "self-powered" : "",
+	    (self_powered & remote_wakeup) ? ", " : "",
+	    remote_wakeup ? "remote-wakeup" : "");
+	printf(INDENT "MaxPower = %d (%dmA)\n", d->max_power,
+	    2 * d->max_power);
+	// printf(INDENT " = %d\n", d->);
+}
+
+void dump_standard_interface_descriptor(
+    const usb_standard_interface_descriptor_t *d)
+{
+	printf("Standard interface descriptor\n");
+	printf(INDENT "bLength = %d\n", d->length);
+	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
+	printf(INDENT "bInterfaceNumber = %d\n", d->interface_number);
+	printf(INDENT "bAlternateSetting = %d\n", d->alternate_setting);
+	printf(INDENT "bNumEndpoints = %d\n", d->endpoint_count);
+	printf(INDENT "bInterfaceClass = %d\n", d->interface_class);
+	printf(INDENT "bInterfaceSubClass = %d\n", d->interface_subclass);
+	printf(INDENT "bInterfaceProtocol = %d\n", d->interface_protocol);
+	printf(INDENT "iInterface = %d\n", d->str_interface);
+}
+
+void dump_standard_endpoint_descriptor(
+    const usb_standard_endpoint_descriptor_t *d)
+{
+	const char *transfer_type;
+	switch (d->attributes & 3) {
+	case USB_TRANSFER_CONTROL:
+		transfer_type = "control";
+		break;
+	case USB_TRANSFER_ISOCHRONOUS:
+		transfer_type = "isochronous";
+		break;
+	case USB_TRANSFER_BULK:
+		transfer_type = "bulk";
+		break;
+	case USB_TRANSFER_INTERRUPT:
+		transfer_type = "interrupt";
+		break;
+	}
+
+	printf("Standard endpoint descriptor\n");
+	printf(INDENT "bLength = %d\n", d->length);
+	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
+	printf(INDENT "bmAttributes = %d [%s]\n", d->attributes, transfer_type);
+	printf(INDENT "wMaxPacketSize = %d\n", d->max_packet_size);
+	printf(INDENT "bInterval = %d\n", d->poll_interval);
+}
+
+void dump_standard_hid_descriptor_header(
+    const usb_standard_hid_descriptor_t *d)
+{
+	printf("Standard HID descriptor\n");
+	printf(INDENT "bLength = %d\n", d->length);
+	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
+	printf(INDENT "bcdHID = %d\n", d->spec_release);
+	printf(INDENT "bCountryCode = %d\n", d->country_code);
+	printf(INDENT "bNumDescriptors = %d\n", d->class_desc_count);
+	printf(INDENT "bDescriptorType = %d\n", d->report_desc_info.type);
+	printf(INDENT "wDescriptorLength = %d\n", d->report_desc_info.length);
+}
+
+void dump_standard_hid_class_descriptor_info(
+    const usb_standard_hid_class_descriptor_info_t *d)
+{
+	printf(INDENT "bDescriptorType = %d\n", d->type);
+	printf(INDENT "wDescriptorLength = %d\n", d->length);
+}
+
+void dump_hid_class_descriptor(int index, uint8_t type, 
+    const uint8_t *d, size_t size )
+{
+	printf("Class-specific descriptor #%d (type: %u)\n", index, type);
+	assert(d != NULL);
+	dump_buffer("", d, size);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/drv/usbhid/descdump.h
===================================================================
--- uspace/drv/usbhid/descdump.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/descdump.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * Descriptor dumping.
+ */
+
+#ifndef USBHID_DESCDUMP_H_
+#define USBHID_DESCDUMP_H_
+
+#include <usb/descriptor.h>
+#include <usb/classes/hid.h>
+
+void dump_standard_configuration_descriptor(
+    int index, const usb_standard_configuration_descriptor_t *d);
+
+void dump_standard_interface_descriptor(
+    const usb_standard_interface_descriptor_t *d);
+
+void dump_standard_endpoint_descriptor(
+    const usb_standard_endpoint_descriptor_t *d);
+
+void dump_standard_hid_descriptor_header(
+    const usb_standard_hid_descriptor_t *d);
+
+void dump_standard_hid_class_descriptor_info(
+    const usb_standard_hid_class_descriptor_info_t *d);
+
+void dump_hid_class_descriptor(int index, uint8_t type, 
+    const uint8_t *d, size_t size);
+
+#endif /* USBHID_DESCDUMP_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/hiddev.c
===================================================================
--- uspace/drv/usbhid/hiddev.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/hiddev.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * Generic USB HID device structure and API.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <ddf/driver.h>
+
+#include <usb/dp.h>
+#include <usb/debug.h>
+#include <usb/request.h>
+#include <usb/descriptor.h>
+#include <usb/classes/hid.h>
+#include <usb/pipes.h>
+
+#include "hiddev.h"
+
+/*----------------------------------------------------------------------------*/
+/* Non-API functions                                                          */
+/*----------------------------------------------------------------------------*/
+
+static int usbhid_dev_get_report_descriptor(usbhid_dev_t *hid_dev, 
+    uint8_t *config_desc, size_t config_desc_size, uint8_t *iface_desc)
+{
+	assert(hid_dev != NULL);
+	assert(config_desc != NULL);
+	assert(config_desc_size != 0);
+	assert(iface_desc != NULL);
+	
+	usb_dp_parser_t parser =  {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+	
+	usb_dp_parser_data_t parser_data = {
+		.data = config_desc,
+		.size = config_desc_size,
+		.arg = NULL
+	};
+	
+	/*
+	 * First nested descriptor of interface descriptor.
+	 */
+	uint8_t *d = 
+	    usb_dp_get_nested_descriptor(&parser, &parser_data, iface_desc);
+	
+	/*
+	 * Search through siblings until the HID descriptor is found.
+	 */
+	while (d != NULL && *(d + 1) != USB_DESCTYPE_HID) {
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		    iface_desc, d);
+	}
+	
+	if (d == NULL) {
+		usb_log_fatal("No HID descriptor found!\n");
+		return ENOENT;
+	}
+	
+	if (*d != sizeof(usb_standard_hid_descriptor_t)) {
+		usb_log_fatal("HID descriptor hass wrong size (%u, expected %u"
+		    ")\n", *d, sizeof(usb_standard_hid_descriptor_t));
+		return EINVAL;
+	}
+	
+	usb_standard_hid_descriptor_t *hid_desc = 
+	    (usb_standard_hid_descriptor_t *)d;
+	
+	uint16_t length =  hid_desc->report_desc_info.length;
+	size_t actual_size = 0;
+
+	/*
+	 * Allocate space for the report descriptor.
+	 */
+	hid_dev->report_desc = (uint8_t *)malloc(length);
+	if (hid_dev->report_desc == NULL) {
+		usb_log_fatal("Failed to allocate space for Report descriptor."
+		    "\n");
+		return ENOMEM;
+	}
+	
+	usb_log_debug("Getting Report descriptor, expected size: %u\n", length);
+	
+	/*
+	 * Get the descriptor from the device.
+	 */
+	int rc = usb_request_get_descriptor(&hid_dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
+	    USB_DESCTYPE_HID_REPORT, 0,
+	    hid_dev->iface, hid_dev->report_desc, length, &actual_size);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (actual_size != length) {
+		free(hid_dev->report_desc);
+		hid_dev->report_desc = NULL;
+		usb_log_fatal("Report descriptor has wrong size (%u, expected "
+		    "%u)\n", actual_size, length);
+		return EINVAL;
+	}
+	
+	usb_log_debug("Done.\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usbhid_dev_process_descriptors(usbhid_dev_t *hid_dev, 
+    usb_endpoint_description_t *poll_ep_desc) 
+{
+	assert(hid_dev != NULL);
+	
+	usb_log_info("Processing descriptors...\n");
+	
+	// get the first configuration descriptor
+	usb_standard_configuration_descriptor_t config_desc;
+	
+	int rc;
+	rc = usb_request_get_bare_configuration_descriptor(&hid_dev->ctrl_pipe,
+	    0, &config_desc);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to get bare config descriptor: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	// prepare space for all underlying descriptors
+	uint8_t *descriptors = (uint8_t *)malloc(config_desc.total_length);
+	if (descriptors == NULL) {
+		usb_log_error("No memory!.\n");
+		return ENOMEM;
+	}
+	
+	size_t transferred = 0;
+	// get full configuration descriptor
+	rc = usb_request_get_full_configuration_descriptor(&hid_dev->ctrl_pipe,
+	    0, descriptors, config_desc.total_length, &transferred);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to get full config descriptor: %s.\n",
+		    str_error(rc));
+		free(descriptors);
+		return rc;
+	}
+	
+	if (transferred != config_desc.total_length) {
+		usb_log_error("Configuration descriptor has wrong size (%u, "
+		    "expected %u).\n", transferred, config_desc.total_length);
+		free(descriptors);
+		return ELIMIT;
+	}
+	
+	/*
+	 * Initialize the interrupt in endpoint.
+	 */
+	usb_endpoint_mapping_t endpoint_mapping[1] = {
+		{
+			.pipe = &hid_dev->poll_pipe,
+			.description = poll_ep_desc,
+			.interface_no =
+			    usb_device_get_assigned_interface(hid_dev->device)
+		}
+	};
+	
+	rc = usb_endpoint_pipe_initialize_from_configuration(
+	    endpoint_mapping, 1, descriptors, config_desc.total_length,
+	    &hid_dev->wire);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize poll pipe: %s.\n",
+		    str_error(rc));
+		free(descriptors);
+		return rc;
+	}
+	
+	if (!endpoint_mapping[0].present) {
+		usb_log_warning("Not accepting device.\n");
+		free(descriptors);
+		return EREFUSED;  // probably not very good return value
+	}
+	
+	usb_log_debug("Accepted device. Saving interface, and getting Report"
+	    " descriptor.\n");
+	
+	/*
+	 * Save assigned interface number.
+	 */
+	if (endpoint_mapping[0].interface_no < 0) {
+		usb_log_error("Bad interface number.\n");
+		free(descriptors);
+		return EINVAL;
+	}
+	
+	hid_dev->iface = endpoint_mapping[0].interface_no;
+	
+	assert(endpoint_mapping[0].interface != NULL);
+	
+	rc = usbhid_dev_get_report_descriptor(hid_dev, descriptors, transferred,
+	    (uint8_t *)endpoint_mapping[0].interface);
+	
+	free(descriptors);
+	
+	if (rc != EOK) {
+		usb_log_warning("Problem with parsing Report descriptor: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/* API functions                                                              */
+/*----------------------------------------------------------------------------*/
+
+usbhid_dev_t *usbhid_dev_new(void)
+{
+	usbhid_dev_t *dev = 
+	    (usbhid_dev_t *)malloc(sizeof(usbhid_dev_t));
+
+	if (dev == NULL) {
+		usb_log_fatal("No memory!\n");
+		return NULL;
+	}
+	
+	memset(dev, 0, sizeof(usbhid_dev_t));
+	
+	dev->initialized = 0;
+	
+	return dev;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usbhid_dev_free(usbhid_dev_t **hid_dev)
+{
+	if (hid_dev == NULL || *hid_dev == NULL) {
+		return;
+	}
+	
+	// free the report descriptor
+	if ((*hid_dev)->report_desc != NULL) {
+		free((*hid_dev)->report_desc);
+	}
+	// destroy the parser
+	if ((*hid_dev)->parser != NULL) {
+		usb_hid_free_report_parser((*hid_dev)->parser);
+	}
+	
+	// TODO: cleanup pipes
+	
+	free(*hid_dev);
+	*hid_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usbhid_dev_init(usbhid_dev_t *hid_dev, ddf_dev_t *dev, 
+    usb_endpoint_description_t *poll_ep_desc)
+{
+	usb_log_info("Initializing HID device structure.\n");
+	
+	if (hid_dev == NULL) {
+		usb_log_error("Failed to init HID device structure: no "
+		    "structure given.\n");
+		return EINVAL;
+	}
+	
+	if (dev == NULL) {
+		usb_log_error("Failed to init HID device structure: no device"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	if (poll_ep_desc == NULL) {
+		usb_log_error("No poll endpoint description given.\n");
+		return EINVAL;
+	}
+	
+	hid_dev->device = dev;
+	
+	int rc;
+
+	/*
+	 * Initialize the backing connection to the host controller.
+	 */
+	rc = usb_device_connection_initialize_from_device(&hid_dev->wire, dev);
+	if (rc != EOK) {
+		usb_log_error("Problem initializing connection to device: %s."
+		    "\n", str_error(rc));
+		return rc;
+	}
+
+	/*
+	 * Initialize device pipes.
+	 */
+	rc = usb_endpoint_pipe_initialize_default_control(&hid_dev->ctrl_pipe,
+	    &hid_dev->wire);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize default control pipe: %s."
+		    "\n", str_error(rc));
+		return rc;
+	}
+
+	/*
+	 * Get descriptors, parse descriptors and save endpoints.
+	 */
+	usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
+	
+	rc = usbhid_dev_process_descriptors(hid_dev, poll_ep_desc);
+	
+	usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
+	if (rc != EOK) {
+		usb_log_error("Failed to process descriptors: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	hid_dev->initialized = 1;
+	usb_log_info("HID device structure initialized.\n");
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/hiddev.h
===================================================================
--- uspace/drv/usbhid/hiddev.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/hiddev.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * Generic USB HID device structure and API.
+ */
+
+#ifndef USBHID_HIDDEV_H_
+#define USBHID_HIDDEV_H_
+
+#include <stdint.h>
+
+#include <ddf/driver.h>
+
+#include <usb/classes/hid.h>
+#include <usb/pipes.h>
+#include <usb/classes/hidparser.h>
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief USB/HID device type.
+ */
+typedef struct {
+	ddf_dev_t *device;
+
+	usb_device_connection_t wire;
+	usb_endpoint_pipe_t ctrl_pipe;
+	usb_endpoint_pipe_t poll_pipe;
+	
+	uint16_t iface;
+	
+	uint8_t *report_desc;
+	usb_hid_report_parser_t *parser;
+	
+	int initialized;
+} usbhid_dev_t;
+
+/*----------------------------------------------------------------------------*/
+
+usbhid_dev_t *usbhid_dev_new(void);
+
+void usbhid_dev_free(usbhid_dev_t **hid_dev);
+
+int usbhid_dev_init(usbhid_dev_t *hid_dev, ddf_dev_t *dev,
+    usb_endpoint_description_t *poll_ep_desc);
+
+/*----------------------------------------------------------------------------*/
+
+#endif /* USBHID_HIDDEV_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/hidreq.c
===================================================================
--- uspace/drv/usbhid/hidreq.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/hidreq.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * HID class-specific requests.
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/classes/hid.h>
+#include <usb/debug.h>
+#include <usb/request.h>
+
+#include "hidreq.h"
+#include "hiddev.h"
+
+/*----------------------------------------------------------------------------*/
+
+int usbhid_req_set_report(usbhid_dev_t *hid_dev,
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size)
+{
+	if (hid_dev == NULL) {
+		usb_log_error("usbhid_req_set_report(): no HID device structure"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	usb_log_debug("Sending Set_Report request to the device.\n");
+	
+	rc = usb_control_request_set(&hid_dev->ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_REPORT, type, hid_dev->iface, buffer, buf_size);
+
+	sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol)
+{
+	if (hid_dev == NULL) {
+		usb_log_error("usbhid_req_set_protocol(): no HID device "
+		    "structure given.\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	usb_log_debug("Sending Set_Protocol request to the device ("
+	    "protocol: %d, iface: %d).\n", protocol, hid_dev->iface);
+	
+	rc = usb_control_request_set(&hid_dev->ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_PROTOCOL, protocol, hid_dev->iface, NULL, 0);
+
+	sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/hidreq.h
===================================================================
--- uspace/drv/usbhid/hidreq.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/hidreq.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * HID class-specific requests.
+ */
+
+#ifndef USBHID_HIDREQ_H_
+#define USBHID_HIDREQ_H_
+
+#include <stdint.h>
+
+#include <usb/classes/hid.h>
+
+#include "hiddev.h"
+
+/*----------------------------------------------------------------------------*/
+
+int usbhid_req_set_report(usbhid_dev_t *hid_dev,
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size);
+
+int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol);
+
+/*----------------------------------------------------------------------------*/
+
+#endif /* USBHID_HIDREQ_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/kbd.h
===================================================================
--- uspace/drv/usbhid/kbd.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/kbd.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,5 @@
+/*
+ * Dummy file because of shared layout sources.
+ *
+ * Do not delete.
+ */
Index: uspace/drv/usbhid/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbddev.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/kbddev.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,744 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID keyboard device structure and API.
+ */
+
+#include <errno.h>
+#include <str_error.h>
+#include <fibril.h>
+
+#include <io/keycode.h>
+#include <ipc/kbd.h>
+#include <async.h>
+
+#include <usb/usb.h>
+#include <usb/classes/hid.h>
+#include <usb/pipes.h>
+#include <usb/debug.h>
+#include <usb/classes/hidparser.h>
+#include <usb/classes/classes.h>
+
+#include "kbddev.h"
+#include "hiddev.h"
+#include "hidreq.h"
+#include "layout.h"
+#include "conv.h"
+
+/*----------------------------------------------------------------------------*/
+
+static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
+static const size_t BOOTP_REPORT_SIZE = 6;
+static const size_t BOOTP_BUFFER_SIZE = 8;
+static const size_t BOOTP_BUFFER_OUT_SIZE = 1;
+
+/** Keyboard polling endpoint description for boot protocol class. */
+static usb_endpoint_description_t poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HID,
+	.interface_subclass = USB_HID_SUBCLASS_BOOT,
+	.interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
+	.flags = 0
+};
+
+/*----------------------------------------------------------------------------*/
+/* Keyboard layouts                                                           */
+/*----------------------------------------------------------------------------*/
+
+#define NUM_LAYOUTS 3
+
+static layout_op_t *layout[NUM_LAYOUTS] = {
+	&us_qwerty_op,
+	&us_dvorak_op,
+	&cz_op
+};
+
+static int active_layout = 0;
+
+/*----------------------------------------------------------------------------*/
+/* Modifier constants                                                         */
+/*----------------------------------------------------------------------------*/
+
+static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
+	KC_LCTRL,         /* USB_HID_MOD_LCTRL */
+	KC_LSHIFT,        /* USB_HID_MOD_LSHIFT */
+	KC_LALT,          /* USB_HID_MOD_LALT */
+	0,                /* USB_HID_MOD_LGUI */
+	KC_RCTRL,         /* USB_HID_MOD_RCTRL */
+	KC_RSHIFT,        /* USB_HID_MOD_RSHIFT */
+	KC_RALT,          /* USB_HID_MOD_RALT */
+	0,                /* USB_HID_MOD_RGUI */
+};
+
+/*----------------------------------------------------------------------------*/
+/* IPC method handler                                                         */
+/*----------------------------------------------------------------------------*/
+
+static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+static ddf_dev_ops_t keyboard_ops = {
+	.default_handler = default_connection_handler
+};
+
+/** Default handler for IPC methods not handled by DDF.
+ *
+ * @param dev Device handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+	
+	usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)fun->driver_data;
+	assert(kbd_dev != NULL);
+
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (kbd_dev->console_phone != -1) {
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		kbd_dev->console_phone = callback;
+		async_answer_0(icallid, EOK);
+		return;
+	}
+	
+	async_answer_0(icallid, EINVAL);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Key processing functions                                                   */
+/*----------------------------------------------------------------------------*/
+
+static void usbhid_kbd_set_led(usbhid_kbd_t *kbd_dev) 
+{
+	uint8_t buffer[BOOTP_BUFFER_OUT_SIZE];
+	int rc= 0;
+	unsigned i;
+	
+	memset(buffer, 0, BOOTP_BUFFER_OUT_SIZE);
+	uint8_t leds = 0;
+
+	if (kbd_dev->mods & KM_NUM_LOCK) {
+		leds |= USB_HID_LED_NUM_LOCK;
+	}
+	
+	if (kbd_dev->mods & KM_CAPS_LOCK) {
+		leds |= USB_HID_LED_CAPS_LOCK;
+	}
+	
+	if (kbd_dev->mods & KM_SCROLL_LOCK) {
+		leds |= USB_HID_LED_SCROLL_LOCK;
+	}
+
+	// TODO: COMPOSE and KANA
+	
+	usb_log_debug("Creating output report.\n");
+	usb_log_debug("Leds: 0x%x\n", leds);
+	if ((rc = usb_hid_boot_keyboard_output_report(
+	    leds, buffer, BOOTP_BUFFER_OUT_SIZE)) != EOK) {
+		usb_log_warning("Error composing output report to the keyboard:"
+		    "%s.\n", str_error(rc));
+		return;
+	}
+	
+	// TODO: REFACTOR!!!
+	
+	usb_log_debug("Output report buffer: ");
+	for (i = 0; i < BOOTP_BUFFER_OUT_SIZE; ++i) {
+		usb_log_debug("0x%x ", buffer[i]);
+	}
+	usb_log_debug("\n");
+	
+	uint16_t value = 0;
+	value |= (USB_HID_REPORT_TYPE_OUTPUT << 8);
+
+	assert(kbd_dev->hid_dev != NULL);
+	assert(kbd_dev->hid_dev->initialized);
+	usbhid_req_set_report(kbd_dev->hid_dev, value, buffer, 
+	    BOOTP_BUFFER_OUT_SIZE);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, 
+    unsigned int key)
+{
+	console_event_t ev;
+	unsigned mod_mask;
+
+	// TODO: replace by our own parsing?? or are the key codes identical??
+	switch (key) {
+	case KC_LCTRL: mod_mask = KM_LCTRL; break;
+	case KC_RCTRL: mod_mask = KM_RCTRL; break;
+	case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
+	case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
+	case KC_LALT: mod_mask = KM_LALT; break;
+	case KC_RALT: mod_mask = KM_RALT; break;
+	default: mod_mask = 0; break;
+	}
+
+	if (mod_mask != 0) {
+		if (type == KEY_PRESS)
+			kbd_dev->mods = kbd_dev->mods | mod_mask;
+		else
+			kbd_dev->mods = kbd_dev->mods & ~mod_mask;
+	}
+
+	switch (key) {
+	case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
+	case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
+	case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
+	default: mod_mask = 0; break;
+	}
+
+	if (mod_mask != 0) {
+		usb_log_debug2("\n\nChanging mods and lock keys\n");
+		usb_log_debug2("\nmods before: 0x%x\n", kbd_dev->mods);
+		usb_log_debug2("\nLock keys before:0x%x\n\n", 
+		    kbd_dev->lock_keys);
+		
+		if (type == KEY_PRESS) {
+			usb_log_debug2("\nKey pressed.\n");
+			/*
+			 * Only change lock state on transition from released
+			 * to pressed. This prevents autorepeat from messing
+			 * up the lock state.
+			 */
+			kbd_dev->mods = 
+			    kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys);
+			kbd_dev->lock_keys = kbd_dev->lock_keys | mod_mask;
+
+			/* Update keyboard lock indicator lights. */
+ 			usbhid_kbd_set_led(kbd_dev);
+		} else {
+			usb_log_debug2("\nKey released.\n");
+			kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask;
+		}
+	}
+
+	usb_log_debug2("\n\nmods after: 0x%x\n", kbd_dev->mods);
+	usb_log_debug2("\nLock keys after: 0x%x\n\n", kbd_dev->lock_keys);
+	
+	if (key == KC_CAPS_LOCK || key == KC_NUM_LOCK || key == KC_SCROLL_LOCK) {
+		// do not send anything to the console, this is our business
+		return;
+	}
+	
+	if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F1) {
+		active_layout = 0;
+		layout[active_layout]->reset();
+		return;
+	}
+
+	if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F2) {
+		active_layout = 1;
+		layout[active_layout]->reset();
+		return;
+	}
+
+	if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F3) {
+		active_layout = 2;
+		layout[active_layout]->reset();
+		return;
+	}
+	
+	ev.type = type;
+	ev.key = key;
+	ev.mods = kbd_dev->mods;
+	
+	if (ev.mods & KM_NUM_LOCK) {
+		usb_log_debug("\n\nNum Lock turned on.\n\n");
+	}
+
+	ev.c = layout[active_layout]->parse_ev(&ev);
+
+	usb_log_debug2("Sending key %d to the console\n", ev.key);
+	assert(kbd_dev->console_phone != -1);
+	
+	async_msg_4(kbd_dev->console_phone, KBD_EVENT, ev.type, ev.key, 
+	    ev.mods, ev.c);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev,
+    uint8_t modifiers)
+{
+	/*
+	 * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK
+	 *       both as modifiers and as keys with their own scancodes???
+	 *
+	 * modifiers should be sent as normal keys to usbhid_parse_scancode()!!
+	 * so maybe it would be better if I received it from report parser in 
+	 * that way
+	 */
+	
+	int i;
+	for (i = 0; i < USB_HID_MOD_COUNT; ++i) {
+		if ((modifiers & usb_hid_modifiers_consts[i]) &&
+		    !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
+			// modifier pressed
+			if (usbhid_modifiers_keycodes[i] != 0) {
+				usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, 
+				    usbhid_modifiers_keycodes[i]);
+			}
+		} else if (!(modifiers & usb_hid_modifiers_consts[i]) &&
+		    (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
+			// modifier released
+			if (usbhid_modifiers_keycodes[i] != 0) {
+				usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, 
+				    usbhid_modifiers_keycodes[i]);
+			}
+		}	// no change
+	}
+	
+	kbd_dev->modifiers = modifiers;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usbhid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev, 
+    const uint8_t *key_codes)
+{
+	// TODO: phantom state!!
+	
+	unsigned int key;
+	unsigned int i, j;
+	
+	// TODO: quite dummy right now, think of better implementation
+	
+	/*
+	 * 1) Key releases
+	 */
+	for (j = 0; j < kbd_dev->keycode_count; ++j) {
+		// try to find the old key in the new key list
+		i = 0;
+		while (i < kbd_dev->keycode_count
+		    && key_codes[i] != kbd_dev->keycodes[j]) {
+			++i;
+		}
+		
+		if (i == kbd_dev->keycode_count) {
+			// not found, i.e. the key was released
+			key = usbhid_parse_scancode(kbd_dev->keycodes[j]);
+			usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
+			usb_log_debug2("\nKey released: %d\n", key);
+		} else {
+			// found, nothing happens
+		}
+	}
+	
+	/*
+	 * 1) Key presses
+	 */
+	for (i = 0; i < kbd_dev->keycode_count; ++i) {
+		// try to find the new key in the old key list
+		j = 0;
+		while (j < kbd_dev->keycode_count 
+		    && kbd_dev->keycodes[j] != key_codes[i]) { 
+			++j;
+		}
+		
+		if (j == kbd_dev->keycode_count) {
+			// not found, i.e. new key pressed
+			key = usbhid_parse_scancode(key_codes[i]);
+			usb_log_debug2("\nKey pressed: %d (keycode: %d)\n", key,
+			    key_codes[i]);
+			usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
+		} else {
+			// found, nothing happens
+		}
+	}
+	
+	memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count);
+	
+	usb_log_debug2("\nNew stored keycodes: ");
+	for (i = 0; i < kbd_dev->keycode_count; ++i) {
+		usb_log_debug2("%d ", kbd_dev->keycodes[i]);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/* Callbacks for parser                                                       */
+/*----------------------------------------------------------------------------*/
+
+static void usbhid_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
+    uint8_t modifiers, void *arg)
+{
+	if (arg == NULL) {
+		usb_log_warning("Missing argument in callback "
+		    "usbhid_process_keycodes().\n");
+		return;
+	}
+
+	usb_log_debug2("Got keys from parser: ");
+	unsigned i;
+	for (i = 0; i < count; ++i) {
+		usb_log_debug2("%d ", key_codes[i]);
+	}
+	usb_log_debug2("\n");
+	
+	usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
+	assert(kbd_dev != NULL);
+	
+	if (count != kbd_dev->keycode_count) {
+		usb_log_warning("Number of received keycodes (%d) differs from"
+		    " expected number (%d).\n", count, kbd_dev->keycode_count);
+		return;
+	}
+	
+	usbhid_kbd_check_modifier_changes(kbd_dev, modifiers);
+	usbhid_kbd_check_key_changes(kbd_dev, key_codes);
+}
+
+/*----------------------------------------------------------------------------*/
+/* General kbd functions                                                      */
+/*----------------------------------------------------------------------------*/
+
+static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev,
+                                    uint8_t *buffer, size_t actual_size)
+{
+	usb_hid_report_in_callbacks_t *callbacks =
+	    (usb_hid_report_in_callbacks_t *)malloc(
+	        sizeof(usb_hid_report_in_callbacks_t));
+	
+	callbacks->keyboard = usbhid_kbd_process_keycodes;
+
+	//usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks, 
+	//    NULL);
+	/*usb_log_debug2("Calling usb_hid_boot_keyboard_input_report() with size"
+	    " %zu\n", actual_size);*/
+	//dump_buffer("bufffer: ", buffer, actual_size);
+	
+	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
+	    callbacks, kbd_dev);
+	
+	if (rc != EOK) {
+		usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
+		    "%s\n", str_error(rc));
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/* HID/KBD structure manipulation                                             */
+/*----------------------------------------------------------------------------*/
+
+static usbhid_kbd_t *usbhid_kbd_new(void)
+{
+	usbhid_kbd_t *kbd_dev = 
+	    (usbhid_kbd_t *)malloc(sizeof(usbhid_kbd_t));
+
+	if (kbd_dev == NULL) {
+		usb_log_fatal("No memory!\n");
+		return NULL;
+	}
+	
+	memset(kbd_dev, 0, sizeof(usbhid_kbd_t));
+	
+	kbd_dev->hid_dev = usbhid_dev_new();
+	if (kbd_dev->hid_dev == NULL) {
+		usb_log_fatal("Could not create HID device structure.\n");
+		return NULL;
+	}
+	
+	kbd_dev->console_phone = -1;
+	kbd_dev->initialized = 0;
+	
+	return kbd_dev;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
+{
+	if (kbd_dev == NULL || *kbd_dev == NULL) {
+		return;
+	}
+	
+	// hangup phone to the console
+	async_hangup((*kbd_dev)->console_phone);
+	
+	if ((*kbd_dev)->hid_dev != NULL) {
+		usbhid_dev_free(&(*kbd_dev)->hid_dev);
+		assert((*kbd_dev)->hid_dev == NULL);
+	}
+	
+	free(*kbd_dev);
+	*kbd_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)
+{
+	int rc;
+	
+	usb_log_info("Initializing HID/KBD structure...\n");
+	
+	if (kbd_dev == NULL) {
+		usb_log_error("Failed to init keyboard structure: no structure"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	if (dev == NULL) {
+		usb_log_error("Failed to init keyboard structure: no device"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	if (kbd_dev->initialized) {
+		usb_log_warning("Keyboard structure already initialized.\n");
+		return EINVAL;
+	}
+	
+	rc = usbhid_dev_init(kbd_dev->hid_dev, dev, &poll_endpoint_description);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize HID device structure: %s\n",
+		   str_error(rc));
+		return rc;
+	}
+	
+	assert(kbd_dev->hid_dev->initialized);
+	
+	// save the size of the report (boot protocol report by default)
+	kbd_dev->keycode_count = BOOTP_REPORT_SIZE;
+	kbd_dev->keycodes = (uint8_t *)calloc(
+	    kbd_dev->keycode_count, sizeof(uint8_t));
+	
+	if (kbd_dev->keycodes == NULL) {
+		usb_log_fatal("No memory!\n");
+		return rc;
+	}
+	
+	kbd_dev->modifiers = 0;
+	kbd_dev->mods = DEFAULT_ACTIVE_MODS;
+	kbd_dev->lock_keys = 0;
+	
+	/*
+	 * Set boot protocol.
+	 * Set LEDs according to initial setup.
+	 */
+	assert(kbd_dev->hid_dev != NULL);
+	assert(kbd_dev->hid_dev->initialized);
+	usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
+	
+	usbhid_kbd_set_led(kbd_dev);
+	
+	kbd_dev->initialized = 1;
+	usb_log_info("HID/KBD device structure initialized.\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/* HID/KBD polling                                                            */
+/*----------------------------------------------------------------------------*/
+
+static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev)
+{
+	int rc, sess_rc;
+	uint8_t buffer[BOOTP_BUFFER_SIZE];
+	size_t actual_size;
+	
+	usb_log_info("Polling keyboard...\n");
+	
+	if (!kbd_dev->initialized) {
+		usb_log_error("HID/KBD device not initialized!\n");
+		return;
+	}
+	
+	assert(kbd_dev->hid_dev != NULL);
+	assert(kbd_dev->hid_dev->initialized);
+
+	while (true) {
+		async_usleep(1000 * 10);
+
+		sess_rc = usb_endpoint_pipe_start_session(
+		    &kbd_dev->hid_dev->poll_pipe);
+		if (sess_rc != EOK) {
+			usb_log_warning("Failed to start a session: %s.\n",
+			    str_error(sess_rc));
+			continue;
+		}
+
+		rc = usb_endpoint_pipe_read(&kbd_dev->hid_dev->poll_pipe, 
+		    buffer, BOOTP_BUFFER_SIZE, &actual_size);
+		
+		sess_rc = usb_endpoint_pipe_end_session(
+		    &kbd_dev->hid_dev->poll_pipe);
+
+		if (rc != EOK) {
+			usb_log_warning("Error polling the keyboard: %s.\n",
+			    str_error(rc));
+			continue;
+		}
+
+		if (sess_rc != EOK) {
+			usb_log_warning("Error closing session: %s.\n",
+			    str_error(sess_rc));
+			continue;
+		}
+
+		/*
+		 * If the keyboard answered with NAK, it returned no data.
+		 * This implies that no change happened since last query.
+		 */
+		if (actual_size == 0) {
+			usb_log_debug("Keyboard returned NAK\n");
+			continue;
+		}
+
+		/*
+		 * TODO: Process pressed keys.
+		 */
+		usb_log_debug("Calling usbhid_kbd_process_data()\n");
+		usbhid_kbd_process_data(kbd_dev, buffer, actual_size);
+	}
+
+	// not reached
+	assert(0);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usbhid_kbd_fibril(void *arg)
+{
+	if (arg == NULL) {
+		usb_log_error("No device!\n");
+		return EINVAL;
+	}
+	
+	usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
+
+	usbhid_kbd_poll(kbd_dev);
+	
+	// at the end, properly destroy the KBD structure
+	usbhid_kbd_free(&kbd_dev);
+	assert(kbd_dev == NULL);
+
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/* API functions                                                              */
+/*----------------------------------------------------------------------------*/
+
+int usbhid_kbd_try_add_device(ddf_dev_t *dev)
+{
+	/*
+	 * Create default function.
+	 */
+	ddf_fun_t *kbd_fun = ddf_fun_create(dev, fun_exposed, "keyboard");
+	if (kbd_fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	/* 
+	 * Initialize device (get and process descriptors, get address, etc.)
+	 */
+	usb_log_info("Initializing USB/HID KBD device...\n");
+	
+	usbhid_kbd_t *kbd_dev = usbhid_kbd_new();
+	if (kbd_dev == NULL) {
+		usb_log_error("Error while creating USB/HID KBD device "
+		    "structure.\n");
+		ddf_fun_destroy(kbd_fun);
+		return EINVAL;  // TODO: some other code??
+	}
+	
+	int rc = usbhid_kbd_init(kbd_dev, dev);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize USB/HID KBD device.\n");
+		ddf_fun_destroy(kbd_fun);
+		usbhid_kbd_free(&kbd_dev);
+		return rc;
+	}	
+	
+	usb_log_info("USB/HID KBD device structure initialized.\n");
+	
+	/*
+	 * Store the initialized keyboard device and keyboard ops
+	 * to the DDF function.
+	 */
+	kbd_fun->driver_data = kbd_dev;
+	kbd_fun->ops = &keyboard_ops;
+
+	rc = ddf_fun_bind(kbd_fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function.\n");
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(kbd_fun);
+		usbhid_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
+	rc = ddf_fun_add_to_class(kbd_fun, "keyboard");
+	if (rc != EOK) {
+		usb_log_error("Could not add DDF function to class 'keyboard'"
+		    "\n");
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(kbd_fun);
+		usbhid_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
+	/*
+	 * Create new fibril for handling this keyboard
+	 */
+	fid_t fid = fibril_create(usbhid_kbd_fibril, kbd_dev);
+	if (fid == 0) {
+		usb_log_error("Failed to start fibril for KBD device\n");
+		return ENOMEM;
+	}
+	fibril_add_ready(fid);
+
+	(void)keyboard_ops;
+
+	/*
+	 * Hurrah, device is initialized.
+	 */
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/kbddev.h
===================================================================
--- uspace/drv/usbhid/kbddev.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/kbddev.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID keyboard device structure and API.
+ */
+
+#ifndef USBHID_KBDDEV_H_
+#define USBHID_KBDDEV_H_
+
+#include <stdint.h>
+
+#include <usb/classes/hid.h>
+#include <ddf/driver.h>
+#include <usb/pipes.h>
+
+#include "hiddev.h"
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief USB/HID keyboard device type.
+ */
+typedef struct {
+	usbhid_dev_t *hid_dev;
+	
+	uint8_t *keycodes;
+	size_t keycode_count;
+	uint8_t modifiers;
+	
+	unsigned mods;
+	unsigned lock_keys;
+	
+	int console_phone;
+	
+	int initialized;
+} usbhid_kbd_t;
+
+/*----------------------------------------------------------------------------*/
+
+int usbhid_kbd_try_add_device(ddf_dev_t *dev);
+
+#endif /* USBHID_KBDDEV_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/layout.h
===================================================================
--- uspace/drv/usbhid/layout.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/layout.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Lubos Slovak 
+ * (copied from /uspace/srv/hid/kbd/include/layout.h)
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * Keyboard layout.
+ */
+
+#ifndef USBHID_LAYOUT_H_
+#define USBHID_LAYOUT_H_
+
+#include <sys/types.h>
+#include <io/console.h>
+
+typedef struct {
+	void (*reset)(void);
+	wchar_t (*parse_ev)(console_event_t *);
+} layout_op_t;
+
+extern layout_op_t us_qwerty_op;
+extern layout_op_t us_dvorak_op;
+extern layout_op_t cz_op;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB HID driver.
+ */
+
+#include <ddf/driver.h>
+#include <usb/debug.h>
+#include <errno.h>
+
+#include "kbddev.h"
+
+/*----------------------------------------------------------------------------*/
+
+#define NAME "usbhid"
+
+/*----------------------------------------------------------------------------*/
+
+static int usbhid_add_device(ddf_dev_t *dev)
+{
+	usb_log_debug("usbhid_add_device()\n");
+	
+	int rc = usbhid_kbd_try_add_device(dev);
+	
+	if (rc != EOK) {
+		usb_log_info("Device is not a supported keyboard.\n");
+		usb_log_error("Failed to add HID device.\n");
+		return EREFUSED;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static driver_ops_t kbd_driver_ops = {
+	.add_device = usbhid_add_device,
+};
+
+/*----------------------------------------------------------------------------*/
+
+static driver_t kbd_driver = {
+	.name = NAME,
+	.driver_ops = &kbd_driver_ops
+};
+
+/*----------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
+	return ddf_driver_main(&kbd_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/usbhid.ma
===================================================================
--- uspace/drv/usbhid/usbhid.ma	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbhid/usbhid.ma	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,4 @@
+10 usb&class=hid
+10 usb&class=HID
+10 usb&interface&class=HID
+10 usb&hid
Index: uspace/drv/usbhub/main.c
===================================================================
--- uspace/drv/usbhub/main.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/usbhub/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,9 +27,12 @@
  */
 
-#include <driver.h>
+/** @addtogroup drvusbhub
+ * @{
+ */
+
+#include <ddf/driver.h>
 #include <errno.h>
 #include <async.h>
-
-#include <usb/usbdrv.h>
+#include <stdio.h>
 
 #include "usbhub.h"
@@ -38,5 +41,5 @@
 
 usb_general_list_t usb_hub_list;
-futex_t usb_hub_list_lock;
+fibril_mutex_t usb_hub_list_lock;
 
 static driver_ops_t hub_driver_ops = {
@@ -49,27 +52,20 @@
 };
 
-int usb_hub_control_loop(void * noparam){
-	while(true){
-		usb_hub_check_hub_changes();
-		async_usleep(1000 * 1000);
-	}
-	return 0;
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	dprintf(USB_LOG_LEVEL_INFO, "starting hub driver");
+
+	//this is probably not needed anymore
+	fibril_mutex_initialize(&usb_hub_list_lock);
+	fibril_mutex_lock(&usb_hub_list_lock);
+	usb_lst_init(&usb_hub_list);
+	fibril_mutex_unlock(&usb_hub_list_lock);
+	
+	return ddf_driver_main(&hub_driver);
 }
 
+/**
+ * @}
+ */
 
-int main(int argc, char *argv[])
-{
-	usb_dprintf_enable(NAME,1);
-	futex_initialize(&usb_hub_list_lock, 0);
-	usb_lst_init(&usb_hub_list);
-	futex_up(&usb_hub_list_lock);
-	fid_t fid = fibril_create(usb_hub_control_loop, NULL);
-	if (fid == 0) {
-		dprintf(1, "failed to start fibril for HUB devices");
-		//printf("%s: failed to start fibril for HUB devices\n", NAME);
-		return ENOMEM;
-	}
-	fibril_add_ready(fid);
-
-	return driver_main(&hub_driver);
-}
Index: uspace/drv/usbhub/port_status.h
===================================================================
--- uspace/drv/usbhub/port_status.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/usbhub/port_status.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -26,4 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+/** @addtogroup drvusbhub
+ * @{
+ */
 
 #ifndef PORT_STATUS_H
@@ -32,5 +35,5 @@
 #include <bool.h>
 #include <sys/types.h>
-#include <usb/devreq.h>
+#include <usb/request.h>
 #include "usbhub_private.h"
 
@@ -170,4 +173,19 @@
 	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
 	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = USB_HUB_FEATURE_PORT_POWER;
+	request->length = 0;
+}
+
+/**
+ * set the device request to be a port disable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_unset_power_port_request(
+usb_device_request_setup_packet_t * request, uint16_t port
+){
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_CLEAR_FEATURE;
 	request->value = USB_HUB_FEATURE_PORT_POWER;
 	request->length = 0;
@@ -302,2 +320,5 @@
 #endif	/* PORT_STATUS_H */
 
+/**
+ * @}
+ */
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/usbhub/usbhub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -26,5 +26,5 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-/** @addtogroup usb hub driver
+/** @addtogroup drvusbhub
  * @{
  */
@@ -33,25 +33,50 @@
  */
 
-#include <driver.h>
+#include <ddf/driver.h>
 #include <bool.h>
 #include <errno.h>
+#include <str_error.h>
 
 #include <usb_iface.h>
-#include <usb/usbdrv.h>
+#include <usb/ddfiface.h>
 #include <usb/descriptor.h>
-#include <usb/devreq.h>
+#include <usb/recognise.h>
+#include <usb/request.h>
 #include <usb/classes/hub.h>
+#include <stdio.h>
 
 #include "usbhub.h"
 #include "usbhub_private.h"
 #include "port_status.h"
-
-static usb_iface_t hub_usb_iface = {
-	.get_hc_handle = usb_drv_find_hc
+#include "usb/usb.h"
+#include "usb/pipes.h"
+#include "usb/classes/classes.h"
+
+static ddf_dev_ops_t hub_device_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
 };
 
-static device_ops_t hub_device_ops = {
-	.interfaces[USB_DEV_IFACE] = &hub_usb_iface
+/** Hub status-change endpoint description
+ *
+ * For more see usb hub specification in 11.15.1 of
+ */
+static usb_endpoint_description_t status_change_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HUB,
+	.interface_subclass = 0,
+	.interface_protocol = 0,
+	.flags = 0
 };
+
+int usb_hub_control_loop(void * hub_info_param){
+	usb_hub_info_t * hub_info = (usb_hub_info_t*)hub_info_param;
+	while(true){
+		usb_hub_check_hub_changes(hub_info);
+		async_usleep(1000 * 1000 );/// \TODO proper number once
+	}
+	return 0;
+}
+
 
 //*********************************************
@@ -61,66 +86,200 @@
 //*********************************************
 
-usb_hub_info_t * usb_create_hub_info(device_t * device, int hc) {
+/**
+ * Initialize connnections to host controller, device, and device
+ * control endpoint
+ * @param hub
+ * @param device
+ * @return
+ */
+static int usb_hub_init_communication(usb_hub_info_t * hub){
+	usb_log_debug("Initializing hub USB communication (hub->device->handle=%zu).\n", hub->device->handle);
+	int opResult;
+	opResult = usb_device_connection_initialize_from_device(
+			&hub->device_connection,
+			hub->device);
+	if(opResult != EOK){
+		dprintf(USB_LOG_LEVEL_ERROR,
+				"could not initialize connection to hc, errno %d",opResult);
+		return opResult;
+	}
+	usb_log_debug("Initializing USB wire abstraction.\n");
+	opResult = usb_hc_connection_initialize_from_device(&hub->connection,
+			hub->device);
+	if(opResult != EOK){
+		dprintf(USB_LOG_LEVEL_ERROR,
+				"could not initialize connection to device, errno %d",opResult);
+		return opResult;
+	}
+	usb_log_debug("Initializing default control pipe.\n");
+	opResult = usb_endpoint_pipe_initialize_default_control(&hub->endpoints.control,
+            &hub->device_connection);
+	if(opResult != EOK){
+		dprintf(USB_LOG_LEVEL_ERROR,
+				"could not initialize connection to device endpoint, errno %d",opResult);
+	}
+	return opResult;
+}
+
+/**
+ * When entering this function, hub->endpoints.control should be active.
+ * @param hub
+ * @return
+ */
+static int usb_hub_process_configuration_descriptors(
+	usb_hub_info_t * hub){
+	if(hub==NULL) {
+		return EINVAL;
+	}
+	int opResult;
+	
+	//device descriptor
+	usb_standard_device_descriptor_t std_descriptor;
+	opResult = usb_request_get_device_descriptor(&hub->endpoints.control,
+	    &std_descriptor);
+	if(opResult!=EOK){
+		dprintf(USB_LOG_LEVEL_ERROR, "could not get device descriptor, %d",opResult);
+		return opResult;
+	}
+	dprintf(USB_LOG_LEVEL_INFO, "hub has %d configurations",
+			std_descriptor.configuration_count);
+	if(std_descriptor.configuration_count<1){
+		dprintf(USB_LOG_LEVEL_ERROR, "THERE ARE NO CONFIGURATIONS AVAILABLE");
+		//shouldn`t I return?
+	}
+
+	//configuration descriptor
+	/// \TODO check other configurations?
+	usb_standard_configuration_descriptor_t config_descriptor;
+	opResult = usb_request_get_bare_configuration_descriptor(
+	    &hub->endpoints.control, 0,
+        &config_descriptor);
+	if(opResult!=EOK){
+		dprintf(USB_LOG_LEVEL_ERROR, "could not get configuration descriptor, %d",opResult);
+		return opResult;
+	}
+	//set configuration
+	opResult = usb_request_set_configuration(&hub->endpoints.control,
+		config_descriptor.configuration_number);
+
+	if (opResult != EOK) {
+		dprintf(USB_LOG_LEVEL_ERROR,
+				"something went wrong when setting hub`s configuration, %d",
+				opResult);
+		return opResult;
+	}
+	dprintf(USB_LOG_LEVEL_DEBUG, "\tused configuration %d",
+			config_descriptor.configuration_number);
+
+	//full configuration descriptor
+	size_t transferred = 0;
+	uint8_t * descriptors = (uint8_t *)malloc(config_descriptor.total_length);
+	if (descriptors == NULL) {
+		dprintf(USB_LOG_LEVEL_ERROR, "insufficient memory");
+		return ENOMEM;
+	}
+	opResult = usb_request_get_full_configuration_descriptor(&hub->endpoints.control,
+	    0, descriptors,
+	    config_descriptor.total_length, &transferred);
+	if(opResult!=EOK){
+		free(descriptors);
+		dprintf(USB_LOG_LEVEL_ERROR,
+				"could not get full configuration descriptor, %d",opResult);
+		return opResult;
+	}
+	if (transferred != config_descriptor.total_length) {
+		dprintf(USB_LOG_LEVEL_ERROR,
+				"received incorrect full configuration descriptor");
+		return ELIMIT;
+	}
+
+	usb_endpoint_mapping_t endpoint_mapping[1] = {
+		{
+			.pipe = &hub->endpoints.status_change,
+			.description = &status_change_endpoint_description,
+			.interface_no =
+			    usb_device_get_assigned_interface(hub->device)
+		}
+	};
+	opResult = usb_endpoint_pipe_initialize_from_configuration(
+	    endpoint_mapping, 1,
+	    descriptors, config_descriptor.total_length,
+	    &hub->device_connection);
+	if (opResult != EOK) {
+		dprintf(USB_LOG_LEVEL_ERROR,
+				"Failed to initialize status change pipe: %s",
+		    str_error(opResult));
+		return opResult;
+	}
+	if (!endpoint_mapping[0].present) {
+		dprintf(USB_LOG_LEVEL_ERROR,"Not accepting device, " \
+		    "cannot understand what is happenning");
+		return EREFUSED;
+	}
+
+	free(descriptors);
+	return EOK;
+	
+}
+
+
+/**
+ * Create hub representation from device information.
+ * @param device
+ * @return pointer to created structure or NULL in case of error
+ */
+usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device) {
 	usb_hub_info_t* result = usb_new(usb_hub_info_t);
+	result->device = device;
+	int opResult;
+	opResult = usb_hub_init_communication(result);
+	if(opResult != EOK){
+		free(result);
+		return NULL;
+	}
+
 	//result->device = device;
 	result->port_count = -1;
-	/// \TODO is this correct? is the device stored?
 	result->device = device;
 
-
-	//printf("[usb_hub] phone to hc = %d\n", hc);
-	if (hc < 0) {
-		return result;
-	}
-	//get some hub info
-	usb_address_t addr = usb_drv_get_my_address(hc, device);
-	dprintf(1,"[usb_hub] address of newly created hub = %d", addr);
-	/*if(addr<0){
-		//return result;
-
-	}*/
-
-	result->usb_device = usb_new(usb_hcd_attached_device_info_t);
-	result->usb_device->address = addr;
+	//result->usb_device = usb_new(usb_hcd_attached_device_info_t);
+	size_t received_size;
 
 	// get hub descriptor
-	usb_target_t target;
-	target.address = addr;
-	target.endpoint = 0;
-	usb_device_request_setup_packet_t request;
-	//printf("[usb_hub] creating descriptor request\n");
-	usb_hub_set_descriptor_request(&request);
-
-	//printf("[usb_hub] creating serialized descriptor\n");
+	dprintf(USB_LOG_LEVEL_DEBUG, "creating serialized descripton");
 	void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
 	usb_hub_descriptor_t * descriptor;
-	size_t received_size;
-	int opResult;
-	//printf("[usb_hub] starting control transaction\n");
-	opResult = usb_drv_sync_control_read(
-			hc, target, &request, serialized_descriptor,
+	dprintf(USB_LOG_LEVEL_DEBUG, "starting control transaction");
+	usb_endpoint_pipe_start_session(&result->endpoints.control);
+	opResult = usb_request_get_descriptor(&result->endpoints.control,
+			USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
+			USB_DESCTYPE_HUB,
+			0, 0, serialized_descriptor,
 			USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
-	if (opResult != EOK) {
-		dprintf(1,"[usb_hub] failed when receiving hub descriptor, badcode = %d",opResult);
+	usb_endpoint_pipe_end_session(&result->endpoints.control);
+
+	if (opResult != EOK) {
+		dprintf(USB_LOG_LEVEL_ERROR, "failed when receiving hub descriptor, badcode = %d",opResult);
 		free(serialized_descriptor);
 		return result;
 	}
-	//printf("[usb_hub] deserializing descriptor\n");
+	dprintf(USB_LOG_LEVEL_DEBUG2, "deserializing descriptor");
 	descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);
 	if(descriptor==NULL){
-		dprintf(1,"[usb_hub] could not deserialize descriptor ");
+		dprintf(USB_LOG_LEVEL_WARNING, "could not deserialize descriptor ");
 		result->port_count = 1;///\TODO this code is only for debug!!!
 		return result;
 	}
-	//printf("[usb_hub] setting port count to %d\n",descriptor->ports_count);
+
+	dprintf(USB_LOG_LEVEL_INFO, "setting port count to %d",descriptor->ports_count);
 	result->port_count = descriptor->ports_count;
-	result->attached_devs = (usb_hub_attached_device_t*)
-	    malloc((result->port_count+1) * sizeof(usb_hub_attached_device_t));
+	result->attached_devs = (usb_hc_attached_device_t*)
+	    malloc((result->port_count+1) * sizeof(usb_hc_attached_device_t));
 	int i;
 	for(i=0;i<result->port_count+1;++i){
-		result->attached_devs[i].devman_handle=0;
+		result->attached_devs[i].handle=0;
 		result->attached_devs[i].address=0;
 	}
-	//printf("[usb_hub] freeing data\n");
+	dprintf(USB_LOG_LEVEL_DEBUG2, "freeing data");
 	free(serialized_descriptor);
 	free(descriptor->devices_removable);
@@ -129,103 +288,86 @@
 	//finish
 
-	dprintf(1,"[usb_hub] hub info created");
+	dprintf(USB_LOG_LEVEL_INFO, "hub info created");
 
 	return result;
 }
 
-int usb_add_hub_device(device_t *dev) {
-	dprintf(1, "add_hub_device(handle=%d)", (int) dev->handle);
-	dprintf(1,"[usb_hub] hub device");
-
-	/*
-	 * We are some (probably deeply nested) hub.
-	 * Thus, assign our own operations and explore already
-	 * connected devices.
-	 */
-	dev->ops = &hub_device_ops;
-
-	//create the hub structure
-	//get hc connection
-	int hc = usb_drv_hc_connect_auto(dev, 0);
-	if (hc < 0) {
-		return hc;
-	}
-
-	usb_hub_info_t * hub_info = usb_create_hub_info(dev, hc);
+/**
+ * Create hub representation and add it into hub list
+ * @param dev
+ * @return
+ */
+int usb_add_hub_device(ddf_dev_t *dev) {
+	dprintf(USB_LOG_LEVEL_INFO, "add_hub_device(handle=%d)", (int) dev->handle);
+
+	//dev->ops = &hub_device_ops;
+	(void) hub_device_ops;
+
+	usb_hub_info_t * hub_info = usb_create_hub_info(dev);
+
+	int opResult;
+
+	//perform final configurations
+	usb_endpoint_pipe_start_session(&hub_info->endpoints.control);
+	// process descriptors
+	opResult = usb_hub_process_configuration_descriptors(hub_info);
+	if(opResult != EOK){
+		dprintf(USB_LOG_LEVEL_ERROR,"could not get condiguration descriptors, %d",
+				opResult);
+		return opResult;
+	}
+	//power ports
+	usb_device_request_setup_packet_t request;
 	int port;
-	int opResult;
-	usb_device_request_setup_packet_t request;
-	usb_target_t target;
-	target.address = hub_info->usb_device->address;
-	target.endpoint = 0;
-
-	//get configuration descriptor
-	// this is not fully correct - there are more configurations
-	// and all should be checked
-	usb_standard_device_descriptor_t std_descriptor;
-	opResult = usb_drv_req_get_device_descriptor(hc, target.address,
-    &std_descriptor);
-	if(opResult!=EOK){
-		dprintf(1,"[usb_hub] could not get device descriptor, %d",opResult);
-		return opResult;
-	}
-	dprintf(1,"[usb_hub] hub has %d configurations",std_descriptor.configuration_count);
-	if(std_descriptor.configuration_count<1){
-		dprintf(1,"[usb_hub] THERE ARE NO CONFIGURATIONS AVAILABLE");
-	}
-	/// \TODO check other configurations
-	usb_standard_configuration_descriptor_t config_descriptor;
-	opResult = usb_drv_req_get_bare_configuration_descriptor(hc,
-        target.address, 0,
-        &config_descriptor);
-	if(opResult!=EOK){
-		dprintf(1,"[usb_hub] could not get configuration descriptor, %d",opResult);
-		return opResult;
-	}
-	//set configuration
-	request.request_type = 0;
-	request.request = USB_DEVREQ_SET_CONFIGURATION;
-	request.index=0;
-	request.length=0;
-	request.value_high=0;
-	request.value_low = config_descriptor.configuration_number;
-	opResult = usb_drv_sync_control_write(hc, target, &request, NULL, 0);
-	if (opResult != EOK) {
-		dprintf(1,"[usb_hub]something went wrong when setting hub`s configuration, %d", opResult);
-	}
-
 	for (port = 1; port < hub_info->port_count+1; ++port) {
 		usb_hub_set_power_port_request(&request, port);
-		opResult = usb_drv_sync_control_write(hc, target, &request, NULL, 0);
-		dprintf(1,"[usb_hub] powering port %d",port);
+		opResult = usb_endpoint_pipe_control_write(&hub_info->endpoints.control,
+				&request,sizeof(usb_device_request_setup_packet_t), NULL, 0);
+		dprintf(USB_LOG_LEVEL_INFO, "powering port %d",port);
 		if (opResult != EOK) {
-			dprintf(1,"[usb_hub]something went wrong when setting hub`s %dth port", port);
+			dprintf(USB_LOG_LEVEL_WARNING, "something went wrong when setting hub`s %dth port", port);
 		}
 	}
 	//ports powered, hub seems to be enabled
-
-	ipc_hangup(hc);
+	usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
 
 	//add the hub to list
-	futex_down(&usb_hub_list_lock);
+	//is this needed now?
+	fibril_mutex_lock(&usb_hub_list_lock);
 	usb_lst_append(&usb_hub_list, hub_info);
-	futex_up(&usb_hub_list_lock);
-
-	dprintf(1,"[usb_hub] hub info added to list");
+	fibril_mutex_unlock(&usb_hub_list_lock);
+	dprintf(USB_LOG_LEVEL_DEBUG, "hub info added to list");
+
+	dprintf(USB_LOG_LEVEL_DEBUG, "adding to ddf");
+	ddf_fun_t *hub_fun = ddf_fun_create(dev, fun_exposed, "hub");
+	assert(hub_fun != NULL);
+	hub_fun->ops = NULL;
+
+	int rc = ddf_fun_bind(hub_fun);
+	assert(rc == EOK);
+	rc = ddf_fun_add_to_class(hub_fun, "hub");
+	assert(rc == EOK);
+
+	fid_t fid = fibril_create(usb_hub_control_loop, hub_info);
+	if (fid == 0) {
+		dprintf(USB_LOG_LEVEL_ERROR, 
+				": failed to start monitoring fibril for new hub");
+		return ENOMEM;
+	}
+	fibril_add_ready(fid);
+
+	dprintf(USB_LOG_LEVEL_DEBUG, "hub fibril created");
 	//(void)hub_info;
-	usb_hub_check_hub_changes();
-
+	//usb_hub_check_hub_changes();
 	
-
-	dprintf(1,"[usb_hub] hub dev added");
-	dprintf(1,"\taddress %d, has %d ports ",
-			hub_info->usb_device->address,
+	dprintf(USB_LOG_LEVEL_INFO, "hub dev added");
+	//address is lost...
+	dprintf(USB_LOG_LEVEL_DEBUG, "\taddress %d, has %d ports ",
+			//hub_info->endpoints.control.,
 			hub_info->port_count);
-	dprintf(1,"\tused configuration %d",config_descriptor.configuration_number);
 
 	return EOK;
 	//return ENOTSUP;
 }
-
 
 
@@ -237,50 +379,40 @@
 
 /**
- * convenience function for releasing default address and writing debug info
- * (these few lines are used too often to be written again and again)
- * @param hc
- * @return
- */
-inline static int usb_hub_release_default_address(int hc){
-	int opResult;
-	dprintf(1,"[usb_hub] releasing default address");
-	opResult = usb_drv_release_default_address(hc);
-	if (opResult != EOK) {
-		dprintf(1,"[usb_hub] failed to release default address");
-	}
-	return opResult;
-}
-
-/**
- * reset the port with new device and reserve the default address
+ * Reset the port with new device and reserve the default address.
  * @param hc
  * @param port
  * @param target
  */
-static void usb_hub_init_add_device(int hc, uint16_t port, usb_target_t target) {
+static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port) {
 	usb_device_request_setup_packet_t request;
 	int opResult;
-	dprintf(1,"[usb_hub] some connection changed");
+	dprintf(USB_LOG_LEVEL_INFO, "some connection changed");
+	assert(hub->endpoints.control.hc_phone);
 	//get default address
-	opResult = usb_drv_reserve_default_address(hc);
-	if (opResult != EOK) {
-		dprintf(1,"[usb_hub] cannot assign default address, it is probably used");
+	//opResult = usb_drv_reserve_default_address(hc);
+	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 %d",opResult);
 		return;
 	}
 	//reset port
 	usb_hub_set_reset_port_request(&request, port);
-	opResult = usb_drv_sync_control_write(
-			hc, target,
-			&request,
+	opResult = usb_endpoint_pipe_control_write(
+			&hub->endpoints.control,
+			&request,sizeof(usb_device_request_setup_packet_t),
 			NULL, 0
 			);
 	if (opResult != EOK) {
-		dprintf(1,"[usb_hub] something went wrong when reseting a port");
-		usb_hub_release_default_address(hc);
-	}
-}
-
-/**
- * finalize adding new device after port reset
+		dprintf(USB_LOG_LEVEL_ERROR, 
+				"something went wrong when reseting a port %d",opResult);
+		//usb_hub_release_default_address(hc);
+		usb_hc_release_default_address(&hub->connection);
+	}
+}
+
+/**
+ * Finalize adding new device after port reset
  * @param hc
  * @param port
@@ -288,36 +420,57 @@
  */
 static void usb_hub_finalize_add_device( usb_hub_info_t * hub,
-		int hc, uint16_t port, usb_target_t target) {
-
-	int opResult;
-	dprintf(1,"[usb_hub] finalizing add device");
-	opResult = usb_hub_clear_port_feature(hc, target.address,
+		uint16_t port, bool isLowSpeed) {
+
+	int opResult;
+	dprintf(USB_LOG_LEVEL_INFO, "finalizing add device");
+	opResult = usb_hub_clear_port_feature(&hub->endpoints.control,
 	    port, USB_HUB_FEATURE_C_PORT_RESET);
-	if (opResult != EOK) {
-		dprintf(1,"[usb_hub] failed to clear port reset feature");
-		usb_hub_release_default_address(hc);
-		return;
-	}
-
-	/* Request address at from host controller. */
-	usb_address_t new_device_address = usb_drv_request_address(hc);
+
+	if (opResult != EOK) {
+		dprintf(USB_LOG_LEVEL_ERROR, "failed to clear port reset feature");
+		usb_hc_release_default_address(&hub->connection);
+		return;
+	}
+	//create connection to device
+	usb_endpoint_pipe_t new_device_pipe;
+	usb_device_connection_t new_device_connection;
+	usb_device_connection_initialize_on_default_address(
+			&new_device_connection,
+			&hub->connection
+			);
+	usb_endpoint_pipe_initialize_default_control(
+			&new_device_pipe,
+			&new_device_connection);
+	/// \TODO get highspeed info
+	usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
+
+
+	/* Request address from host controller. */
+	usb_address_t new_device_address = usb_hc_request_address(
+			&hub->connection,
+			speed/// \TODO fullspeed??
+			);
 	if (new_device_address < 0) {
-		dprintf(1,"[usb_hub] failed to get free USB address");
+		dprintf(USB_LOG_LEVEL_ERROR, "failed to get free USB address");
 		opResult = new_device_address;
-		usb_hub_release_default_address(hc);
-		return;
-	}
-	dprintf(1,"[usb_hub] setting new address");
-	opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,
-	    new_device_address);
-
-	if (opResult != EOK) {
-		dprintf(1,"[usb_hub] could not set address for new device");
-		usb_hub_release_default_address(hc);
-		return;
-	}
-
-
-	opResult = usb_hub_release_default_address(hc);
+		usb_hc_release_default_address(&hub->connection);
+		return;
+	}
+	dprintf(USB_LOG_LEVEL_INFO, "setting new address %d",new_device_address);
+	//opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,
+	//    new_device_address);
+	usb_endpoint_pipe_start_session(&new_device_pipe);
+	opResult = usb_request_set_address(&new_device_pipe,new_device_address);
+	usb_endpoint_pipe_end_session(&new_device_pipe);
+	if (opResult != EOK) {
+		dprintf(USB_LOG_LEVEL_ERROR, 
+				"could not set address for new device %d",opResult);
+		usb_hc_release_default_address(&hub->connection);
+		return;
+	}
+
+
+	//opResult = usb_hub_release_default_address(hc);
+	opResult = usb_hc_release_default_address(&hub->connection);
 	if(opResult!=EOK){
 		return;
@@ -325,19 +478,27 @@
 
 	devman_handle_t child_handle;
-	opResult = usb_drv_register_child_in_devman(hc, hub->device,
-            new_device_address, &child_handle);
-	if (opResult != EOK) {
-		dprintf(1,"[usb_hub] could not start driver for new device");
-		return;
-	}
-	hub->attached_devs[port].devman_handle = child_handle;
+	//??
+    opResult = usb_device_register_child_in_devman(new_device_address,
+            hub->connection.hc_handle, hub->device, &child_handle,
+            NULL, NULL, NULL);
+
+	if (opResult != EOK) {
+		dprintf(USB_LOG_LEVEL_ERROR, 
+				"could not start driver for new device %d",opResult);
+		return;
+	}
+	hub->attached_devs[port].handle = child_handle;
 	hub->attached_devs[port].address = new_device_address;
 
-	opResult = usb_drv_bind_address(hc, new_device_address, child_handle);
-	if (opResult != EOK) {
-		dprintf(1,"[usb_hub] could not assign address of device in hcd");
-		return;
-	}
-	dprintf(1,"[usb_hub] new device address %d, handle %zu",
+	//opResult = usb_drv_bind_address(hc, new_device_address, child_handle);
+	opResult = usb_hc_register_device(
+			&hub->connection,
+			&hub->attached_devs[port]);
+	if (opResult != EOK) {
+		dprintf(USB_LOG_LEVEL_ERROR, 
+				"could not assign address of device in hcd %d",opResult);
+		return;
+	}
+	dprintf(USB_LOG_LEVEL_INFO, "new device address %d, handle %zu",
 	    new_device_address, child_handle);
 
@@ -345,5 +506,5 @@
 
 /**
- * unregister device address in hc
+ * Unregister device address in hc
  * @param hc
  * @param port
@@ -351,80 +512,114 @@
  */
 static void usb_hub_removed_device(
-    usb_hub_info_t * hub, int hc, uint16_t port, usb_target_t target) {
+    usb_hub_info_t * hub,uint16_t port) {
 	//usb_device_request_setup_packet_t request;
 	int opResult;
 	
-	/// \TODO remove device
-
-	hub->attached_devs[port].devman_handle=0;
+	/** \TODO remove device from device manager - not yet implemented in
+	 * devide manager
+	 */
+	
 	//close address
 	if(hub->attached_devs[port].address!=0){
-		opResult = usb_drv_release_address(hc,hub->attached_devs[port].address);
+		//opResult = usb_drv_release_address(hc,hub->attached_devs[port].address);
+		opResult = usb_hc_unregister_device(
+				&hub->connection, hub->attached_devs[port].address);
 		if(opResult != EOK) {
-			dprintf(1,
-					"[usb_hub] could not release address of removed device: %d"
-					,opResult);
+			dprintf(USB_LOG_LEVEL_WARNING, "could not release address of " \
+			    "removed device: %d", opResult);
 		}
 		hub->attached_devs[port].address = 0;
+		hub->attached_devs[port].handle = 0;
 	}else{
-		dprintf(1,
-				"[usb_hub] this is strange, disconnected device had no address");
+		dprintf(USB_LOG_LEVEL_WARNING, "this is strange, disconnected device had no address");
 		//device was disconnected before it`s port was reset - return default address
-		usb_drv_release_default_address(hc);
-	}
-}
-
-/**
- * process interrupts on given hub port
+		//usb_drv_release_default_address(hc);
+		usb_hc_release_default_address(&hub->connection);
+	}
+}
+
+
+/**
+ *Process over current condition on port.
+ * 
+ * Turn off the power on the port.
+ *
+ * @param hub
+ * @param port
+ */
+static void usb_hub_over_current( usb_hub_info_t * hub,
+		uint16_t port){
+	int opResult;
+	opResult = usb_hub_clear_port_feature(&hub->endpoints.control,
+	    port, USB_HUB_FEATURE_PORT_POWER);
+	if(opResult!=EOK){
+		dprintf(USB_LOG_LEVEL_ERROR, "cannot power off port %d;  %d",
+				port, opResult);
+	}
+}
+
+/**
+ * Process interrupts on given hub port
  * @param hc
  * @param port
  * @param target
  */
-static void usb_hub_process_interrupt(usb_hub_info_t * hub, int hc,
-        uint16_t port, usb_address_t address) {
-	dprintf(1,"[usb_hub] interrupt at port %d", port);
+static void usb_hub_process_interrupt(usb_hub_info_t * hub, 
+        uint16_t port) {
+	dprintf(USB_LOG_LEVEL_DEBUG, "interrupt at port %d", port);
 	//determine type of change
-	usb_target_t target;
-	target.address=address;
-	target.endpoint=0;
+	usb_endpoint_pipe_t *pipe = &hub->endpoints.control;
+	
+	int opResult;
+
 	usb_port_status_t status;
 	size_t rcvd_size;
 	usb_device_request_setup_packet_t request;
-	int opResult;
+	//int opResult;
 	usb_hub_set_port_status_request(&request, port);
 	//endpoint 0
 
-	opResult = usb_drv_sync_control_read(
-			hc, target,
-			&request,
+	opResult = usb_endpoint_pipe_control_read(
+			pipe,
+			&request, sizeof(usb_device_request_setup_packet_t),
 			&status, 4, &rcvd_size
 			);
 	if (opResult != EOK) {
-		dprintf(1,"[usb_hub] ERROR: could not get port status");
+		dprintf(USB_LOG_LEVEL_ERROR, "could not get port status");
 		return;
 	}
 	if (rcvd_size != sizeof (usb_port_status_t)) {
-		dprintf(1,"[usb_hub] ERROR: received status has incorrect size");
+		dprintf(USB_LOG_LEVEL_ERROR, "received status has incorrect size");
 		return;
 	}
 	//something connected/disconnected
 	if (usb_port_connect_change(&status)) {
-		opResult = usb_hub_clear_port_feature(hc, target.address,
+		opResult = usb_hub_clear_port_feature(pipe,
 		    port, USB_HUB_FEATURE_C_PORT_CONNECTION);
 		// TODO: check opResult
 		if (usb_port_dev_connected(&status)) {
-			dprintf(1,"[usb_hub] some connection changed");
-			usb_hub_init_add_device(hc, port, target);
+			dprintf(USB_LOG_LEVEL_INFO, "some connection changed");
+			usb_hub_init_add_device(hub, port);
 		} else {
-			usb_hub_removed_device(hub, hc, port, target);
+			usb_hub_removed_device(hub, port);
+		}
+	}
+	//over current
+	if (usb_port_overcurrent_change(&status)) {
+		//check if it was not auto-resolved
+		if(usb_port_over_current(&status)){
+			usb_hub_over_current(hub,port);
+		}else{
+			dprintf(USB_LOG_LEVEL_INFO,
+				"over current condition was auto-resolved on port %d",port);
 		}
 	}
 	//port reset
 	if (usb_port_reset_completed(&status)) {
-		dprintf(1,"[usb_hub] port reset complete");
+		dprintf(USB_LOG_LEVEL_INFO, "port reset complete");
 		if (usb_port_enabled(&status)) {
-			usb_hub_finalize_add_device(hub, hc, port, target);
+			usb_hub_finalize_add_device(hub, port, usb_port_low_speed(&status));
 		} else {
-			dprintf(1,"[usb_hub] ERROR: port reset, but port still not enabled");
+			dprintf(USB_LOG_LEVEL_WARNING, "port reset, but port still not enabled");
 		}
 	}
@@ -434,83 +629,76 @@
 	usb_port_set_reset_completed(&status, false);
 	usb_port_set_dev_connected(&status, false);
-	if (status) {
-		dprintf(1,"[usb_hub]there was some unsupported change on port %d",port);
+	if (status>>16) {
+		dprintf(USB_LOG_LEVEL_INFO, "there was some unsupported change on port %d: %X",port,status);
+
 	}
 	/// \TODO handle other changes
-	/// \TODO debug log for various situations
-
-}
-
-/* Check changes on all known hubs.
- */
-void usb_hub_check_hub_changes(void) {
+}
+
+/**
+ * Check changes on particular hub
+ * @param hub_info_param
+ */
+void usb_hub_check_hub_changes(usb_hub_info_t * hub_info){
+	int opResult;
+	opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change);
+	if(opResult != EOK){
+		dprintf(USB_LOG_LEVEL_ERROR,
+				"could not initialize communication for hub; %d", opResult);
+		return;
+	}
+
+	size_t port_count = hub_info->port_count;
+
+	/// FIXME: count properly
+	size_t byte_length = ((port_count+1) / 8) + 1;
+		void *change_bitmap = malloc(byte_length);
+	size_t actual_size;
+
 	/*
-	 * Iterate through all hubs.
+	 * Send the request.
 	 */
-	usb_general_list_t * lst_item;
-	futex_down(&usb_hub_list_lock);
-	for (lst_item = usb_hub_list.next;
-			lst_item != &usb_hub_list;
-			lst_item = lst_item->next) {
-		futex_up(&usb_hub_list_lock);
-		usb_hub_info_t * hub_info = ((usb_hub_info_t*)lst_item->data);
-		/*
-		 * Check status change pipe of this hub.
-		 */
-
-		usb_target_t target;
-		target.address = hub_info->usb_device->address;
-		target.endpoint = 1;/// \TODO get from endpoint descriptor
-		dprintf(1,"[usb_hub] checking changes for hub at addr %d",
-		    target.address);
-
-		size_t port_count = hub_info->port_count;
-
-		/*
-		 * Connect to respective HC.
-		 */
-		int hc = usb_drv_hc_connect_auto(hub_info->device, 0);
-		if (hc < 0) {
-			continue;
+	opResult = usb_endpoint_pipe_read(
+			&hub_info->endpoints.status_change,
+			change_bitmap, byte_length, &actual_size
+			);
+
+	if (opResult != EOK) {
+		free(change_bitmap);
+		dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");
+		usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
+		return;
+	}
+	unsigned int port;
+	opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.control);
+	if(opResult!=EOK){
+		dprintf(USB_LOG_LEVEL_ERROR, "could not start control pipe session %d",
+				opResult);
+		usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
+		return;
+	}
+	opResult = usb_hc_connection_open(&hub_info->connection);
+	if(opResult!=EOK){
+		dprintf(USB_LOG_LEVEL_ERROR, "could not start host controller session %d",
+				opResult);
+		usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
+		usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
+		return;
+	}
+
+	///todo, opresult check, pre obe konekce
+	for (port = 1; port < port_count+1; ++port) {
+		bool interrupt =
+				(((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;
+		if (interrupt) {
+			usb_hub_process_interrupt(
+			        hub_info, port);
 		}
-
-		/// FIXME: count properly
-		size_t byte_length = ((port_count+1) / 8) + 1;
-
-		void *change_bitmap = malloc(byte_length);
-		size_t actual_size;
-		usb_handle_t handle;
-
-		/*
-		 * Send the request.
-		 */
-		int opResult = usb_drv_async_interrupt_in(hc, target,
-				change_bitmap, byte_length, &actual_size,
-				&handle);
-
-		usb_drv_async_wait_for(handle);
-
-		if (opResult != EOK) {
-			dprintf(1,"[usb_hub] something went wrong while getting status of hub");
-			continue;
-		}
-		unsigned int port;
-		for (port = 1; port < port_count+1; ++port) {
-			bool interrupt =
-					(((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;
-			if (interrupt) {
-				usb_hub_process_interrupt(
-				        hub_info, hc, port, hub_info->usb_device->address);
-			}
-		}
-		free(change_bitmap);
-
-		ipc_hangup(hc);
-		futex_down(&usb_hub_list_lock);
-	}
-	futex_up(&usb_hub_list_lock);
-}
-
-
+	}
+	usb_hc_connection_close(&hub_info->connection);
+	usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
+	usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
+	free(change_bitmap);
+}
 
 
Index: uspace/drv/usbhub/usbhub.h
===================================================================
--- uspace/drv/usbhub/usbhub.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/usbhub/usbhub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbhub
  * @{
  */
@@ -36,13 +36,21 @@
 #define DRV_USBHUB_USBHUB_H
 
+#include <ipc/devman.h>
+#include <usb/usb.h>
+#include <ddf/driver.h>
+
 #define NAME "usbhub"
 
-#include "usb/hcdhubd.h"
+#include <usb/hub.h>
 
-/** basic information about device attached to hub */
-typedef struct{
-	usb_address_t address;
-	devman_handle_t devman_handle;
-}usb_hub_attached_device_t;
+#include <usb/pipes.h>
+
+/* Hub endpoints. */
+typedef struct {
+        usb_endpoint_pipe_t control;
+        usb_endpoint_pipe_t status_change;
+} usb_hub_endpoints_t;
+
+
 
 /** Information about attached hub. */
@@ -50,18 +58,24 @@
 	/** Number of ports. */
 	int port_count;
-	/** attached device handles */
-	usb_hub_attached_device_t * attached_devs;
+	/** attached device handles, for each port one */
+	usb_hc_attached_device_t * attached_devs;
 	/** General usb device info. */
-	usb_hcd_attached_device_info_t * usb_device;
+	//usb_hcd_attached_device_info_t * usb_device;
 	/** General device info*/
-	device_t * device;
-
+	ddf_dev_t * device;
+	/** connection to hcd */
+	//usb_device_connection_t connection;
+	usb_hc_connection_t connection;
+	/** */
+	usb_device_connection_t device_connection;
+	/** hub endpoints */
+	usb_hub_endpoints_t endpoints;
 } usb_hub_info_t;
 
 /**
  * function running the hub-controlling loop.
- * @param noparam fundtion does not need any parameters
+ * @param hub_info_param hub info pointer
  */
-int usb_hub_control_loop(void * noparam);
+int usb_hub_control_loop(void * hub_info_param);
 
 /** Callback when new hub device is detected.
@@ -70,13 +84,13 @@
  * @return Error code.
  */
-int usb_add_hub_device(device_t *dev);
+int usb_add_hub_device(ddf_dev_t *dev);
 
 /**
- * check changes on all registered hubs
+ * check changes on specified hub
+ * @param hub_info_param pointer to usb_hub_info_t structure
  */
-void usb_hub_check_hub_changes(void);
+void usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
 
 
-//int usb_add_hub_device(device_t *);
 
 
Index: uspace/drv/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/usbhub/usbhub_private.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/usbhub/usbhub_private.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,9 +27,9 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbhub
  * @{
  */
 /** @file
- * @brief Hub driver.
+ * @brief Hub driver private definitions
  */
 
@@ -42,12 +42,11 @@
 #include <adt/list.h>
 #include <bool.h>
-#include <driver.h>
-#include <futex.h>
+#include <ddf/driver.h>
+#include <fibril_synch.h>
 
+#include <usb/classes/hub.h>
 #include <usb/usb.h>
-#include <usb/usbdrv.h>
-#include <usb/classes/hub.h>
-#include <usb/devreq.h>
 #include <usb/debug.h>
+#include <usb/request.h>
 
 //************
@@ -61,12 +60,13 @@
 //************
 //
-// convenience debug printf
+// convenience debug printf for usb hub
 //
 //************
 #define dprintf(level, format, ...) \
-	usb_dprintf(NAME, (level), format "\n", ##__VA_ARGS__)
+	usb_log_printf((level), format "\n", ##__VA_ARGS__)
+
 
 /**
- * create hub structure instance
+ * Create hub structure instance
  *
  * Set the address and port count information most importantly.
@@ -76,50 +76,51 @@
  * @return
  */
-usb_hub_info_t * usb_create_hub_info(device_t * device, int hc);
+usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
 
-/** list of hubs maanged by this driver */
+/** List of hubs maanged by this driver */
 extern usb_general_list_t usb_hub_list;
 
-/** lock for hub list*/
-extern futex_t usb_hub_list_lock;
+/** Lock for hub list*/
+extern fibril_mutex_t usb_hub_list_lock;
 
 
 /**
- * perform complete control read transaction
+ * Perform complete control read transaction
  *
- * manages all three steps of transaction: setup, read and finalize
+ * Manages all three steps of transaction: setup, read and finalize
  * @param phone
  * @param target
- * @param request request for data
- * @param rcvd_buffer received data
+ * @param request Request packet
+ * @param rcvd_buffer Received data
  * @param rcvd_size
- * @param actual_size actual size of received data
+ * @param actual_size Actual size of received data
  * @return error code
  */
+/*
 int usb_drv_sync_control_read(
-    int phone, usb_target_t target,
+    usb_endpoint_pipe_t *pipe,
     usb_device_request_setup_packet_t * request,
     void * rcvd_buffer, size_t rcvd_size, size_t * actual_size
-);
+);*/
 
 /**
- * perform complete control write transaction
+ * Perform complete control write transaction
  *
- * manages all three steps of transaction: setup, write and finalize
+ * Manages all three steps of transaction: setup, write and finalize
  * @param phone
  * @param target
- * @param request request to send data
+ * @param request Request packet to send data
  * @param sent_buffer
  * @param sent_size
  * @return error code
  */
-int usb_drv_sync_control_write(
-    int phone, usb_target_t target,
+/*int usb_drv_sync_control_write(
+    usb_endpoint_pipe_t *pipe,
     usb_device_request_setup_packet_t * request,
     void * sent_buffer, size_t sent_size
-);
+);*/
 
 /**
- * set the device request to be a get hub descriptor request.
+ * Set the device request to be a get hub descriptor request.
  * @warning the size is allways set to USB_HUB_MAX_DESCRIPTOR_SIZE
  * @param request
@@ -137,11 +138,17 @@
 }
 
-static inline int usb_hub_clear_port_feature(int hc, usb_address_t address,
+/**
+ * Clear feature on hub port.
+ *
+ * @param hc Host controller telephone
+ * @param address Hub address
+ * @param port_index Port
+ * @param feature Feature selector
+ * @return Operation result
+ */
+static inline int usb_hub_clear_port_feature(usb_endpoint_pipe_t *pipe,
     int port_index,
     usb_hub_class_feature_t feature) {
-	usb_target_t target = {
-		.address = address,
-		.endpoint = 0
-	};
+	
 	usb_device_request_setup_packet_t clear_request = {
 		.request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
@@ -151,8 +158,26 @@
 	};
 	clear_request.value = feature;
-	return usb_drv_psync_control_write(hc, target, &clear_request,
+	return usb_endpoint_pipe_control_write(pipe, &clear_request,
 	    sizeof(clear_request), NULL, 0);
 }
 
+/**
+ * @brief create uint8_t array with serialized descriptor
+ *
+ * @param descriptor
+ * @return newly created serializd descriptor pointer
+ */
+void * usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor);
+
+/**
+ * @brief create deserialized desriptor structure out of serialized descriptor
+ *
+ * The serialized descriptor must be proper usb hub descriptor,
+ * otherwise an eerror might occur.
+ *
+ * @param sdescriptor serialized descriptor
+ * @return newly created deserialized descriptor pointer
+ */
+usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * sdescriptor);
 
 
Index: uspace/drv/usbhub/usblist.c
===================================================================
--- uspace/drv/usbhub/usblist.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/usbhub/usblist.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -26,5 +26,5 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-/** @addtogroup usb hub driver
+/** @addtogroup drvusbhub
  * @{
  */
Index: uspace/drv/usbhub/usblist.h
===================================================================
--- uspace/drv/usbhub/usblist.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/usbhub/usblist.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,8 +27,5 @@
  */
 
-
-#ifndef USBLIST_H
-#define	USBLIST_H
-/** @addtogroup usb hub driver
+/** @addtogroup drvusbhub
  * @{
  */
@@ -40,4 +37,6 @@
  * much simpler and more straight-forward semantics.
  */
+#ifndef USBLIST_H
+#define	USBLIST_H
 
 /**
@@ -78,11 +77,6 @@
 }
 
-
+#endif	/* USBLIST_H */
 /**
  * @}
  */
-
-
-
-#endif	/* USBLIST_H */
-
Index: uspace/drv/usbhub/utils.c
===================================================================
--- uspace/drv/usbhub/utils.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/usbhub/utils.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup drvusbhub
  * @{
  */
@@ -33,12 +33,10 @@
  * @brief various utilities
  */
-#include <driver.h>
+#include <ddf/driver.h>
 #include <bool.h>
 #include <errno.h>
 
 #include <usbhc_iface.h>
-#include <usb/usbdrv.h>
 #include <usb/descriptor.h>
-#include <usb/devreq.h>
 #include <usb/classes/hub.h>
 
@@ -114,16 +112,16 @@
 
 //control transactions
-
+/*
 int usb_drv_sync_control_read(
-		int phone, usb_target_t target,
-		usb_device_request_setup_packet_t * request,
-		void * rcvd_buffer, size_t rcvd_size, size_t * actual_size
-		) {
+    int phone, usb_target_t target,
+    usb_device_request_setup_packet_t * request,
+    void * rcvd_buffer, size_t rcvd_size, size_t * actual_size
+) {
 	usb_handle_t handle;
 	int opResult;
 	//setup
 	opResult = usb_drv_async_control_read_setup(phone, target,
-			request, sizeof (usb_device_request_setup_packet_t),
-			&handle);
+	    request, sizeof (usb_device_request_setup_packet_t),
+	    &handle);
 	if (opResult != EOK) {
 		return opResult;
@@ -158,14 +156,14 @@
 
 int usb_drv_sync_control_write(
-		int phone, usb_target_t target,
-		usb_device_request_setup_packet_t * request,
-		void * sent_buffer, size_t sent_size
-		) {
+    int phone, usb_target_t target,
+    usb_device_request_setup_packet_t * request,
+    void * sent_buffer, size_t sent_size
+) {
 	usb_handle_t handle;
 	int opResult;
 	//setup
 	opResult = usb_drv_async_control_write_setup(phone, target,
-			request, sizeof (usb_device_request_setup_packet_t),
-			&handle);
+	    request, sizeof (usb_device_request_setup_packet_t),
+	    &handle);
 	if (opResult != EOK) {
 		return opResult;
@@ -188,5 +186,5 @@
 	//finalize
 	opResult = usb_drv_async_control_write_status(phone, target,
-			&handle);
+	    &handle);
 	if (opResult != EOK) {
 		return opResult;
@@ -199,5 +197,5 @@
 }
 
-
+*/
 
 
Index: pace/drv/usbkbd/Makefile
===================================================================
--- uspace/drv/usbkbd/Makefile	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2010 Vojtech Horky
-# 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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include
-BINARY = usbkbd
-
-SOURCES = \
-	main.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/usbkbd/main.c
===================================================================
--- uspace/drv/usbkbd/main.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,357 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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.
- */
-#include <usb/usbdrv.h>
-#include <driver.h>
-#include <ipc/driver.h>
-#include <ipc/kbd.h>
-#include <io/keycode.h>
-#include <io/console.h>
-#include <errno.h>
-#include <fibril.h>
-#include <usb/classes/hid.h>
-#include <usb/classes/hidparser.h>
-#include <usb/devreq.h>
-#include <usb/descriptor.h>
-
-#define BUFFER_SIZE 32
-#define NAME "usbkbd"
-
-#define GUESSED_POLL_ENDPOINT 1
-
-static void default_connection_handler(device_t *, ipc_callid_t, ipc_call_t *);
-static device_ops_t keyboard_ops = {
-	.default_handler = default_connection_handler
-};
-
-static int console_callback_phone = -1;
-
-/** Default handler for IPC methods not handled by DDF.
- *
- * @param dev Device handling the call.
- * @param icallid Call id.
- * @param icall Call data.
- */
-void default_connection_handler(device_t *dev,
-    ipc_callid_t icallid, ipc_call_t *icall)
-{
-	sysarg_t method = IPC_GET_IMETHOD(*icall);
-
-	if (method == IPC_M_CONNECT_TO_ME) {
-		int callback = IPC_GET_ARG5(*icall);
-
-		if (console_callback_phone != -1) {
-			ipc_answer_0(icallid, ELIMIT);
-			return;
-		}
-
-		console_callback_phone = callback;
-		ipc_answer_0(icallid, EOK);
-		return;
-	}
-
-	ipc_answer_0(icallid, EINVAL);
-}
-
-#if 0
-static void send_key(int key, int type, wchar_t c) {
-	async_msg_4(console_callback_phone, KBD_EVENT, type, key,
-	    KM_NUM_LOCK, c);
-}
-#endif
-
-/*
- * Callbacks for parser
- */
-static void usbkbd_process_keycodes(const uint16_t *key_codes, size_t count,
-                                    void *arg)
-{
-
-}
-
-/*
- * Kbd functions
- */
-static int usbkbd_parse_descriptors(usb_hid_dev_kbd_t *kbd_dev,
-                                    const uint8_t *data, size_t size)
-{
-//	const uint8_t *pos = data;
-	
-//	// get the configuration descriptor (should be first)
-//	if (*pos != sizeof(usb_standard_configuration_descriptor_t)
-//	    || *(pos + 1) != USB_DESCTYPE_CONFIGURATION) {
-//		fprintf(stderr, "Wrong format of configuration descriptor");
-//		return EINVAL;
-//	}
-	
-//	usb_standard_configuration_descriptor_t config_descriptor;
-//	memcpy(&config_descriptor, pos, 
-//	    sizeof(usb_standard_configuration_descriptor_t));
-//	pos += sizeof(usb_standard_configuration_descriptor_t);
-	
-//	// parse other descriptors
-//	while (pos - data < size) {
-//		//uint8_t desc_size = *pos;
-//		uint8_t desc_type = *(pos + 1);
-//		switch (desc_type) {
-//		case USB_DESCTYPE_INTERFACE:
-//			break;
-//		case USB_DESCTYPE_ENDPOINT:
-//			break;
-//		case USB_DESCTYPE_HID:
-//			break;
-//		case USB_DESCTYPE_HID_REPORT:
-//			break;
-//		case USB_DESCTYPE_HID_PHYSICAL:
-//			break;
-//		}
-//	}
-	
-	return EOK;
-}
-
-static int usbkbd_get_descriptors(usb_hid_dev_kbd_t *kbd_dev)
-{
-	// get the first configuration descriptor (TODO: or some other??)
-	usb_standard_configuration_descriptor_t config_desc;
-	
-	int rc = usb_drv_req_get_bare_configuration_descriptor(
-	    kbd_dev->device->parent_phone, kbd_dev->address, 0, &config_desc);
-	
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	// prepare space for all underlying descriptors
-	uint8_t *descriptors = (uint8_t *)malloc(config_desc.total_length);
-	if (descriptors == NULL) {
-		return ENOMEM;
-	}
-	
-	size_t transferred = 0;
-	// get full configuration descriptor
-	rc = usb_drv_req_get_full_configuration_descriptor(
-	    kbd_dev->device->parent_phone, kbd_dev->address, 0, descriptors,
-	    config_desc.total_length, &transferred);
-	
-	if (rc != EOK) {
-		return rc;
-	}
-	if (transferred != config_desc.total_length) {
-		return ELIMIT;
-	}
-	
-	rc = usbkbd_parse_descriptors(kbd_dev, descriptors, transferred);
-	free(descriptors);
-	
-	return rc;
-}
-
-static usb_hid_dev_kbd_t *usbkbd_init_device(device_t *dev)
-{
-	usb_hid_dev_kbd_t *kbd_dev = (usb_hid_dev_kbd_t *)malloc(
-			sizeof(usb_hid_dev_kbd_t));
-
-	if (kbd_dev == NULL) {
-		fprintf(stderr, NAME ": No memory!\n");
-		return NULL;
-	}
-
-	kbd_dev->device = dev;
-
-	// get phone to my HC and save it as my parent's phone
-	// TODO: maybe not a good idea if DDF will use parent_phone
-	kbd_dev->device->parent_phone = usb_drv_hc_connect_auto(dev, 0);
-
-	kbd_dev->address = usb_drv_get_my_address(dev->parent_phone,
-	    dev);
-
-	// doesn't matter now that we have no address
-//	if (kbd_dev->address < 0) {
-//		fprintf(stderr, NAME ": No device address!\n");
-//		free(kbd_dev);
-//		return NULL;
-//	}
-
-	// default endpoint
-	kbd_dev->poll_endpoint = GUESSED_POLL_ENDPOINT;
-	
-	/*
-	 * will need all descriptors:
-	 * 1) choose one configuration from configuration descriptors 
-	 *    (set it to the device)
-	 * 2) set endpoints from endpoint descriptors
-	 */
-
-	// TODO: get descriptors
-	usbkbd_get_descriptors(kbd_dev);
-	// TODO: parse descriptors and save endpoints
-
-	return kbd_dev;
-}
-
-static void usbkbd_process_interrupt_in(usb_hid_dev_kbd_t *kbd_dev,
-                                        uint8_t *buffer, size_t actual_size)
-{
-	/*
-	 * here, the parser will be called, probably with some callbacks
-	 * now only take last 6 bytes and process, i.e. send to kbd
-	 */
-
-	usb_hid_report_in_callbacks_t *callbacks =
-	    (usb_hid_report_in_callbacks_t *)malloc(
-		sizeof(usb_hid_report_in_callbacks_t));
-	callbacks->keyboard = usbkbd_process_keycodes;
-
-	usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks, 
-	    NULL);
-}
-
-static void usbkbd_poll_keyboard(usb_hid_dev_kbd_t *kbd_dev)
-{
-	int rc;
-	usb_handle_t handle;
-	uint8_t buffer[BUFFER_SIZE];
-	size_t actual_size;
-	//usb_endpoint_t poll_endpoint = 1;
-
-//	usb_address_t my_address = usb_drv_get_my_address(dev->parent_phone,
-//	    dev);
-//	if (my_address < 0) {
-//		return;
-//	}
-
-	usb_target_t poll_target = {
-		.address = kbd_dev->address,
-		.endpoint = kbd_dev->poll_endpoint
-	};
-
-	while (true) {
-		async_usleep(1000 * 1000);
-		rc = usb_drv_async_interrupt_in(kbd_dev->device->parent_phone,
-		    poll_target, buffer, BUFFER_SIZE, &actual_size, &handle);
-
-		if (rc != EOK) {
-			continue;
-		}
-
-		rc = usb_drv_async_wait_for(handle);
-		if (rc != EOK) {
-			continue;
-		}
-
-		/*
-		 * If the keyboard answered with NAK, it returned no data.
-		 * This implies that no change happened since last query.
-		 */
-		if (actual_size == 0) {
-			continue;
-		}
-
-		/*
-		 * TODO: Process pressed keys.
-		 */
-		usbkbd_process_interrupt_in(kbd_dev, buffer, actual_size);
-	}
-
-	// not reached
-	assert(0);
-}
-
-static int usbkbd_fibril_device(void *arg)
-{
-	printf("!!! USB device fibril\n");
-
-	if (arg == NULL) {
-		printf("No device!\n");
-		return -1;
-	}
-
-	device_t *dev = (device_t *)arg;
-
-	// initialize device (get and process descriptors, get address, etc.)
-	usb_hid_dev_kbd_t *kbd_dev = usbkbd_init_device(dev);
-
-	usbkbd_poll_keyboard(kbd_dev);
-
-	return EOK;
-}
-
-static int usbkbd_add_device(device_t *dev)
-{
-	/* For now, fail immediately. */
-	//return ENOTSUP;
-
-	/*
-	 * When everything is okay, connect to "our" HC.
-	 *
-	 * Not supported yet, skip..
-	 */
-//	int phone = usb_drv_hc_connect_auto(dev, 0);
-//	if (phone < 0) {
-//		/*
-//		 * Connecting to HC failed, roll-back and announce
-//		 * failure.
-//		 */
-//		return phone;
-//	}
-
-//	dev->parent_phone = phone;
-
-	/*
-	 * Create new fibril for handling this keyboard
-	 */
-	fid_t fid = fibril_create(usbkbd_fibril_device, dev);
-	if (fid == 0) {
-		printf("%s: failed to start fibril for HID device\n", NAME);
-		return ENOMEM;
-	}
-	fibril_add_ready(fid);
-
-	dev->ops = &keyboard_ops;
-
-	add_device_to_class(dev, "keyboard");
-
-	/*
-	 * Hurrah, device is initialized.
-	 */
-	return EOK;
-}
-
-static driver_ops_t kbd_driver_ops = {
-	.add_device = usbkbd_add_device,
-};
-
-static driver_t kbd_driver = {
-	.name = NAME,
-	.driver_ops = &kbd_driver_ops
-};
-
-int main(int argc, char *argv[])
-{
-	return driver_main(&kbd_driver);
-}
Index: pace/drv/usbkbd/usbkbd.ma
===================================================================
--- uspace/drv/usbkbd/usbkbd.ma	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,4 +1,0 @@
-10 usb&class=hid
-10 usb&class=HID
-10 usb&interface&class=HID
-10 usb&hid
Index: uspace/drv/usbmid/Makefile
===================================================================
--- uspace/drv/usbmid/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbmid/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2011 Vojtech Horky
+# 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.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include
+BINARY = usbmid
+
+SOURCES = \
+	dump.c \
+	explore.c \
+	main.c \
+	usbmid.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/usbmid/dump.c
===================================================================
--- uspace/drv/usbmid/dump.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbmid/dump.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Dumping and debugging functions.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <usb/pipes.h>
+#include <usb/dp.h>
+#include <usb/classes/classes.h>
+#include "usbmid.h"
+
+/** Dump found descriptor.
+ *
+ * @param data Descriptor data.
+ * @param depth Nesting depth.
+ */
+static void dump_tree_descriptor(uint8_t *data, size_t depth)
+{
+	if (data == NULL) {
+		return;
+	}
+	int type = (int) *(data + 1);
+	if (type == USB_DESCTYPE_INTERFACE) {
+		usb_standard_interface_descriptor_t *descriptor
+		    = (usb_standard_interface_descriptor_t *) data;
+		usb_log_info("Found interface: %s (0x%02x/0x%02x/0x%02x).\n",
+		    usb_str_class(descriptor->interface_class),
+		    (int) descriptor->interface_class,
+		    (int) descriptor->interface_subclass,
+		    (int) descriptor->interface_protocol);
+	}
+}
+
+/** Dump tree of descriptors.
+ *
+ * @param parser Descriptor parser.
+ * @param data Descriptor parser data.
+ * @param root Pointer to current root.
+ * @param depth Nesting depth.
+ */
+static void dump_tree_internal(usb_dp_parser_t *parser, usb_dp_parser_data_t *data,
+    uint8_t *root, size_t depth)
+{
+	if (root == NULL) {
+		return;
+	}
+	dump_tree_descriptor(root, depth);
+	uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
+	do {
+		dump_tree_internal(parser, data, child, depth + 1);
+		child = usb_dp_get_sibling_descriptor(parser, data, root, child);
+	} while (child != NULL);
+}
+
+/** Dump descriptor tree.
+ *
+ * @param parser Descriptor parser.
+ * @param data Descriptor parser data.
+ */
+static void dump_tree(usb_dp_parser_t *parser, usb_dp_parser_data_t *data)
+{
+	uint8_t *ptr = data->data;
+	dump_tree_internal(parser, data, ptr, 0);
+}
+
+/** Dump given descriptors.
+ *
+ * @param descriptors Descriptors buffer (typically full config descriptor).
+ * @param length Size of @p descriptors buffer in bytes.
+ */
+void usbmid_dump_descriptors(uint8_t *descriptors, size_t length)
+{
+	usb_dp_parser_data_t data = {
+		.data = descriptors,
+		.size = length,
+		.arg = NULL
+	};
+
+	usb_dp_parser_t parser = {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+
+	dump_tree(&parser, &data);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbmid/explore.c
===================================================================
--- uspace/drv/usbmid/explore.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbmid/explore.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Exploration of available interfaces in the USB device.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <usb/classes/classes.h>
+#include <usb/request.h>
+#include <usb/dp.h>
+#include "usbmid.h"
+
+/** Allocate and retrieve full configuration descriptor.
+ *
+ * @param[in] dev USB device.
+ * @param[in] config_index Configuration index.
+ * @param[out] size Pointer where to store size of the allocated buffer.
+ * @return Allocated full configuration descriptor.
+ * @retval NULL Error occured.
+ */
+static void *get_configuration_descriptor(usbmid_device_t *dev,
+    size_t config_index, size_t *size)
+{
+	usb_standard_configuration_descriptor_t config_descriptor;
+	int rc = usb_request_get_bare_configuration_descriptor(&dev->ctrl_pipe,
+	    config_index, &config_descriptor);
+	if (rc != EOK) {
+		usb_log_error("Failed getting configuration descriptor: %s.\n",
+		    str_error(rc));
+		return NULL;
+	}
+
+	void *full_config_descriptor = malloc(config_descriptor.total_length);
+	if (full_config_descriptor == NULL) {
+		usb_log_fatal("Out of memory (wanted: %zuB).\n",
+		    (size_t) config_descriptor.total_length);
+		return NULL;
+	}
+
+	size_t full_config_descriptor_size;
+	rc = usb_request_get_full_configuration_descriptor(&dev->ctrl_pipe,
+	    config_index,
+	    full_config_descriptor, config_descriptor.total_length,
+	    &full_config_descriptor_size);
+	if (rc != EOK) {
+		usb_log_error("Failed getting configuration descriptor: %s.\n",
+		    str_error(rc));
+		free(full_config_descriptor);
+		return NULL;
+	}
+
+	if (full_config_descriptor_size != config_descriptor.total_length) {
+		usb_log_error("Failed getting full configuration descriptor.\n");
+		free(full_config_descriptor);
+		return NULL;
+	}
+
+	if (size != NULL) {
+		*size = full_config_descriptor_size;
+	}
+
+	return full_config_descriptor;
+}
+
+/** Find starting indexes of all interface descriptors in a configuration.
+ *
+ * @param config_descriptor Full configuration descriptor.
+ * @param config_descriptor_size Size of @p config_descriptor in bytes.
+ * @param interface_positions Array where to store indexes of interfaces.
+ * @param interface_count Size of @p interface_positions array.
+ * @return Number of found interfaces.
+ * @retval (size_t)-1 Error occured.
+ */
+static size_t find_interface_descriptors(uint8_t *config_descriptor,
+    size_t config_descriptor_size,
+    size_t *interface_positions, size_t interface_count)
+{
+	if (interface_count == 0) {
+		return (size_t) -1;
+	}
+
+	usb_dp_parser_data_t data = {
+		.data = config_descriptor,
+		.size = config_descriptor_size,
+		.arg = NULL
+	};
+
+	usb_dp_parser_t parser = {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+
+	uint8_t *interface = usb_dp_get_nested_descriptor(&parser, &data,
+	    data.data);
+	if (interface == NULL) {
+		return (size_t) -1;
+	}
+	if (interface[1] != USB_DESCTYPE_INTERFACE) {
+		return (size_t) -1;
+	}
+
+	size_t found_interfaces = 0;
+	interface_positions[found_interfaces] = interface - config_descriptor;
+	found_interfaces++;
+
+	while (interface != NULL) {
+		interface = usb_dp_get_sibling_descriptor(&parser, &data,
+		    data.data, interface);
+		if ((interface != NULL)
+		    && (found_interfaces < interface_count)
+		    && (interface[1] == USB_DESCTYPE_INTERFACE)) {
+			interface_positions[found_interfaces]
+			    = interface - config_descriptor;
+			found_interfaces++;
+		}
+	}
+
+	return found_interfaces;
+}
+
+/** Explore MID device.
+ *
+ * We expect that @p dev is initialized and session on control pipe is
+ * started.
+ *
+ * @param dev Device to be explored.
+ * @return Whether to accept this device from devman.
+ */
+bool usbmid_explore_device(usbmid_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) {
+		usb_log_warning(
+		    "Device class: %d (%s), but expected class 0.\n",
+		    device_descriptor.device_class,
+		    usb_str_class(device_descriptor.device_class));
+		usb_log_error("Not multi interface device, refusing.\n");
+		return false;
+	}
+
+	size_t config_descriptor_size;
+	uint8_t *config_descriptor_raw = get_configuration_descriptor(dev, 0,
+	    &config_descriptor_size);
+	if (config_descriptor_raw == NULL) {
+		return false;
+	}
+
+	usb_standard_configuration_descriptor_t *config_descriptor
+	    = (usb_standard_configuration_descriptor_t *) config_descriptor_raw;
+
+	size_t *interface_descriptors
+	    = malloc(sizeof(size_t) * config_descriptor->interface_count);
+	if (interface_descriptors == NULL) {
+		usb_log_error("Out of memory (wanted %zuB).\n",
+		    sizeof(size_t) * config_descriptor->interface_count);
+		free(config_descriptor_raw);
+		return false;
+	}
+	size_t interface_descriptors_count
+	    = find_interface_descriptors(
+	    config_descriptor_raw, config_descriptor_size,
+	    interface_descriptors, config_descriptor->interface_count);
+
+	if (interface_descriptors_count == (size_t) -1) {
+		usb_log_error("Problem parsing configuration descriptor.\n");
+		free(config_descriptor_raw);
+		free(interface_descriptors);
+		return false;
+	}
+
+	ddf_fun_t *ctl_fun = ddf_fun_create(dev->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;
+	}
+	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;
+	}
+
+	size_t i;
+	for (i = 0; i < interface_descriptors_count; i++) {
+		usb_standard_interface_descriptor_t *interface
+		    = (usb_standard_interface_descriptor_t *)
+		    (config_descriptor_raw + interface_descriptors[i]);
+		usb_log_debug2("Interface descriptor at index %zu (type %d).\n",
+		    interface_descriptors[i], (int) interface->descriptor_type);
+		usb_log_info("Creating child for interface %d (%s).\n",
+		    (int) interface->interface_number,
+		    usb_str_class(interface->interface_class));
+		rc = usbmid_spawn_interface_child(dev, &device_descriptor,
+		    interface);
+		if (rc != EOK) {
+			usb_log_error("Failed to create interface child: %s.\n",
+			    str_error(rc));
+		}
+	}
+
+	free(config_descriptor_raw);
+
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbmid/main.c
===================================================================
--- uspace/drv/usbmid/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbmid/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB multi interface device driver.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/request.h>
+#include <usb/descriptor.h>
+#include <usb/pipes.h>
+
+#include "usbmid.h"
+
+static int usbmid_add_device(ddf_dev_t *gen_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);
+
+	int rc;
+
+	rc = usb_endpoint_pipe_start_session(&dev->ctrl_pipe);
+	if (rc != EOK) {
+		usb_log_error("Failed to start session on control pipe: %s.\n",
+		    str_error(rc));
+		goto error_leave;
+	}
+
+	bool accept = usbmid_explore_device(dev);
+
+	rc = usb_endpoint_pipe_end_session(&dev->ctrl_pipe);
+	if (rc != EOK) {
+		usb_log_warning("Failed to end session on control pipe: %s.\n",
+		    str_error(rc));
+	}
+
+	if (!accept) {
+		rc = ENOTSUP;
+		goto error_leave;
+	}
+
+	gen_dev->driver_data = dev;
+
+	return EOK;
+
+
+error_leave:
+	free(dev);
+	return rc;
+}
+
+static driver_ops_t mid_driver_ops = {
+	.add_device = usbmid_add_device,
+};
+
+static driver_t mid_driver = {
+	.name = NAME,
+	.driver_ops = &mid_driver_ops
+};
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": USB multi interface device driver.\n");
+
+	usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
+	return ddf_driver_main(&mid_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbmid/usbmid.c
===================================================================
--- uspace/drv/usbmid/usbmid.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbmid/usbmid.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Helper functions.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/pipes.h>
+#include <usb/classes/classes.h>
+#include <usb/recognise.h>
+#include "usbmid.h"
+
+/** Callback for DDF USB interface. */
+static int usb_iface_get_address_impl(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	return usb_iface_get_address_hub_impl(fun, handle, address);
+}
+
+/** Callback for DDF USB interface. */
+static int usb_iface_get_interface_impl(ddf_fun_t *fun, devman_handle_t handle,
+    int *iface_no)
+{
+	assert(fun);
+
+	usbmid_interface_t *iface = fun->driver_data;
+	assert(iface);
+
+	if (iface_no != NULL) {
+		*iface_no = iface->interface_no;
+	}
+
+	return EOK;
+}
+
+static usb_iface_t child_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
+	.get_address = usb_iface_get_address_impl,
+	.get_interface = usb_iface_get_interface_impl
+};
+
+
+static ddf_dev_ops_t child_device_ops = {
+	.interfaces[USB_DEV_IFACE] = &child_usb_iface
+};
+
+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_endpoint_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;
+	}
+
+	mid->dev = dev;
+	(void) &mid_device_ops;
+
+	return mid;
+}
+
+/** Create new interface for USB MID device.
+ *
+ * @param dev Backing generic DDF child device (representing interface).
+ * @param iface_no Interface number.
+ * @return New interface.
+ * @retval NULL Error occured.
+ */
+usbmid_interface_t *usbmid_interface_create(ddf_fun_t *fun, int iface_no)
+{
+	usbmid_interface_t *iface = malloc(sizeof(usbmid_interface_t));
+	if (iface == NULL) {
+		usb_log_error("Out of memory (wanted %zuB).\n",
+		    sizeof(usbmid_interface_t));
+		return NULL;
+	}
+
+	iface->fun = fun;
+	iface->interface_no = iface_no;
+
+	return iface;
+}
+
+
+/** Spawn new child device from one interface.
+ *
+ * @param parent Parent MID device.
+ * @param device_descriptor Device descriptor.
+ * @param interface_descriptor Interface descriptor.
+ * @return Error code.
+ */
+int usbmid_spawn_interface_child(usbmid_device_t *parent,
+    const usb_standard_device_descriptor_t *device_descriptor,
+    const usb_standard_interface_descriptor_t *interface_descriptor)
+{
+	ddf_fun_t *child = NULL;
+	char *child_name = NULL;
+	usbmid_interface_t *child_as_interface = NULL;
+	int rc;
+
+	/*
+	 * Name is class name followed by interface number.
+	 * The interface number shall provide uniqueness while the
+	 * class name something humanly understandable.
+	 */
+	rc = asprintf(&child_name, "%s%d",
+	    usb_str_class(interface_descriptor->interface_class),
+	    (int) interface_descriptor->interface_number);
+	if (rc < 0) {
+		goto error_leave;
+	}
+
+	/* Create the device. */
+	child = ddf_fun_create(parent->dev, fun_inner, child_name);
+	if (child == NULL) {
+		rc = ENOMEM;
+		goto error_leave;
+	}
+
+
+
+	child_as_interface = usbmid_interface_create(child,
+	    (int) interface_descriptor->interface_number);
+	if (child_as_interface == NULL) {
+		rc = ENOMEM;
+		goto error_leave;
+	}
+
+	child->driver_data = child_as_interface;
+	child->ops = &child_device_ops;
+
+	rc = usb_device_create_match_ids_from_interface(device_descriptor,
+	    interface_descriptor,
+	    &child->match_ids);
+	if (rc != EOK) {
+		goto error_leave;
+	}
+
+	rc = ddf_fun_bind(child);
+	if (rc != EOK) {
+		goto error_leave;
+	}
+
+	return EOK;
+
+error_leave:
+	if (child != NULL) {
+		child->name = NULL;
+		/* This takes care of match_id deallocation as well. */
+		ddf_fun_destroy(child);
+	}
+	if (child_name != NULL) {
+		free(child_name);
+	}
+	if (child_as_interface != NULL) {
+		free(child_as_interface);
+	}
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbmid/usbmid.h
===================================================================
--- uspace/drv/usbmid/usbmid.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbmid/usbmid.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 drvusbmid
+ * @{
+ */
+/** @file
+ * Common definitions.
+ */
+
+#ifndef USBMID_H_
+#define USBMID_H_
+
+#include <ddf/driver.h>
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <usb/debug.h>
+
+#define NAME "usbmid"
+
+typedef struct {
+	/** Device container. */
+	ddf_dev_t *dev;
+
+	/** Representation of USB wire. */
+	usb_device_connection_t wire;
+	/** Default control pipe. */
+	usb_endpoint_pipe_t ctrl_pipe;
+} usbmid_device_t;
+
+typedef struct {
+	/** Function container. */
+	ddf_fun_t *fun;
+
+	/** Interface number. */
+	int interface_no;
+} 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 *,
+    const usb_standard_device_descriptor_t *,
+    const usb_standard_interface_descriptor_t *);
+void usbmid_dump_descriptors(uint8_t *, size_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/usbmid/usbmid.ma
===================================================================
--- uspace/drv/usbmid/usbmid.ma	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/drv/usbmid/usbmid.ma	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,1 @@
+100 usb&mid
Index: uspace/drv/vhc/Makefile
===================================================================
--- uspace/drv/vhc/Makefile	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -44,5 +44,4 @@
 	conndev.c \
 	connhost.c \
-	debug.c \
 	devices.c \
 	hc.c \
Index: uspace/drv/vhc/conn.h
===================================================================
--- uspace/drv/vhc/conn.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/conn.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -37,6 +37,6 @@
 
 #include <usb/usb.h>
-#include <usb/hcdhubd.h>
 #include <usbhc_iface.h>
+#include <usb_iface.h>
 #include "vhcd.h"
 #include "devices.h"
@@ -44,11 +44,13 @@
 void connection_handler_host(sysarg_t);
 
-usb_hcd_transfer_ops_t vhc_transfer_ops;
-usbhc_iface_t vhc_iface;
+extern usbhc_iface_t vhc_iface;
+extern usb_iface_t vhc_usb_iface;
+extern usb_iface_t rh_usb_iface;
 
 void address_init(void);
 
 
-void default_connection_handler(device_t *, ipc_callid_t, ipc_call_t *);
+void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+void on_client_close(ddf_fun_t *);
 
 
Index: uspace/drv/vhc/conndev.c
===================================================================
--- uspace/drv/vhc/conndev.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/conndev.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -76,9 +76,9 @@
 /** Default handler for IPC methods not handled by DDF.
  *
- * @param dev Device handling the call.
+ * @param fun Device handling the call.
  * @param icallid Call id.
  * @param icall Call data.
  */
-void default_connection_handler(device_t *dev,
+void default_connection_handler(ddf_fun_t *fun,
     ipc_callid_t icallid, ipc_call_t *icall)
 {
@@ -88,24 +88,40 @@
 		int callback = IPC_GET_ARG5(*icall);
 		virtdev_connection_t *dev
-		    = virtdev_add_device(callback);
+		    = virtdev_add_device(callback, (sysarg_t)fibril_get_id());
 		if (!dev) {
-			ipc_answer_0(icallid, EEXISTS);
-			ipc_hangup(callback);
+			async_answer_0(icallid, EEXISTS);
+			async_hangup(callback);
 			return;
 		}
-		ipc_answer_0(icallid, EOK);
+		async_answer_0(icallid, EOK);
 
 		char devname[DEVICE_NAME_MAXLENGTH + 1];
 		int rc = get_device_name(callback, devname, DEVICE_NAME_MAXLENGTH);
 
-		dprintf(0, "virtual device connected (name: %s)",
-		    rc == EOK ? devname : "<unknown>");
-
-		/* FIXME: destroy the device when the client disconnects. */
+		usb_log_info("New virtual device `%s' (id = %x).\n",
+		    rc == EOK ? devname : "<unknown>", dev->id);
 
 		return;
 	}
 
-	ipc_answer_0(icallid, EINVAL);
+	async_answer_0(icallid, EINVAL);
+}
+
+/** Callback for DDF when client disconnects.
+ *
+ * @param d Device the client was connected to.
+ */
+void on_client_close(ddf_fun_t *fun)
+{
+	/*
+	 * Maybe a virtual device is being unplugged.
+	 */
+	virtdev_connection_t *dev = virtdev_find((sysarg_t)fibril_get_id());
+	if (dev == NULL) {
+		return;
+	}
+
+	usb_log_info("Virtual device disconnected (id = %x).\n", dev->id);
+	virtdev_destroy_device(dev);
 }
 
Index: uspace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/connhost.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -36,9 +36,11 @@
 #include <errno.h>
 #include <usb/usb.h>
-#include <usb/hcd.h>
+#include <usb/addrkeep.h>
+#include <usb/ddfiface.h>
 
 #include "vhcd.h"
 #include "conn.h"
 #include "hc.h"
+
 
 typedef struct {
@@ -46,21 +48,37 @@
 	usbhc_iface_transfer_out_callback_t out_callback;
 	usbhc_iface_transfer_in_callback_t in_callback;
-	device_t *dev;
+	ddf_fun_t *fun;
+	size_t reported_size;
 	void *arg;
 } transfer_info_t;
 
+typedef struct {
+	usb_direction_t direction;
+	usb_target_t target;
+	usbhc_iface_transfer_out_callback_t out_callback;
+	usbhc_iface_transfer_in_callback_t in_callback;
+	ddf_fun_t *fun;
+	void *arg;
+	void *data_buffer;
+	size_t data_buffer_size;
+} control_transfer_info_t;
+
 static void universal_callback(void *buffer, size_t size,
-    usb_transaction_outcome_t outcome, void *arg)
+    int outcome, void *arg)
 {
 	transfer_info_t *transfer = (transfer_info_t *) arg;
+
+	if (transfer->reported_size != (size_t) -1) {
+		size = transfer->reported_size;
+	}
 
 	switch (transfer->direction) {
 		case USB_DIRECTION_IN:
-			transfer->in_callback(transfer->dev,
+			transfer->in_callback(transfer->fun,
 			    outcome, size,
 			    transfer->arg);
 			break;
 		case USB_DIRECTION_OUT:
-			transfer->out_callback(transfer->dev,
+			transfer->out_callback(transfer->fun,
 			    outcome,
 			    transfer->arg);
@@ -74,5 +92,5 @@
 }
 
-static transfer_info_t *create_transfer_info(device_t *dev,
+static transfer_info_t *create_transfer_info(ddf_fun_t *fun,
     usb_direction_t direction, void *arg)
 {
@@ -83,15 +101,124 @@
 	transfer->out_callback = NULL;
 	transfer->arg = arg;
-	transfer->dev = dev;
+	transfer->fun = fun;
+	transfer->reported_size = (size_t) -1;
 
 	return transfer;
 }
 
-static int enqueue_transfer_out(device_t *dev,
+static void control_abort_prematurely(control_transfer_info_t *transfer,
+    size_t size, int outcome)
+{
+	switch (transfer->direction) {
+		case USB_DIRECTION_IN:
+			transfer->in_callback(transfer->fun,
+			    outcome, size,
+			    transfer->arg);
+			break;
+		case USB_DIRECTION_OUT:
+			transfer->out_callback(transfer->fun,
+			    outcome,
+			    transfer->arg);
+			break;
+		default:
+			assert(false && "unreachable");
+			break;
+	}
+}
+
+static void control_callback_two(void *buffer, size_t size,
+    int outcome, void *arg)
+{
+	control_transfer_info_t *ctrl_transfer = (control_transfer_info_t *) arg;
+
+	if (outcome != EOK) {
+		control_abort_prematurely(ctrl_transfer, outcome, size);
+		free(ctrl_transfer);
+		return;
+	}
+
+	transfer_info_t *transfer  = create_transfer_info(ctrl_transfer->fun,
+	    ctrl_transfer->direction, ctrl_transfer->arg);
+	transfer->out_callback = ctrl_transfer->out_callback;
+	transfer->in_callback = ctrl_transfer->in_callback;
+	transfer->reported_size = size;
+
+	switch (ctrl_transfer->direction) {
+		case USB_DIRECTION_IN:
+			hc_add_transaction_to_device(false, ctrl_transfer->target,
+			    USB_TRANSFER_CONTROL,
+			    NULL, 0,
+			    universal_callback, transfer);
+			break;
+		case USB_DIRECTION_OUT:
+			hc_add_transaction_from_device(ctrl_transfer->target,
+			    USB_TRANSFER_CONTROL,
+			    NULL, 0,
+			    universal_callback, transfer);
+			break;
+		default:
+			assert(false && "unreachable");
+			break;
+	}
+
+	free(ctrl_transfer);
+}
+
+static void control_callback_one(void *buffer, size_t size,
+    int outcome, void *arg)
+{
+	control_transfer_info_t *transfer = (control_transfer_info_t *) arg;
+
+	if (outcome != EOK) {
+		control_abort_prematurely(transfer, outcome, size);
+		free(transfer);
+		return;
+	}
+
+	switch (transfer->direction) {
+		case USB_DIRECTION_IN:
+			hc_add_transaction_from_device(transfer->target,
+			    USB_TRANSFER_CONTROL,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    control_callback_two, transfer);
+			break;
+		case USB_DIRECTION_OUT:
+			hc_add_transaction_to_device(false, transfer->target,
+			    USB_TRANSFER_CONTROL,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    control_callback_two, transfer);
+			break;
+		default:
+			assert(false && "unreachable");
+			break;
+	}
+}
+
+static control_transfer_info_t *create_control_transfer_info(ddf_fun_t *fun,
+    usb_direction_t direction, usb_target_t target,
+    void *data_buffer, size_t data_buffer_size,
+    void *arg)
+{
+	control_transfer_info_t *transfer
+	    = malloc(sizeof(control_transfer_info_t));
+
+	transfer->direction = direction;
+	transfer->target = target;
+	transfer->in_callback = NULL;
+	transfer->out_callback = NULL;
+	transfer->arg = arg;
+	transfer->fun = fun;
+	transfer->data_buffer = data_buffer;
+	transfer->data_buffer_size = data_buffer_size;
+
+	return transfer;
+}
+
+static int enqueue_transfer_out(ddf_fun_t *fun,
     usb_target_t target, usb_transfer_type_t transfer_type,
     void *buffer, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
-	dprintf(3, "transfer OUT [%d.%d (%s); %zu]",
+	usb_log_debug2("Transfer OUT [%d.%d (%s); %zu].\n",
 	    target.address, target.endpoint,
 	    usb_str_transfer_type(transfer_type),
@@ -99,5 +226,5 @@
 
 	transfer_info_t *transfer
-	    = create_transfer_info(dev, USB_DIRECTION_OUT, arg);
+	    = create_transfer_info(fun, USB_DIRECTION_OUT, arg);
 	transfer->out_callback = callback;
 
@@ -108,10 +235,10 @@
 }
 
-static int enqueue_transfer_setup(device_t *dev,
+static int enqueue_transfer_in(ddf_fun_t *fun,
     usb_target_t target, usb_transfer_type_t transfer_type,
     void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	dprintf(3, "transfer SETUP [%d.%d (%s); %zu]",
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_log_debug2("Transfer IN [%d.%d (%s); %zu].\n",
 	    target.address, target.endpoint,
 	    usb_str_transfer_type(transfer_type),
@@ -119,25 +246,5 @@
 
 	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,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	dprintf(3, "transfer IN [%d.%d (%s); %zu]",
-	    target.address, target.endpoint,
-	    usb_str_transfer_type(transfer_type),
-	    size);
-
-	transfer_info_t *transfer
-	    = create_transfer_info(dev, USB_DIRECTION_IN, arg);
+	    = create_transfer_info(fun, USB_DIRECTION_IN, arg);
 	transfer->in_callback = callback;
 
@@ -149,78 +256,77 @@
 
 
-static int interrupt_out(device_t *dev, usb_target_t target,
+static int interrupt_out(ddf_fun_t *fun, 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_INTERRUPT,
+	return enqueue_transfer_out(fun, target, USB_TRANSFER_INTERRUPT,
 	    data, size,
 	    callback, arg);
 }
 
-static int interrupt_in(device_t *dev, usb_target_t target,
+static int interrupt_in(ddf_fun_t *fun, 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_INTERRUPT,
+	return enqueue_transfer_in(fun, target, USB_TRANSFER_INTERRUPT,
 	    data, size,
 	    callback, arg);
 }
 
-static int control_write_setup(device_t *dev, usb_target_t target,
-    void *data, size_t size,
+static int control_write(ddf_fun_t *fun, usb_target_t target,
+    size_t max_packet_size,
+    void *setup_packet, size_t setup_packet_size,
+    void *data, size_t data_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,
-    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,
+	control_transfer_info_t *transfer
+	    = create_control_transfer_info(fun, USB_DIRECTION_OUT, target,
+	    data, data_size, arg);
+	transfer->out_callback = callback;
+
+	hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL,
+	    setup_packet, setup_packet_size,
+	    control_callback_one, transfer);
+
+	return EOK;
+}
+
+static int control_read(ddf_fun_t *fun, usb_target_t target,
+    size_t max_packet_size,
+    void *setup_packet, size_t setup_packet_size,
+    void *data, size_t data_size,
     usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
-	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
-	    NULL, 0,
-	    callback, arg);
-}
-
-static int control_read_setup(device_t *dev, usb_target_t target,
-    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,
-    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);
+	control_transfer_info_t *transfer
+	    = create_control_transfer_info(fun, USB_DIRECTION_IN, target,
+	    data, data_size, arg);
+	transfer->in_callback = callback;
+
+	hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL,
+	    setup_packet, setup_packet_size,
+	    control_callback_one, transfer);
+
+	return EOK;
 }
 
 static usb_address_keeping_t addresses;
 
-
-static int reserve_default_address(device_t *dev)
+static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	usb_log_debug("tell_address(fun \"%s\", handle %zu)\n",
+	    fun->name, (size_t) fun->handle);
+	usb_address_t addr = usb_address_keeping_find(&addresses, handle);
+	if (addr < 0) {
+		return addr;
+	}
+
+	*address = addr;
+	return EOK;
+}
+
+static int reserve_default_address(ddf_fun_t *fun, usb_speed_t ignored)
 {
 	usb_address_keeping_reserve_default(&addresses);
@@ -228,5 +334,5 @@
 }
 
-static int release_default_address(device_t *dev)
+static int release_default_address(ddf_fun_t *fun)
 {
 	usb_address_keeping_release_default(&addresses);
@@ -234,5 +340,6 @@
 }
 
-static int request_address(device_t *dev, usb_address_t *address)
+static int request_address(ddf_fun_t *fun, usb_speed_t ignored,
+    usb_address_t *address)
 {
 	usb_address_t addr = usb_address_keeping_request(&addresses);
@@ -245,10 +352,10 @@
 }
 
-static int release_address(device_t *dev, usb_address_t address)
+static int release_address(ddf_fun_t *fun, usb_address_t address)
 {
 	return usb_address_keeping_release(&addresses, address);
 }
 
-static int bind_address(device_t *dev, usb_address_t address,
+static int bind_address(ddf_fun_t *fun, usb_address_t address,
     devman_handle_t handle)
 {
@@ -257,14 +364,24 @@
 }
 
-static int tell_address(device_t *dev, devman_handle_t handle,
+static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
+    devman_handle_t *handle)
+{
+	ddf_fun_t *hc_fun = root_hub_fun->driver_data;
+	assert(hc_fun != NULL);
+
+	*handle = hc_fun->handle;
+
+	usb_log_debug("usb_iface_get_hc_handle_rh_impl returns %zu\n", *handle);
+
+	return EOK;
+}
+
+static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
     usb_address_t *address)
 {
-	usb_address_t addr = usb_address_keeping_find(&addresses, handle);
-	if (addr < 0) {
-		return addr;
-	}
-
-	*address = addr;
-	return EOK;
+	ddf_fun_t *hc_fun = root_hub_fun->driver_data;
+	assert(hc_fun != NULL);
+
+	return tell_address(hc_fun, root_hub_fun->handle, address);
 }
 
@@ -275,6 +392,4 @@
 
 usbhc_iface_t vhc_iface = {
-	.tell_address = tell_address,
-
 	.reserve_default_address = reserve_default_address,
 	.release_default_address = release_default_address,
@@ -286,12 +401,18 @@
 	.interrupt_in = interrupt_in,
 
-	.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
+	.control_write = control_write,
+	.control_read = control_read
 };
+
+usb_iface_t vhc_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle_hc_impl,
+	.get_address = tell_address
+};
+
+usb_iface_t rh_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle_rh_impl,
+	.get_address = tell_address_rh
+};
+
 
 /**
Index: pace/drv/vhc/debug.c
===================================================================
--- uspace/drv/vhc/debug.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 Debugging support.
- */
-#include <stdio.h>
-#include <ipc/ipc.h>
-#include <usb/debug.h>
-
-#include "vhcd.h"
-
-
-/** Debug print informing of invalid call.
- */
-void dprintf_inval_call(int level, ipc_call_t call, sysarg_t phone_hash)
-{
-	dprintf(level, "phone%#x: invalid call [%u (%u, %u, %u, %u, %u)]",
-	    phone_hash,
-	    IPC_GET_IMETHOD(call),
-	    IPC_GET_ARG1(call), IPC_GET_ARG2(call), IPC_GET_ARG3(call),
-	    IPC_GET_ARG4(call), IPC_GET_ARG5(call));
-}
-
-/**
- * @}
- */
Index: uspace/drv/vhc/devices.c
===================================================================
--- uspace/drv/vhc/devices.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/devices.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -34,5 +34,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <adt/list.h>
 #include <bool.h>
@@ -58,14 +57,19 @@
 /** Create virtual device.
  *
- * @param address USB address.
  * @param phone Callback phone.
+ * @param id Device id.
  * @return New device.
- * @retval NULL Out of memory or address already occupied.
- */
-virtdev_connection_t *virtdev_add_device(int phone)
+ * @retval NULL Out of memory.
+ */
+virtdev_connection_t *virtdev_add_device(int phone, sysarg_t id)
 {
 	virtdev_connection_t *dev = (virtdev_connection_t *)
 	    malloc(sizeof(virtdev_connection_t));
+	if (dev == NULL) {
+		return NULL;
+	}
+
 	dev->phone = phone;
+	dev->id = id;
 	list_append(&dev->link, &devices);
 	
@@ -73,4 +77,24 @@
 	
 	return dev;
+}
+
+/** Find virtual device by id.
+ *
+ * @param id Device id.
+ * @return Device with given id.
+ * @retval NULL No such device.
+ */
+virtdev_connection_t *virtdev_find(sysarg_t id)
+{
+	link_t *pos;
+	list_foreach(pos, &devices) {
+		virtdev_connection_t *dev
+		    = list_get_instance(pos, virtdev_connection_t, link);
+		if (dev->id == id) {
+			return dev;
+		}
+	}
+
+	return NULL;
 }
 
@@ -88,6 +112,20 @@
  * @param transaction Transaction to be sent over the bus.
  */
-usb_transaction_outcome_t virtdev_send_to_all(transaction_t *transaction)
-{
+int virtdev_send_to_all(transaction_t *transaction)
+{
+	/* For easier debugging. */
+	switch (transaction->type) {
+		case USBVIRT_TRANSACTION_SETUP:
+		case USBVIRT_TRANSACTION_OUT:
+			transaction->actual_len = transaction->len;
+			break;
+		case USBVIRT_TRANSACTION_IN:
+			transaction->actual_len = 0;
+			break;
+		default:
+			assert(false && "unreachable branch in switch()");
+	}
+	int outcome = EBADCHECKSUM;
+
 	link_t *pos;
 	list_foreach(pos, &devices) {
@@ -138,5 +176,14 @@
 		} else {
 			async_wait_for(req, &answer_rc);
+			transaction->actual_len = IPC_GET_ARG1(answer_data);
 			rc = (int)answer_rc;
+		}
+
+		/*
+		 * If at least one device was able to accept this
+		 * transaction and process it, we can announce success.
+		 */
+		if (rc == EOK) {
+			outcome = EOK;
 		}
 	}
@@ -148,5 +195,5 @@
 	if (virtual_hub_device.address == transaction->target.address) {
 		size_t tmp;
-		dprintf(1, "sending `%s' transaction to hub",
+		usb_log_debug2("Sending `%s' transaction to hub.\n",
 		    usbvirt_str_transaction_type(transaction->type));
 		switch (transaction->type) {
@@ -164,7 +211,5 @@
 				    transaction->buffer, transaction->len,
 				    &tmp);
-				if (tmp < transaction->len) {
-					transaction->len = tmp;
-				}
+				transaction->actual_len = tmp;
 				break;
 				
@@ -176,5 +221,5 @@
 				break;
 		}
-		dprintf(4, "transaction on hub processed...");
+		outcome = EOK;
 	}
 	
@@ -183,5 +228,5 @@
 	 * real-life image.
 	 */
-	return USB_OUTCOME_OK;
+	return outcome;
 }
 
Index: uspace/drv/vhc/devices.h
===================================================================
--- uspace/drv/vhc/devices.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/devices.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */ 
@@ -45,12 +45,14 @@
 	/** Phone used when sending data to device. */
 	int phone;
+	/** Unique identification. */
+	sysarg_t id;
 	/** Linked-list handle. */
 	link_t link;
 } virtdev_connection_t;
 
-virtdev_connection_t *virtdev_add_device(int);
-virtdev_connection_t *virtdev_get_mine(void);
+virtdev_connection_t *virtdev_add_device(int, sysarg_t);
+virtdev_connection_t *virtdev_find(sysarg_t);
 void virtdev_destroy_device(virtdev_connection_t *);
-usb_transaction_outcome_t virtdev_send_to_all(transaction_t *);
+int virtdev_send_to_all(transaction_t *);
 
 #endif
Index: uspace/drv/vhc/hc.c
===================================================================
--- uspace/drv/vhc/hc.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/hc.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -34,5 +34,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <adt/list.h>
 #include <bool.h>
@@ -90,12 +89,12 @@
  */
 static void process_transaction_with_outcome(transaction_t * transaction,
-    usb_transaction_outcome_t outcome)
-{
-	dprintf(3, "transaction " TRANSACTION_FORMAT " done, outcome: %s",
+    int outcome)
+{
+	usb_log_debug2("Transaction " TRANSACTION_FORMAT " done: %s.\n",
 	    TRANSACTION_PRINTF(*transaction),
-	    usb_str_transaction_outcome(outcome));
-	
-	transaction->callback(transaction->buffer, transaction->len, outcome,
-	    transaction->callback_arg);
+	    str_error(outcome));
+	
+	transaction->callback(transaction->buffer, transaction->actual_len,
+	    outcome, transaction->callback_arg);
 }
 
@@ -108,5 +107,5 @@
 	static unsigned int seed = 4573;
 	
-	printf("%s: transaction processor ready.\n", NAME);
+	usb_log_info("Transaction processor ready.\n");
 	
 	while (true) {
@@ -125,12 +124,8 @@
 		list_remove(first_transaction_link);
 		
-
-		dprintf(0, "about to process " TRANSACTION_FORMAT " [%s]",
+		usb_log_debug("Processing " TRANSACTION_FORMAT " [%s].\n",
 		    TRANSACTION_PRINTF(*transaction), ports);
 
-		dprintf(3, "processing transaction " TRANSACTION_FORMAT "",
-		    TRANSACTION_PRINTF(*transaction));
-		
-		usb_transaction_outcome_t outcome;
+		int outcome;
 		outcome = virtdev_send_to_all(transaction);
 		
@@ -148,5 +143,5 @@
 	fid_t fid = fibril_create(hc_manager_fibril, NULL);
 	if (fid == 0) {
-		printf(NAME ": failed to start HC manager fibril\n");
+		usb_log_fatal("Failed to start HC manager fibril.\n");
 		return;
 	}
@@ -169,11 +164,16 @@
 	transaction->buffer = buffer;
 	transaction->len = len;
+	transaction->actual_len = len;
 	transaction->callback = callback;
 	transaction->callback_arg = arg;
-	
-	dprintf(3, "creating transaction " TRANSACTION_FORMAT,
+
+	return transaction;
+}
+
+static void hc_add_transaction(transaction_t *transaction)
+{
+	usb_log_debug("Adding transaction " TRANSACTION_FORMAT ".\n",
 	    TRANSACTION_PRINTF(*transaction));
-	
-	return transaction;
+	list_append(&transaction->link, &transaction_list);
 }
 
@@ -189,5 +189,5 @@
 	    target, transfer_type,
 	    buffer, len, callback, arg);
-	list_append(&transaction->link, &transaction_list);
+	hc_add_transaction(transaction);
 }
 
@@ -202,5 +202,5 @@
 	    target, transfer_type,
 	    buffer, len, callback, arg);
-	list_append(&transaction->link, &transaction_list);
+	hc_add_transaction(transaction);
 }
 
Index: uspace/drv/vhc/hc.h
===================================================================
--- uspace/drv/vhc/hc.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/hc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -47,5 +47,5 @@
  */
 typedef void (*hc_transaction_done_callback_t)(void *buffer, size_t size,
-    usb_transaction_outcome_t outcome, void *arg);
+    int outcome, void *arg);
 
 /** Pending transaction details. */
@@ -65,4 +65,6 @@
 	/** Transaction data length. */
 	size_t len;
+	/** Data length actually transfered. */
+	size_t actual_len;
 	/** Callback after transaction is done. */
 	hc_transaction_done_callback_t callback;
Index: uspace/drv/vhc/hcd.c
===================================================================
--- uspace/drv/vhc/hcd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/hcd.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */ 
@@ -35,5 +35,4 @@
 
 #include <devmap.h>
-#include <ipc/ipc.h>
 #include <async.h>
 #include <unistd.h>
@@ -43,7 +42,8 @@
 #include <errno.h>
 #include <str_error.h>
-#include <driver.h>
+#include <ddf/driver.h>
 
 #include <usb/usb.h>
+#include <usb/ddfiface.h>
 #include <usb_iface.h>
 #include "vhcd.h"
@@ -53,26 +53,16 @@
 #include "conn.h"
 
-static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
-{
-	/* This shall be called only for VHC device. */
-	assert(dev->parent == NULL);
-
-	*handle = dev->handle;
-	return EOK;
-}
-
-static usb_iface_t hc_usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle
-};
-
-static device_ops_t vhc_ops = {
+static ddf_dev_ops_t vhc_ops = {
 	.interfaces[USBHC_DEV_IFACE] = &vhc_iface,
-	.interfaces[USB_DEV_IFACE] = &hc_usb_iface,
+	.interfaces[USB_DEV_IFACE] = &vhc_usb_iface,
+	.close = on_client_close,
 	.default_handler = default_connection_handler
 };
 
-static int vhc_count = 0;
-static int vhc_add_device(device_t *dev)
+static int vhc_add_device(ddf_dev_t *dev)
 {
+	static int vhc_count = 0;
+	int rc;
+
 	/*
 	 * Currently, we know how to simulate only single HC.
@@ -82,16 +72,32 @@
 	}
 
-	vhc_count++;
+	/*
+	 * Create exposed function representing the host controller
+	 * itself.
+	 */
+	ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
+	if (hc == NULL) {
+		usb_log_fatal("Failed to create device function.\n");
+		return ENOMEM;
+	}
 
-	dev->ops = &vhc_ops;
+	hc->ops = &vhc_ops;
 
-	devman_add_device_to_class(dev->handle, "usbhc");
+	rc = ddf_fun_bind(hc);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to bind HC function: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+
+	ddf_fun_add_to_class(hc, "usbhc");
 
 	/*
 	 * Initialize our hub and announce its presence.
 	 */
-	virtual_hub_device_init(dev);
+	virtual_hub_device_init(hc);
 
-	printf("%s: virtual USB host controller ready.\n", NAME);
+	usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n",
+	    (size_t) dev->handle, (size_t) hc->handle);
 
 	return EOK;
@@ -114,7 +120,7 @@
 	 * in devman output.
 	 */
-	sleep(5);
+	//sleep(5);
 
-	usb_dprintf_enable(NAME, 0);
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
 
 	printf(NAME ": virtual USB host controller driver.\n");
@@ -133,5 +139,5 @@
 	 * We are also a driver within devman framework.
 	 */
-	return driver_main(&vhc_driver);
+	return ddf_driver_main(&vhc_driver);
 }
 
Index: uspace/drv/vhc/hub.c
===================================================================
--- uspace/drv/vhc/hub.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/hub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -39,16 +39,22 @@
 #include <str_error.h>
 #include <stdlib.h>
-#include <driver.h>
-#include <usb/usbdrv.h>
+#include <ddf/driver.h>
+#include <devman.h>
+#include <usb/hub.h>
+#include <usb/recognise.h>
 
 #include "hub.h"
 #include "hub/virthub.h"
 #include "vhcd.h"
+#include "conn.h"
 
 usbvirt_device_t virtual_hub_device;
+static ddf_dev_ops_t rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &rh_usb_iface,
+};
 
 static int hub_register_in_devman_fibril(void *arg);
 
-void virtual_hub_device_init(device_t *hc_dev)
+void virtual_hub_device_init(ddf_fun_t *hc_dev)
 {
 	virthub_init(&virtual_hub_device);
@@ -63,9 +69,14 @@
 	    = fibril_create(hub_register_in_devman_fibril, hc_dev);
 	if (root_hub_registration == 0) {
-		printf(NAME ": failed to register root hub\n");
+		usb_log_fatal("Failed to create hub registration fibril.\n");
 		return;
 	}
 
 	fibril_add_ready(root_hub_registration);
+}
+
+static int pretend_port_rest(int unused, void *unused2)
+{
+	return EOK;
 }
 
@@ -77,24 +88,40 @@
 int hub_register_in_devman_fibril(void *arg)
 {
-	device_t *hc_dev = (device_t *) arg;
+	ddf_fun_t *hc_dev = (ddf_fun_t *) arg;
 
-	int hc = usb_drv_hc_connect(hc_dev, hc_dev->handle, IPC_FLAG_BLOCKING);
-	if (hc < 0) {
-		printf(NAME ": failed to register root hub\n");
-		return hc;
+	/*
+	 * Wait until parent device is properly initialized.
+	 */
+	int phone;
+	do {
+		phone = devman_device_connect(hc_dev->handle, 0);
+	} while (phone < 0);
+	async_hangup(phone);
+
+	int rc;
+
+	usb_hc_connection_t hc_conn;
+	rc = usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
+	assert(rc == EOK);
+
+	rc = usb_hc_connection_open(&hc_conn);
+	assert(rc == EOK);
+
+	ddf_fun_t *hub_dev;
+	rc = usb_hc_new_device_wrapper(hc_dev->dev, &hc_conn,
+	    USB_SPEED_FULL,
+	    pretend_port_rest, 0, NULL,
+	    NULL, NULL, &rh_ops, hc_dev, &hub_dev);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to create root hub: %s.\n",
+		    str_error(rc));
 	}
 
-	usb_drv_reserve_default_address(hc);
+	usb_hc_connection_close(&hc_conn);
 
-	usb_address_t hub_address = usb_drv_request_address(hc);
-	usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT, hub_address);
+	usb_log_info("Created root hub function (handle %zu).\n",
+	    (size_t) hub_dev->handle);
 
-	usb_drv_release_default_address(hc);
-
-	devman_handle_t hub_handle;
-	usb_drv_register_child_in_devman(hc, hc_dev, hub_address, &hub_handle);
-	usb_drv_bind_address(hc, hub_address, hub_handle);
-
-	return EOK;
+	return 0;
 }
 	
Index: uspace/drv/vhc/hub.h
===================================================================
--- uspace/drv/vhc/hub.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -37,5 +37,5 @@
 
 #include <usbvirt/device.h>
-#include <driver.h>
+#include <ddf/driver.h>
 
 #include "devices.h"
@@ -45,5 +45,5 @@
 extern usbvirt_device_t virtual_hub_device;
 
-void virtual_hub_device_init(device_t *);
+void virtual_hub_device_init(ddf_fun_t *);
 
 #endif
Index: uspace/drv/vhc/hub/hub.c
===================================================================
--- uspace/drv/vhc/hub/hub.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/hub/hub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -38,7 +38,7 @@
 #include <errno.h>
 #include <str_error.h>
+#include <assert.h>
 #include <stdlib.h>
-#include <driver.h>
-#include <usb/usbdrv.h>
+#include <ddf/driver.h>
 
 #include "hub.h"
@@ -155,4 +155,26 @@
 }
 
+/** Disconnects a device from a hub.
+ *
+ * @param hub Hub the device was connected to.
+ * @param device Device to be disconnected.
+ * @return Error code.
+ */
+int hub_disconnect_device(hub_t *hub, void *device)
+{
+	size_t index = hub_find_device(hub, device);
+	if (index == (size_t) -1) {
+		return ENOENT;
+	}
+
+	hub_port_t *port = &hub->ports[index];
+
+	port->connected_device = NULL;
+	port->state = HUB_PORT_STATE_DISCONNECTED;
+	set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
+
+	return EOK;
+}
+
 /** Find port device is connected to.
  *
@@ -173,5 +195,5 @@
 	}
 
-	return 0;
+	return -1;
 }
 
Index: uspace/drv/vhc/hub/hub.h
===================================================================
--- uspace/drv/vhc/hub/hub.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/hub/hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -38,5 +38,7 @@
 #include <fibril_synch.h>
 
+#ifndef HUB_PORT_COUNT
 #define HUB_PORT_COUNT 2
+#endif
 #define BITS2BYTES(bits) (bits ? ((((bits)-1)>>3)+1) : 0)
 
@@ -94,4 +96,5 @@
 void hub_init(hub_t *);
 size_t hub_connect_device(hub_t *, void *);
+int hub_disconnect_device(hub_t *, void *);
 size_t hub_find_device(hub_t *, void *);
 void hub_acquire(hub_t *);
Index: uspace/drv/vhc/hub/virthub.c
===================================================================
--- uspace/drv/vhc/hub/virthub.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/hub/virthub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -39,7 +39,7 @@
 #include <errno.h>
 #include <str_error.h>
+#include <assert.h>
 #include <stdlib.h>
-#include <driver.h>
-#include <usb/usbdrv.h>
+#include <ddf/driver.h>
 
 #include "virthub.h"
@@ -164,7 +164,13 @@
 	dev->device_data = hub;
 
-	usbvirt_connect_local(dev);
-
-	return EOK;
+	int rc;
+#ifdef STANDALONE_HUB
+	dev->name = "hub";
+	rc = usbvirt_connect(dev);
+#else
+	rc = usbvirt_connect_local(dev);
+#endif
+
+	return rc;
 }
 
@@ -203,5 +209,5 @@
 
 	hub_acquire(hub);
-	/* TODO: implement. */
+	hub_disconnect_device(hub, conn);
 	hub_release(hub);
 
Index: uspace/drv/vhc/hub/virthub.h
===================================================================
--- uspace/drv/vhc/hub/virthub.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/hub/virthub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -37,6 +37,11 @@
 
 #include <usbvirt/device.h>
+#include "hub.h"
+
+#ifdef STANDALONE_HUB
+#define virtdev_connection_t int
+#else
 #include "../devices.h"
-#include "hub.h"
+#endif
 
 /** Endpoint number for status change pipe. */
Index: uspace/drv/vhc/hub/virthubops.c
===================================================================
--- uspace/drv/vhc/hub/virthubops.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/hub/virthubops.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
Index: uspace/drv/vhc/vhcd.h
===================================================================
--- uspace/drv/vhc/vhcd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/drv/vhc/vhcd.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup usb
+/** @addtogroup drvusbvhc
  * @{
  */
@@ -45,7 +45,7 @@
 #define DEVMAP_PATH_DEV NAMESPACE "/" NAME_DEV
 
-#define dprintf(level, format, ...) \
-	usb_dprintf(NAME, (level), format "\n", ##__VA_ARGS__)
-void dprintf_inval_call(int, ipc_call_t, sysarg_t);
+//#define dprintf(level, format, ...)
+//	usb_dprintf(NAME, (level), format "\n", ##__VA_ARGS__)
+//void dprintf_inval_call(int, ipc_call_t, sysarg_t);
 
 #endif
Index: uspace/lib/block/libblock.c
===================================================================
--- uspace/lib/block/libblock.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/block/libblock.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -44,5 +44,4 @@
 #include <sys/mman.h>
 #include <async.h>
-#include <ipc/ipc.h>
 #include <as.h>
 #include <assert.h>
@@ -177,5 +176,5 @@
 	if (rc != EOK) {
 	    	munmap(comm_area, comm_size);
-		ipc_hangup(dev_phone);
+		async_hangup(dev_phone);
 		return rc;
 	}
@@ -183,5 +182,5 @@
 	if (get_block_size(dev_phone, &bsize) != EOK) {
 		munmap(comm_area, comm_size);
-		ipc_hangup(dev_phone);
+		async_hangup(dev_phone);
 		return rc;
 	}
@@ -190,5 +189,5 @@
 	if (rc != EOK) {
 		munmap(comm_area, comm_size);
-		ipc_hangup(dev_phone);
+		async_hangup(dev_phone);
 		return rc;
 	}
@@ -211,5 +210,5 @@
 
 	munmap(devcon->comm_area, devcon->comm_size);
-	ipc_hangup(devcon->dev_phone);
+	async_hangup(devcon->dev_phone);
 
 	free(devcon);	
@@ -295,6 +294,8 @@
 
 	/* Allow 1:1 or small-to-large block size translation */
-	if (cache->lblock_size % devcon->pblock_size != 0)
+	if (cache->lblock_size % devcon->pblock_size != 0) {
+		free(cache);
 		return ENOTSUP;
+	}
 
 	cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
@@ -437,4 +438,5 @@
 			if (!b->data) {
 				free(b);
+				b = NULL;
 				goto recycle;
 			}
@@ -564,4 +566,5 @@
 	assert(devcon);
 	assert(devcon->cache);
+	assert(block->refcnt >= 1);
 
 	cache = devcon->cache;
@@ -623,6 +626,7 @@
 			unsigned long key = block->lba;
 			hash_table_remove(&cache->block_hash, &key, 1);
+			fibril_mutex_unlock(&block->lock);
+			free(block->data);
 			free(block);
-			free(block->data);
 			cache->blocks_cached--;
 			fibril_mutex_unlock(&cache->lock);
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -83,4 +83,5 @@
 	generic/io/console.c \
 	generic/io/screenbuffer.c \
+	generic/ipc/ns.c \
 	generic/malloc.c \
 	generic/sysinfo.c \
@@ -90,11 +91,10 @@
 	generic/loader.c \
 	generic/getopt.c \
-	generic/adt/list.o \
-	generic/adt/hash_table.o \
+	generic/adt/list.c \
+	generic/adt/hash_table.c \
 	generic/adt/dynamic_fifo.c \
 	generic/adt/measured_strings.c \
 	generic/adt/char_map.c \
 	generic/time.c \
-	generic/err.c \
 	generic/stdlib.c \
 	generic/mman.c \
Index: uspace/lib/c/arch/abs32le/_link.ld.in
===================================================================
--- uspace/lib/c/arch/abs32le/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/abs32le/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -44,8 +44,4 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	
-	_heap = .;
-	
 	/DISCARD/ : {
 		*(*);
Index: uspace/lib/c/arch/abs32le/src/entry.c
===================================================================
--- uspace/lib/c/arch/abs32le/src/entry.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/abs32le/src/entry.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -30,12 +30,11 @@
  */
 
-#include <libc.h>
 #include <unistd.h>
 #include <libarch/entry.h>
+#include "../../../generic/private/libc.h"
 
 void __entry(void)
 {
 	__main(NULL);
-	__exit();
 }
 
Index: uspace/lib/c/arch/abs32le/src/thread_entry.c
===================================================================
--- uspace/lib/c/arch/abs32le/src/thread_entry.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/abs32le/src/thread_entry.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -31,5 +31,5 @@
 
 #include <unistd.h>
-#include <thread.h>
+#include "../../../generic/private/thread.h"
 
 void __thread_entry(void)
Index: uspace/lib/c/arch/amd64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/amd64/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/amd64/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -5,4 +5,5 @@
 	text PT_LOAD FLAGS(5);
 	data PT_LOAD FLAGS(6);
+	debug PT_NOTE;
 }
 
@@ -13,14 +14,16 @@
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x1000;
-
+	
 	.data : {
 		*(.data);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -31,16 +34,27 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(COMMON);
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x1000);
-	_heap = .;
+	
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); } :debug
+	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
+	.debug_aranges 0 : { *(.debug_aranges); } :debug
+	.debug_info 0 : { *(.debug_info); } :debug
+	.debug_line 0 : { *(.debug_line); } :debug
+	.debug_loc 0 : { *(.debug_loc); } :debug
+	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
+	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
+	.debug_ranges 0 : { *(.debug_ranges); } :debug
+	.debug_str 0 : { *(.debug_str); } :debug
+#endif
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/lib/c/arch/amd64/src/entry.s
===================================================================
--- uspace/lib/c/arch/amd64/src/entry.s	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/amd64/src/entry.s	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -47,4 +47,2 @@
 	# Pass PCB pointer to __main (no operation)
 	call __main
-
-	call __exit
Index: uspace/lib/c/arch/arm32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/arm32/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/arm32/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -9,15 +9,16 @@
 SECTIONS {
 	. = 0x1000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
-        *(.rodata*);
+		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x1000;
-
+	
 	.data : {
 		*(.opd);
@@ -25,4 +26,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -33,18 +35,16 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
 		*(.scommon);
-        *(COMMON);
-        *(.bss);
+		*(COMMON);
+		*(.bss);
 	} :data
-	
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/lib/c/arch/arm32/src/entry.s
===================================================================
--- uspace/lib/c/arch/arm32/src/entry.s	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/arm32/src/entry.s	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -42,5 +42,5 @@
 	ldr r0, =ras_page
 	str r2, [r0]
-
+	
 	#
 	# Create the first stack frame.
@@ -50,10 +50,8 @@
 	push {fp, ip, lr, pc}
 	sub fp, ip, #4
-
+	
 	# Pass pcb_ptr to __main as the first argument (in r0)
 	mov r0, r1
 	bl __main
-
-	bl __exit
 
 .data
@@ -62,3 +60,2 @@
 ras_page:
 	.long 0
-
Index: uspace/lib/c/arch/ia32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia32/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/ia32/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -5,4 +5,5 @@
 	text PT_LOAD FLAGS(5);
 	data PT_LOAD FLAGS(6);
+	debug PT_NOTE;
 }
 
@@ -42,7 +43,16 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	
-	_heap = .;
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); } :debug
+	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
+	.debug_aranges 0 : { *(.debug_aranges); } :debug
+	.debug_info 0 : { *(.debug_info); } :debug
+	.debug_line 0 : { *(.debug_line); } :debug
+	.debug_loc 0 : { *(.debug_loc); } :debug
+	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
+	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
+	.debug_ranges 0 : { *(.debug_ranges); } :debug
+	.debug_str 0 : { *(.debug_str); } :debug
+#endif
 	
 	/DISCARD/ : {
Index: uspace/lib/c/arch/ia32/src/entry.s
===================================================================
--- uspace/lib/c/arch/ia32/src/entry.s	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/ia32/src/entry.s	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -46,5 +46,5 @@
 	mov %ax, %fs
 	# Do not set %gs, it contains descriptor that can see TLS
-
+	
 	# Detect the mechanism used for making syscalls
 	movl $(INTEL_CPUID_STANDARD), %eax
@@ -58,10 +58,8 @@
 	# Create the first stack frame.
 	#
-	pushl $0 
+	pushl $0
 	movl %esp, %ebp
-
+	
 	# Pass the PCB pointer to __main as the first argument
 	pushl %edi
 	call __main
-
-	call __exit
Index: uspace/lib/c/arch/ia64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia64/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/ia64/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -9,19 +9,21 @@
 SECTIONS {
 	. = 0x4000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		_gp = .;
 		*(.got*);
-	} :data	
+	} :data
+	
 	.data : {
 		*(.opd);
@@ -29,4 +31,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -37,5 +40,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
@@ -44,10 +49,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
- 
+	
 	/DISCARD/ : {
 		*(*);
-        }
+	}
 }
Index: uspace/lib/c/arch/ia64/src/entry.s
===================================================================
--- uspace/lib/c/arch/ia64/src/entry.s	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/ia64/src/entry.s	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,8 +40,6 @@
 	alloc loc0 = ar.pfs, 0, 1, 2, 0
 	movl gp = _gp
-
+	
 	# Pass PCB pointer as the first argument to __main
 	mov out0 = r2
 	br.call.sptk.many b0 = __main
-0:
-	br.call.sptk.many b0 = __exit
Index: uspace/lib/c/arch/mips32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/mips32/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/mips32/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -13,43 +13,46 @@
 		*(.init);
 	} :text
+	
 	.text : {
-	        *(.text);
+		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.data : {
 		*(.data);
 		*(.data.rel*);
 	} :data
-
+	
 	.got : {
 		_gp = .;
 		*(.got);
 	} :data
-
+	
 	.tdata : {
 		_tdata_start = .;
 		*(.tdata);
 		_tdata_end = .;
+	} :data
+	
+	.tbss : {
 		_tbss_start = .;
 		*(.tbss);
 		_tbss_end = .;
 	} :data
-	_tls_alignment = ALIGNOF(.tdata);
-
+	
+	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.sbss : {
 		*(.scommon);
 		*(.sbss);
-	}	
+	}
+	
 	.bss : {
 		*(.bss);
 		*(COMMON);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
-
+	
 	/DISCARD/ : {
 		*(*);
Index: uspace/lib/c/arch/mips32/src/entry.s
===================================================================
--- uspace/lib/c/arch/mips32/src/entry.s	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/mips32/src/entry.s	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -29,6 +29,7 @@
 .text
 .section .init, "ax"
+
 .global __entry
-.global __entry_driver
+
 .set noreorder
 .option pic2
@@ -56,10 +57,3 @@
 	jal __main
 	nop
-	
-	jal __exit
-	nop
 .end
-
-# Alignment of output section data to 0x4000
-.section .data
-.align 14
Index: uspace/lib/c/arch/ppc32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ppc32/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/ppc32/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -9,19 +9,21 @@
 SECTIONS {
 	. = 0x1000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x1000;
-
+	
 	.data : {
 		*(.data);
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -32,5 +34,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
@@ -38,11 +42,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/lib/c/arch/ppc32/src/entry.s
===================================================================
--- uspace/lib/c/arch/ppc32/src/entry.s	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/ppc32/src/entry.s	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -44,9 +44,7 @@
 	stw %r3, 0(%r1)
 	stwu %r1, -16(%r1)
-
+	
 	# Pass the PCB pointer to __main() as the first argument.
 	# The first argument is passed in r3.
 	mr %r3, %r6
 	bl __main
-
-	bl __exit
Index: uspace/lib/c/arch/sparc64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/sparc64/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/sparc64/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -9,23 +9,26 @@
 SECTIONS {
 	. = 0x4000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		 _gp = .;
 		 *(.got*);
 	} :data
+	
 	.data : {
 		*(.data);
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -36,5 +39,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
@@ -42,11 +47,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/lib/c/arch/sparc64/src/entry.s
===================================================================
--- uspace/lib/c/arch/sparc64/src/entry.s	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/arch/sparc64/src/entry.s	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,5 +45,5 @@
 	flushw
 	add %g0, -0x7ff, %fp
-
+	
 	# Pass pcb_ptr as the first argument to __main()
 	mov %i1, %o0
@@ -51,5 +51,2 @@
 	call __main
 	or %l7, %lo(_gp), %l7
-
-	call __exit
-	nop
Index: uspace/lib/c/generic/as.c
===================================================================
--- uspace/lib/c/generic/as.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/as.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,4 +35,5 @@
 #include <as.h>
 #include <libc.h>
+#include <errno.h>
 #include <unistd.h>
 #include <align.h>
@@ -40,7 +41,5 @@
 #include <bitops.h>
 #include <malloc.h>
-
-/** Last position allocated by as_get_mappable_page */
-static uintptr_t last_allocated = 0;
+#include "private/libc.h"
 
 /** Create address space area.
@@ -103,27 +102,41 @@
 }
 
-/** Return pointer to some unmapped area, where fits new as_area
+/** Return pointer to unmapped address space area
  *
  * @param size Requested size of the allocation.
  *
- * @return pointer to the beginning
+ * @return Pointer to the beginning of unmapped address space area.
  *
  */
 void *as_get_mappable_page(size_t size)
 {
-	if (size == 0)
-		return NULL;
+	return (void *) __SYSCALL2(SYS_AS_GET_UNMAPPED_AREA,
+	    (sysarg_t) __entry, (sysarg_t) size);
+}
+
+/** Find mapping to physical address.
+ *
+ * @param address Virtual address in question (virtual).
+ * @param[out] frame Frame address (physical).
+ * @return Error code.
+ * @retval EOK No error, @p frame holds the translation.
+ * @retval ENOENT Mapping not found.
+ */
+int as_get_physical_mapping(void *address, uintptr_t *frame)
+{
+	uintptr_t tmp_frame;
+	uintptr_t virt = (uintptr_t) address;
 	
-	size_t sz = 1 << (fnzb(size - 1) + 1);
-	if (last_allocated == 0)
-		last_allocated = get_max_heap_addr();
+	int rc = (int) __SYSCALL2(SYS_PAGE_FIND_MAPPING,
+	    (sysarg_t) virt, (sysarg_t) &tmp_frame);
+	if (rc != EOK) {
+		return rc;
+	}
 	
-	/*
-	 * Make sure we allocate from naturally aligned address.
-	 */
-	uintptr_t res = ALIGN_UP(last_allocated, sz);
-	last_allocated = res + ALIGN_UP(size, PAGE_SIZE);
+	if (frame != NULL) {
+		*frame = tmp_frame;
+	}
 	
-	return ((void *) res);
+	return EOK;
 }
 
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/async.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -43,9 +43,4 @@
  * framework will automatically take care of most synchronization problems.
  *
- * Default semantics:
- * - async_send_*(): Send asynchronously. If the kernel refuses to send
- *                   more messages, [ try to get responses from kernel, if
- *                   nothing found, might try synchronous ]
- *
  * Example of use (pseudo C):
  *
@@ -58,5 +53,5 @@
  *   int fibril1(void *arg)
  *   {
- *     conn = ipc_connect_me_to();
+ *     conn = async_connect_me_to();
  *     c1 = async_send(conn);
  *     c2 = async_send(conn);
@@ -77,12 +72,12 @@
  *   {
  *     if (want_refuse) {
- *       ipc_answer_0(icallid, ELIMIT);
+ *       async_answer_0(icallid, ELIMIT);
  *       return;
  *     }
- *     ipc_answer_0(icallid, EOK);
+ *     async_answer_0(icallid, EOK);
  *
  *     callid = async_get_call(&call);
  *     somehow_handle_the_call(callid, call);
- *     ipc_answer_2(callid, 1, 2, 3);
+ *     async_answer_2(callid, 1, 2, 3);
  *
  *     callid = async_get_call(&call);
@@ -92,12 +87,14 @@
  */
 
+#define LIBC_ASYNC_C_
+#include <ipc/ipc.h>
+#include <async.h>
+#undef LIBC_ASYNC_C_
+
 #include <futex.h>
-#include <async.h>
-#include <async_priv.h>
 #include <fibril.h>
 #include <stdio.h>
 #include <adt/hash_table.h>
 #include <adt/list.h>
-#include <ipc/ipc.h>
 #include <assert.h>
 #include <errno.h>
@@ -105,4 +102,5 @@
 #include <arch/barrier.h>
 #include <bool.h>
+#include "private/async.h"
 
 atomic_t async_futex = FUTEX_INITIALIZER;
@@ -124,6 +122,6 @@
 
 /**
- * Structures of this type are used to group information about a call and a
- * message queue link.
+ * Structures of this type are used to group information about
+ * a call and about a message queue link.
  */
 typedef struct {
@@ -134,4 +132,11 @@
 
 typedef struct {
+	sysarg_t in_task_hash;
+	link_t link;
+	int refcnt;
+	void *data;
+} client_t;
+
+typedef struct {
 	awaiter_t wdata;
 	
@@ -139,6 +144,11 @@
 	link_t link;
 	
+	/** Incoming client task hash. */
+	sysarg_t in_task_hash;
 	/** Incoming phone hash. */
 	sysarg_t in_phone_hash;
+	
+	/** Link to the client tracking structure. */
+	client_t *client;
 	
 	/** Messages that should be delivered to this fibril. */
@@ -158,8 +168,48 @@
 
 /** Identifier of the incoming connection handled by the current fibril. */
-fibril_local connection_t *FIBRIL_connection;
-
-static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
-static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
+static fibril_local connection_t *FIBRIL_connection;
+
+static void *default_client_data_constructor(void)
+{
+	return NULL;
+}
+
+static void default_client_data_destructor(void *data)
+{
+}
+
+static async_client_data_ctor_t async_client_data_create =
+    default_client_data_constructor;
+static async_client_data_dtor_t async_client_data_destroy =
+    default_client_data_destructor;
+
+void async_set_client_data_constructor(async_client_data_ctor_t ctor)
+{
+	async_client_data_create = ctor;
+}
+
+void async_set_client_data_destructor(async_client_data_dtor_t dtor)
+{
+	async_client_data_destroy = dtor;
+}
+
+void *async_client_data_get(void)
+{
+	assert(FIBRIL_connection);
+	return FIBRIL_connection->client->data;
+}
+
+/** Default fibril function that gets called to handle new connection.
+ *
+ * This function is defined as a weak symbol - to be redefined in user code.
+ *
+ * @param callid Hash of the incoming call.
+ * @param call   Data of the incoming call.
+ *
+ */
+static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_answer_0(callid, ENOENT);
+}
 
 /**
@@ -167,4 +217,16 @@
  */
 static async_client_conn_t client_connection = default_client_connection;
+
+/** Default fibril function that gets called to handle interrupt notifications.
+ *
+ * This function is defined as a weak symbol - to be redefined in user code.
+ *
+ * @param callid Hash of the incoming call.
+ * @param call   Data of the incoming call.
+ *
+ */
+static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)
+{
+}
 
 /**
@@ -174,8 +236,33 @@
 static async_client_conn_t interrupt_received = default_interrupt_received;
 
+static hash_table_t client_hash_table;
 static hash_table_t conn_hash_table;
 static LIST_INITIALIZE(timeout_list);
 
-#define CONN_HASH_TABLE_CHAINS  32
+#define CLIENT_HASH_TABLE_BUCKETS  32
+#define CONN_HASH_TABLE_BUCKETS    32
+
+static hash_index_t client_hash(unsigned long key[])
+{
+	assert(key);
+	return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
+}
+
+static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
+{
+	client_t *client = hash_table_get_instance(item, client_t, link);
+	return (key[0] == client->in_task_hash);
+}
+
+static void client_remove(link_t *item)
+{
+}
+
+/** Operations for the client hash table. */
+static hash_table_operations_t client_hash_table_ops = {
+	.hash = client_hash,
+	.compare = client_compare,
+	.remove_callback = client_remove
+};
 
 /** Compute hash into the connection hash table based on the source phone hash.
@@ -186,8 +273,8 @@
  *
  */
-static hash_index_t conn_hash(unsigned long *key)
+static hash_index_t conn_hash(unsigned long key[])
 {
 	assert(key);
-	return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS);
+	return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
 }
 
@@ -203,21 +290,11 @@
 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
 {
-	connection_t *hs = hash_table_get_instance(item, connection_t, link);
-	return (key[0] == hs->in_phone_hash);
-}
-
-/** Connection hash table removal callback function.
- *
- * This function is called whenever a connection is removed from the connection
- * hash table.
- *
- * @param item Connection hash table item being removed.
- *
- */
+	connection_t *conn = hash_table_get_instance(item, connection_t, link);
+	return (key[0] == conn->in_phone_hash);
+}
+
 static void conn_remove(link_t *item)
 {
-	free(hash_table_get_instance(item, connection_t, link));
-}
-
+}
 
 /** Operations for the connection hash table. */
@@ -240,9 +317,10 @@
 	link_t *tmp = timeout_list.next;
 	while (tmp != &timeout_list) {
-		awaiter_t *cur;
-		
-		cur = list_get_instance(tmp, awaiter_t, to_event.link);
+		awaiter_t *cur
+		    = list_get_instance(tmp, awaiter_t, to_event.link);
+		
 		if (tv_gteq(&cur->to_event.expires, &wd->to_event.expires))
 			break;
+		
 		tmp = tmp->next;
 	}
@@ -261,5 +339,5 @@
  *
  * @return False if the call doesn't match any connection.
- *         True if the call was passed to the respective connection fibril.
+ * @return True if the call was passed to the respective connection fibril.
  *
  */
@@ -352,4 +430,10 @@
 	
 	fid_t fid = fibril_create(notification_fibril, msg);
+	if (fid == 0) {
+		free(msg);
+		futex_up(&async_futex);
+		return false;
+	}
+	
 	fibril_add_ready(fid);
 	
@@ -398,5 +482,5 @@
 			 * the first IPC_M_PHONE_HUNGUP call and continues to
 			 * call async_get_call_timeout(). Repeat
-			 * IPC_M_PHONE_HUNGUP until the caller notices. 
+			 * IPC_M_PHONE_HUNGUP until the caller notices.
 			 */
 			memset(call, 0, sizeof(ipc_call_t));
@@ -405,5 +489,5 @@
 			return conn->close_callid;
 		}
-
+		
 		if (usecs)
 			async_insert_timeout(&conn->wdata);
@@ -443,29 +527,4 @@
 }
 
-/** Default fibril function that gets called to handle new connection.
- *
- * This function is defined as a weak symbol - to be redefined in user code.
- *
- * @param callid Hash of the incoming call.
- * @param call   Data of the incoming call.
- *
- */
-static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
-{
-	ipc_answer_0(callid, ENOENT);
-}
-
-/** Default fibril function that gets called to handle interrupt notifications.
- *
- * This function is defined as a weak symbol - to be redefined in user code.
- *
- * @param callid Hash of the incoming call.
- * @param call   Data of the incoming call.
- *
- */
-static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)
-{
-}
-
 /** Wrapper for client connection fibril.
  *
@@ -481,23 +540,90 @@
 {
 	/*
-	 * Setup fibril-local connection pointer and call client_connection().
-	 *
+	 * Setup fibril-local connection pointer.
 	 */
 	FIBRIL_connection = (connection_t *) arg;
+	
+	futex_down(&async_futex);
+	
+	/*
+	 * Add our reference for the current connection in the client task
+	 * tracking structure. If this is the first reference, create and
+	 * hash in a new tracking structure.
+	 */
+	
+	unsigned long key = FIBRIL_connection->in_task_hash;
+	link_t *lnk = hash_table_find(&client_hash_table, &key);
+	
+	client_t *client;
+	
+	if (lnk) {
+		client = hash_table_get_instance(lnk, client_t, link);
+		client->refcnt++;
+	} else {
+		client = malloc(sizeof(client_t));
+		if (!client) {
+			ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
+			futex_up(&async_futex);
+			return 0;
+		}
+		
+		client->in_task_hash = FIBRIL_connection->in_task_hash;
+		
+		async_serialize_start();
+		client->data = async_client_data_create();
+		async_serialize_end();
+		
+		client->refcnt = 1;
+		hash_table_insert(&client_hash_table, &key, &client->link);
+	}
+	
+	futex_up(&async_futex);
+	
+	FIBRIL_connection->client = client;
+	
+	/*
+	 * Call the connection handler function.
+	 */
 	FIBRIL_connection->cfibril(FIBRIL_connection->callid,
 	    &FIBRIL_connection->call);
 	
-	/* Remove myself from the connection hash table */
+	/*
+	 * Remove the reference for this client task connection.
+	 */
+	bool destroy;
+	
 	futex_down(&async_futex);
-	unsigned long key = FIBRIL_connection->in_phone_hash;
+	
+	if (--client->refcnt == 0) {
+		hash_table_remove(&client_hash_table, &key, 1);
+		destroy = true;
+	} else
+		destroy = false;
+	
+	futex_up(&async_futex);
+	
+	if (destroy) {
+		if (client->data)
+			async_client_data_destroy(client->data);
+		
+		free(client);
+	}
+	
+	/*
+	 * Remove myself from the connection hash table.
+	 */
+	futex_down(&async_futex);
+	key = FIBRIL_connection->in_phone_hash;
 	hash_table_remove(&conn_hash_table, &key, 1);
 	futex_up(&async_futex);
 	
-	/* Answer all remaining messages with EHANGUP */
+	/*
+	 * Answer all remaining messages with EHANGUP.
+	 */
 	while (!list_empty(&FIBRIL_connection->msg_queue)) {
-		msg_t *msg;
-		
-		msg = list_get_instance(FIBRIL_connection->msg_queue.next,
-		    msg_t, link);
+		msg_t *msg =
+		    list_get_instance(FIBRIL_connection->msg_queue.next, msg_t,
+		    link);
+		
 		list_remove(&msg->link);
 		ipc_answer_0(msg->callid, EHANGUP);
@@ -505,7 +631,12 @@
 	}
 	
+	/*
+	 * If the connection was hung-up, answer the last call,
+	 * i.e. IPC_M_PHONE_HUNGUP.
+	 */
 	if (FIBRIL_connection->close_callid)
 		ipc_answer_0(FIBRIL_connection->close_callid, EOK);
 	
+	free(FIBRIL_connection);
 	return 0;
 }
@@ -517,4 +648,5 @@
  * particular fibrils.
  *
+ * @param in_task_hash  Identification of the incoming connection.
  * @param in_phone_hash Identification of the incoming connection.
  * @param callid        Hash of the opening IPC_M_CONNECT_ME_TO call.
@@ -529,6 +661,7 @@
  *
  */
-fid_t async_new_connection(sysarg_t in_phone_hash, ipc_callid_t callid,
-    ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *))
+fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash,
+    ipc_callid_t callid, ipc_call_t *call,
+    void (*cfibril)(ipc_callid_t, ipc_call_t *))
 {
 	connection_t *conn = malloc(sizeof(*conn));
@@ -536,7 +669,9 @@
 		if (callid)
 			ipc_answer_0(callid, ENOMEM);
+		
 		return (uintptr_t) NULL;
 	}
 	
+	conn->in_task_hash = in_task_hash;
 	conn->in_phone_hash = in_phone_hash;
 	list_initialize(&conn->msg_queue);
@@ -552,8 +687,10 @@
 	conn->wdata.fid = fibril_create(connection_fibril, conn);
 	
-	if (!conn->wdata.fid) {
+	if (conn->wdata.fid == 0) {
 		free(conn);
+		
 		if (callid)
 			ipc_answer_0(callid, ENOMEM);
+		
 		return (uintptr_t) NULL;
 	}
@@ -582,8 +719,8 @@
 static void handle_call(ipc_callid_t callid, ipc_call_t *call)
 {
-	/* Unrouted call - do some default behaviour */
+	/* Unrouted call - take some default action */
 	if ((callid & IPC_CALLID_NOTIFICATION)) {
 		process_notification(callid, call);
-		goto out;
+		return;
 	}
 	
@@ -591,20 +728,16 @@
 	case IPC_M_CONNECT_ME:
 	case IPC_M_CONNECT_ME_TO:
-		/* Open new connection with fibril etc. */
-		async_new_connection(IPC_GET_ARG5(*call), callid, call,
-		    client_connection);
-		goto out;
+		/* Open new connection with fibril, etc. */
+		async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call),
+		    callid, call, client_connection);
+		return;
 	}
 	
 	/* Try to route the call through the connection hash table */
 	if (route_call(callid, call))
-		goto out;
+		return;
 	
 	/* Unknown call from unknown phone - hang it up */
 	ipc_answer_0(callid, EHANGUP);
-	return;
-	
-out:
-	;
 }
 
@@ -619,12 +752,12 @@
 	link_t *cur = timeout_list.next;
 	while (cur != &timeout_list) {
-		awaiter_t *waiter;
-		
-		waiter = list_get_instance(cur, awaiter_t, to_event.link);
+		awaiter_t *waiter =
+		    list_get_instance(cur, awaiter_t, to_event.link);
+		
 		if (tv_gt(&waiter->to_event.expires, &tv))
 			break;
-
+		
 		cur = cur->next;
-
+		
 		list_remove(&waiter->to_event.link);
 		waiter->to_event.inlist = false;
@@ -653,5 +786,5 @@
 	while (true) {
 		if (fibril_switch(FIBRIL_FROM_MANAGER)) {
-			futex_up(&async_futex); 
+			futex_up(&async_futex);
 			/*
 			 * async_futex is always held when entering a manager
@@ -676,11 +809,10 @@
 				continue;
 			} else
-				timeout = tv_sub(&waiter->to_event.expires,
-				    &tv);
+				timeout = tv_sub(&waiter->to_event.expires, &tv);
 		} else
 			timeout = SYNCH_NO_TIMEOUT;
 		
 		futex_up(&async_futex);
-
+		
 		atomic_inc(&threads_in_ipc_wait);
 		
@@ -690,5 +822,5 @@
 		
 		atomic_dec(&threads_in_ipc_wait);
-
+		
 		if (!callid) {
 			handle_expired_timeouts();
@@ -729,5 +861,6 @@
 {
 	fid_t fid = fibril_create(async_manager_fibril, NULL);
-	fibril_add_manager(fid);
+	if (fid != 0)
+		fibril_add_manager(fid);
 }
 
@@ -740,17 +873,14 @@
 /** Initialize the async framework.
  *
- * @return Zero on success or an error code.
- */
-int __async_init(void)
-{
-	if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1,
-	    &conn_hash_table_ops)) {
-		printf("%s: Cannot create async hash table\n", "libc");
-		return ENOMEM;
-	}
-
-	_async_sess_init();
-	
-	return 0;
+ */
+void __async_init(void)
+{
+	if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,
+	    &client_hash_table_ops))
+		abort();
+	
+	if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1,
+	    &conn_hash_table_ops))
+		abort();
 }
 
@@ -765,4 +895,5 @@
  * @param retval Value returned in the answer.
  * @param data   Call data of the answer.
+ *
  */
 static void reply_received(void *arg, int retval, ipc_call_t *data)
@@ -812,5 +943,5 @@
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
 {
-	amsg_t *msg = malloc(sizeof(*msg));
+	amsg_t *msg = malloc(sizeof(amsg_t));
 	
 	if (!msg)
@@ -821,5 +952,9 @@
 	
 	msg->wdata.to_event.inlist = false;
-	/* We may sleep in the next method, but it will use its own mechanism */
+	
+	/*
+	 * We may sleep in the next method,
+	 * but it will use its own means
+	 */
 	msg->wdata.active = true;
 	
@@ -852,5 +987,5 @@
     ipc_call_t *dataptr)
 {
-	amsg_t *msg = malloc(sizeof(*msg));
+	amsg_t *msg = malloc(sizeof(amsg_t));
 	
 	if (!msg)
@@ -861,5 +996,9 @@
 	
 	msg->wdata.to_event.inlist = false;
-	/* We may sleep in next method, but it will use its own mechanism */
+	
+	/*
+	 * We may sleep in the next method,
+	 * but it will use its own means
+	 */
 	msg->wdata.active = true;
 	
@@ -960,5 +1099,5 @@
 void async_usleep(suseconds_t timeout)
 {
-	amsg_t *msg = malloc(sizeof(*msg));
+	amsg_t *msg = malloc(sizeof(amsg_t));
 	
 	if (!msg)
@@ -1103,78 +1242,215 @@
 }
 
+void async_msg_0(int phone, sysarg_t imethod)
+{
+	ipc_call_async_0(phone, imethod, NULL, NULL, true);
+}
+
+void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1)
+{
+	ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true);
+}
+
+void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2)
+{
+	ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true);
+}
+
+void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3)
+{
+	ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true);
+}
+
+void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, sysarg_t arg4)
+{
+	ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL,
+	    true);
+}
+
+void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
+{
+	ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL,
+	    NULL, true);
+}
+
+sysarg_t async_answer_0(ipc_callid_t callid, sysarg_t retval)
+{
+	return ipc_answer_0(callid, retval);
+}
+
+sysarg_t async_answer_1(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1)
+{
+	return ipc_answer_1(callid, retval, arg1);
+}
+
+sysarg_t async_answer_2(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
+    sysarg_t arg2)
+{
+	return ipc_answer_2(callid, retval, arg1, arg2);
+}
+
+sysarg_t async_answer_3(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3)
+{
+	return ipc_answer_3(callid, retval, arg1, arg2, arg3);
+}
+
+sysarg_t async_answer_4(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
+{
+	return ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4);
+}
+
+sysarg_t async_answer_5(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
+{
+	return ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5);
+}
+
+int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
+    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
+{
+	return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode);
+}
+
+int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
+    unsigned int mode)
+{
+	return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4,
+	    arg5, mode);
+}
+
+/** Wrapper for making IPC_M_CONNECT_TO_ME calls using the async framework.
+ *
+ * Ask through phone for a new connection to some service.
+ *
+ * @param phone           Phone handle used for contacting the other side.
+ * @param arg1            User defined argument.
+ * @param arg2            User defined argument.
+ * @param arg3            User defined argument.
+ * @param client_receiver Connection handing routine.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, async_client_conn_t client_receiver)
+{
+	sysarg_t task_hash;
+	sysarg_t phone_hash;
+	int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
+	    NULL, NULL, NULL, &task_hash, &phone_hash);
+	if (rc != EOK)
+		return rc;
+	
+	if (client_receiver != NULL)
+		async_new_connection(task_hash, phone_hash, 0, NULL,
+		    client_receiver);
+	
+	return EOK;
+}
+
 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
- * 
+ *
  * Ask through phone for a new connection to some service.
  *
- * @param phoneid	Phone handle used for contacting the other side.
- * @param arg1		User defined argument.
- * @param arg2		User defined argument.
- * @param arg3		User defined argument.
- *
- * @return		New phone handle on success or a negative error code.
- */
-int
-async_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
-{
-	int rc;
+ * @param phone Phone handle used for contacting the other side.
+ * @param arg1  User defined argument.
+ * @param arg2  User defined argument.
+ * @param arg3  User defined argument.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3)
+{
 	sysarg_t newphid;
-
-	rc = async_req_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, NULL,
-	    NULL, NULL, NULL, &newphid);
-	
-	if (rc != EOK)	
+	int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
+	    NULL, NULL, NULL, NULL, &newphid);
+	
+	if (rc != EOK)
 		return rc;
-
+	
 	return newphid;
 }
 
 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
- * 
+ *
  * Ask through phone for a new connection to some service and block until
  * success.
  *
- * @param phoneid	Phone handle used for contacting the other side.
- * @param arg1		User defined argument.
- * @param arg2		User defined argument.
- * @param arg3		User defined argument.
- *
- * @return		New phone handle on success or a negative error code.
- */
-int
-async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
+ * @param phoneid Phone handle used for contacting the other side.
+ * @param arg1    User defined argument.
+ * @param arg2    User defined argument.
+ * @param arg3    User defined argument.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
     sysarg_t arg3)
 {
-	int rc;
 	sysarg_t newphid;
-
-	rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
+	int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
 	    IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
 	
-	if (rc != EOK)	
+	if (rc != EOK)
 		return rc;
-
+	
 	return newphid;
 }
 
-/** Wrapper for making IPC_M_SHARE_IN calls using the async framework.
- *
- * @param phoneid	Phone that will be used to contact the receiving side.
- * @param dst		Destination address space area base.
- * @param size		Size of the destination address space area.
- * @param arg		User defined argument.
- * @param flags		Storage where the received flags will be stored. Can be
- *			NULL.
- *
- * @return		Zero on success or a negative error code from errno.h.
+/** Connect to a task specified by id.
+ *
+ */
+int async_connect_kbox(task_id_t id)
+{
+	return ipc_connect_kbox(id);
+}
+
+/** Wrapper for ipc_hangup.
+ *
+ * @param phone Phone handle to hung up.
+ *
+ * @return Zero on success or a negative error code.
+ *
+ */
+int async_hangup(int phone)
+{
+	return ipc_hangup(phone);
+}
+
+/** Interrupt one thread of this task from waiting for IPC. */
+void async_poke(void)
+{
+	ipc_poke();
+}
+
+/** Wrapper for IPC_M_SHARE_IN calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst     Destination address space area base.
+ * @param size    Size of the destination address space area.
+ * @param arg     User defined argument.
+ * @param flags   Storage for the received flags. Can be NULL.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
  */
 int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
-    int *flags)
-{
-	int res;
+    unsigned int *flags)
+{
 	sysarg_t tmp_flags;
-	res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
+	int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
 	    (sysarg_t) size, arg, NULL, &tmp_flags);
+	
 	if (flags)
-		*flags = tmp_flags;
+		*flags = (unsigned int) tmp_flags;
+	
 	return res;
 }
@@ -1182,54 +1458,59 @@
 /** Wrapper for receiving the IPC_M_SHARE_IN calls using the async framework.
  *
- * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
+ * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN
+ * calls so that the user doesn't have to remember the meaning of each IPC
+ * argument.
  *
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid	Storage where the hash of the IPC_M_SHARE_IN call will
- * 			be stored.
- * @param size		Destination address space area size.	
- *
- * @return		Non-zero on success, zero on failure.
- */
-int async_share_in_receive(ipc_callid_t *callid, size_t *size)
-{
-	ipc_call_t data;
-	
+ * @param callid Storage for the hash of the IPC_M_SHARE_IN call.
+ * @param size   Destination address space area size.
+ *
+ * @return True on success, false on failure.
+ *
+ */
+bool async_share_in_receive(ipc_callid_t *callid, size_t *size)
+{
 	assert(callid);
 	assert(size);
-
+	
+	ipc_call_t data;
 	*callid = async_get_call(&data);
+	
 	if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_IN)
-		return 0;
+		return false;
+	
 	*size = (size_t) IPC_GET_ARG2(data);
-	return 1;
+	return true;
 }
 
 /** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework.
  *
- * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
- *
- * @param callid	Hash of the IPC_M_DATA_READ call to answer.
- * @param src		Source address space base.
- * @param flags		Flags to be used for sharing. Bits can be only cleared.
- *
- * @return		Zero on success or a value from @ref errno.h on failure.
- */
-int async_share_in_finalize(ipc_callid_t callid, void *src, int flags)
+ * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
+ * calls so that the user doesn't have to remember the meaning of each IPC
+ * argument.
+ *
+ * @param callid Hash of the IPC_M_DATA_READ call to answer.
+ * @param src    Source address space base.
+ * @param flags  Flags to be used for sharing. Bits can be only cleared.
+ *
+ * @return Zero on success or a value from @ref errno.h on failure.
+ *
+ */
+int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
 {
 	return ipc_share_in_finalize(callid, src, flags);
 }
 
-/** Wrapper for making IPC_M_SHARE_OUT calls using the async framework.
- *
- * @param phoneid	Phone that will be used to contact the receiving side.
- * @param src		Source address space area base address.
- * @param flags		Flags to be used for sharing. Bits can be only cleared.
- *
- * @return		Zero on success or a negative error code from errno.h.
- */
-int async_share_out_start(int phoneid, void *src, int flags)
+/** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param src     Source address space area base address.
+ * @param flags   Flags to be used for sharing. Bits can be only cleared.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
+ */
+int async_share_out_start(int phoneid, void *src, unsigned int flags)
 {
 	return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
@@ -1239,42 +1520,45 @@
 /** Wrapper for receiving the IPC_M_SHARE_OUT calls using the async framework.
  *
- * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
+ * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT
+ * calls so that the user doesn't have to remember the meaning of each IPC
+ * argument.
  *
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid	Storage where the hash of the IPC_M_SHARE_OUT call will
- * 			be stored.
- * @param size		Storage where the source address space area size will be
- *			stored.
- * @param flags		Storage where the sharing flags will be stored.
- *
- * @return		Non-zero on success, zero on failure.
- */
-int async_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags)
-{
-	ipc_call_t data;
-	
+ * @param callid Storage for the hash of the IPC_M_SHARE_OUT call.
+ * @param size   Storage for the source address space area size.
+ * @param flags  Storage for the sharing flags.
+ *
+ * @return True on success, false on failure.
+ *
+ */
+bool async_share_out_receive(ipc_callid_t *callid, size_t *size, unsigned int *flags)
+{
 	assert(callid);
 	assert(size);
 	assert(flags);
-
+	
+	ipc_call_t data;
 	*callid = async_get_call(&data);
+	
 	if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_OUT)
-		return 0;
+		return false;
+	
 	*size = (size_t) IPC_GET_ARG2(data);
-	*flags = (int) IPC_GET_ARG3(data);
-	return 1;
+	*flags = (unsigned int) IPC_GET_ARG3(data);
+	return true;
 }
 
 /** Wrapper for answering the IPC_M_SHARE_OUT calls using the async framework.
  *
- * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
- *
- * @param callid	Hash of the IPC_M_DATA_WRITE call to answer.
- * @param dst		Destination address space area base address.	
- *
- * @return		Zero on success or a value from @ref errno.h on failure.
+ * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT
+ * calls so that the user doesn't have to remember the meaning of each IPC
+ * argument.
+ *
+ * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
+ * @param dst    Destination address space area base address.
+ *
+ * @return Zero on success or a value from @ref errno.h on failure.
+ *
  */
 int async_share_out_finalize(ipc_callid_t callid, void *dst)
@@ -1283,12 +1567,26 @@
 }
 
-
-/** Wrapper for making IPC_M_DATA_READ calls using the async framework.
- *
- * @param phoneid	Phone that will be used to contact the receiving side.
- * @param dst		Address of the beginning of the destination buffer.
- * @param size		Size of the destination buffer.
- *
- * @return		Zero on success or a negative error code from errno.h.
+/** Start IPC_M_DATA_READ using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst Address of the beginning of the destination buffer.
+ * @param size Size of the destination buffer (in bytes).
+ * @param dataptr Storage of call data (arg 2 holds actual data size).
+ * @return Hash of the sent message or 0 on error.
+ */
+aid_t async_data_read(int phoneid, void *dst, size_t size, ipc_call_t *dataptr)
+{
+	return async_send_2(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
+	    (sysarg_t) size, dataptr);
+}
+
+/** Wrapper for IPC_M_DATA_READ calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst     Address of the beginning of the destination buffer.
+ * @param size    Size of the destination buffer.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
  */
 int async_data_read_start(int phoneid, void *dst, size_t size)
@@ -1300,41 +1598,45 @@
 /** Wrapper for receiving the IPC_M_DATA_READ calls using the async framework.
  *
- * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
+ * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ
+ * calls so that the user doesn't have to remember the meaning of each IPC
+ * argument.
  *
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid	Storage where the hash of the IPC_M_DATA_READ call will
- * 			be stored.
- * @param size		Storage where the maximum size will be stored. Can be
- *			NULL.
- *
- * @return		Non-zero on success, zero on failure.
- */
-int async_data_read_receive(ipc_callid_t *callid, size_t *size)
-{
+ * @param callid Storage for the hash of the IPC_M_DATA_READ.
+ * @param size   Storage for the maximum size. Can be NULL.
+ *
+ * @return True on success, false on failure.
+ *
+ */
+bool async_data_read_receive(ipc_callid_t *callid, size_t *size)
+{
+	assert(callid);
+	
 	ipc_call_t data;
-	
-	assert(callid);
-
 	*callid = async_get_call(&data);
+	
 	if (IPC_GET_IMETHOD(data) != IPC_M_DATA_READ)
-		return 0;
+		return false;
+	
 	if (size)
 		*size = (size_t) IPC_GET_ARG2(data);
-	return 1;
+	
+	return true;
 }
 
 /** Wrapper for answering the IPC_M_DATA_READ calls using the async framework.
  *
- * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
- *
- * @param callid	Hash of the IPC_M_DATA_READ call to answer.
- * @param src		Source address for the IPC_M_DATA_READ call.
- * @param size		Size for the IPC_M_DATA_READ call. Can be smaller than
- *			the maximum size announced by the sender.
- *
- * @return		Zero on success or a value from @ref errno.h on failure.
+ * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
+ * calls so that the user doesn't have to remember the meaning of each IPC
+ * argument.
+ *
+ * @param callid Hash of the IPC_M_DATA_READ call to answer.
+ * @param src    Source address for the IPC_M_DATA_READ call.
+ * @param size   Size for the IPC_M_DATA_READ call. Can be smaller than
+ *               the maximum size announced by the sender.
+ *
+ * @return Zero on success or a value from @ref errno.h on failure.
+ *
  */
 int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
@@ -1344,5 +1646,4 @@
 
 /** Wrapper for forwarding any read request
- *
  *
  */
@@ -1377,5 +1678,5 @@
 }
 
-/** Wrapper for making IPC_M_DATA_WRITE calls using the async framework.
+/** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
  *
  * @param phoneid Phone that will be used to contact the receiving side.
@@ -1394,37 +1695,37 @@
 /** Wrapper for receiving the IPC_M_DATA_WRITE calls using the async framework.
  *
- * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
+ * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE
+ * calls so that the user doesn't have to remember the meaning of each IPC
+ * argument.
  *
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid Storage where the hash of the IPC_M_DATA_WRITE call will
- *               be stored.
- * @param size   Storage where the suggested size will be stored. May be
- *               NULL
- *
- * @return Non-zero on success, zero on failure.
- *
- */
-int async_data_write_receive(ipc_callid_t *callid, size_t *size)
-{
+ * @param callid Storage for the hash of the IPC_M_DATA_WRITE.
+ * @param size   Storage for the suggested size. May be NULL.
+ *
+ * @return True on success, false on failure.
+ *
+ */
+bool async_data_write_receive(ipc_callid_t *callid, size_t *size)
+{
+	assert(callid);
+	
 	ipc_call_t data;
-	
-	assert(callid);
-	
 	*callid = async_get_call(&data);
+	
 	if (IPC_GET_IMETHOD(data) != IPC_M_DATA_WRITE)
-		return 0;
+		return false;
 	
 	if (size)
 		*size = (size_t) IPC_GET_ARG2(data);
 	
-	return 1;
+	return true;
 }
 
 /** Wrapper for answering the IPC_M_DATA_WRITE calls using the async framework.
  *
- * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
+ * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE
+ * calls so that the user doesn't have to remember the meaning of each IPC
+ * argument.
  *
  * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
@@ -1522,5 +1823,5 @@
  *
  */
-void async_data_write_void(const int retval)
+void async_data_write_void(sysarg_t retval)
 {
 	ipc_callid_t callid;
@@ -1530,5 +1831,4 @@
 
 /** Wrapper for forwarding any data that is about to be received
- *
  *
  */
Index: uspace/lib/c/generic/async_sess.c
===================================================================
--- uspace/lib/c/generic/async_sess.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/async_sess.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -99,5 +99,4 @@
 
 #include <async_sess.h>
-#include <ipc/ipc.h>
 #include <fibril_synch.h>
 #include <adt/list.h>
@@ -106,4 +105,5 @@
 #include <errno.h>
 #include <assert.h>
+#include "private/async_sess.h"
 
 /** An inactive open connection. */
@@ -138,6 +138,7 @@
  *
  * Needs to be called prior to any other interface in this file.
- */
-void _async_sess_init(void)
+ *
+ */
+void __async_sess_init(void)
 {
 	fibril_mutex_initialize(&async_sess_mutex);
@@ -200,5 +201,5 @@
 		list_remove(&conn->global_link);
 		
-		ipc_hangup(conn->data_phone);
+		async_hangup(conn->data_phone);
 		free(conn);
 	}
@@ -260,5 +261,5 @@
 			data_phone = conn->data_phone;
 			free(conn);
-			ipc_hangup(data_phone);
+			async_hangup(data_phone);
 			goto retry;
 		} else {
@@ -292,5 +293,5 @@
 		 * means that we simply hang up.
 		 */
-		ipc_hangup(data_phone);
+		async_hangup(data_phone);
 		fibril_mutex_unlock(&async_sess_mutex);
 		return;
Index: uspace/lib/c/generic/clipboard.c
===================================================================
--- uspace/lib/c/generic/clipboard.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/clipboard.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,4 +39,5 @@
 
 #include <clipboard.h>
+#include <ipc/ns.h>
 #include <ipc/services.h>
 #include <ipc/clipboard.h>
@@ -54,5 +55,5 @@
 {
 	while (clip_phone < 0)
-		clip_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_CLIPBOARD, 0, 0);
+		clip_phone = service_connect_blocking(SERVICE_CLIPBOARD, 0, 0);
 }
 
Index: uspace/lib/c/generic/ddi.c
===================================================================
--- uspace/lib/c/generic/ddi.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/ddi.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -127,4 +127,33 @@
 }
 
+/** Register IRQ notification.
+ *
+ * @param inr    IRQ number.
+ * @param devno  Device number of the device generating inr.
+ * @param method Use this method for notifying me.
+ * @param ucode  Top-half pseudocode handler.
+ *
+ * @return Value returned by the kernel.
+ *
+ */
+int register_irq(int inr, int devno, int method, irq_code_t *ucode)
+{
+	return __SYSCALL4(SYS_REGISTER_IRQ, inr, devno, method,
+	    (sysarg_t) ucode);
+}
+
+/** Unregister IRQ notification.
+ *
+ * @param inr   IRQ number.
+ * @param devno Device number of the device generating inr.
+ *
+ * @return Value returned by the kernel.
+ *
+ */
+int unregister_irq(int inr, int devno)
+{
+	return __SYSCALL2(SYS_UNREGISTER_IRQ, inr, devno);
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/devman.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -28,6 +28,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
- 
- /** @addtogroup libc
+
+/** @addtogroup libc
  * @{
  */
@@ -37,5 +37,4 @@
 #include <str.h>
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/devman.h>
@@ -116,6 +115,5 @@
 	async_set_client_connection(conn);
 	
-	sysarg_t callback_phonehash;
-	ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
+	async_connect_to_me(phone, 0, 0, 0, NULL);
 	async_wait_for(req, &retval);
 	
@@ -125,9 +123,13 @@
 }
 
-static int devman_send_match_id(int phone, match_id_t *match_id) \
-{
-	ipc_call_t answer;
-	aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score, &answer);
-	int retval = async_data_write_start(phone, match_id->id, str_size(match_id->id));
+static int devman_send_match_id(int phone, match_id_t *match_id)
+{
+	ipc_call_t answer;
+
+	aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score,
+	    &answer);
+	int retval = async_data_write_start(phone, match_id->id,
+	    str_size(match_id->id));
+
 	async_wait_for(req, NULL);
 	return retval;
@@ -135,26 +137,43 @@
 
 
-static int devman_send_match_ids(int phone, match_id_list_t *match_ids) 
+static int devman_send_match_ids(int phone, match_id_list_t *match_ids)
 {
 	link_t *link = match_ids->ids.next;
 	match_id_t *match_id = NULL;
 	int ret = EOK;
-	
+
 	while (link != &match_ids->ids) {
 		match_id = list_get_instance(link, match_id_t, link); 
-		if (EOK != (ret = devman_send_match_id(phone, match_id))) 
-		{
-			printf("Driver failed to send match id, error number = %d\n", ret);
-			return ret;			
-		}
+		ret = devman_send_match_id(phone, match_id);
+		if (ret != EOK) {
+			printf("Driver failed to send match id, error %d\n",
+			    ret);
+			return ret;
+		}
+
 		link = link->next;
 	}
-	return ret;	
-}
-
-int devman_child_device_register(
-	const char *name, match_id_list_t *match_ids, devman_handle_t parent_handle, devman_handle_t *handle)
-{		
+
+	return ret;
+}
+
+/** Add function to a device.
+ *
+ * Request devman to add a new function to the specified device owned by
+ * this driver task.
+ *
+ * @param name		Name of the new function
+ * @param ftype		Function type, fun_inner or fun_exposed
+ * @param match_ids	Match IDs (should be empty for fun_exposed)
+ * @param devh		Devman handle of the device
+ * @param funh		Place to store handle of the new function
+ *
+ * @return		EOK on success or negative error code.
+ */
+int devman_add_function(const char *name, fun_type_t ftype,
+    match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
+{
 	int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
+	int fun_handle;
 	
 	if (phone < 0)
@@ -163,7 +182,9 @@
 	async_serialize_start();
 	
-	int match_count = list_count(&match_ids->ids);	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAN_ADD_CHILD_DEVICE, parent_handle, match_count, &answer);
+	int match_count = list_count(&match_ids->ids);
+	ipc_call_t answer;
+
+	aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
+	    devh, match_count, &answer);
 
 	sysarg_t retval = async_data_write_start(phone, name, str_size(name));
@@ -180,18 +201,16 @@
 	async_serialize_end();
 	
-	if (retval != EOK) {
-		if (handle != NULL) {
-			*handle = -1;
-		}
-		return retval;
-	}	
-	
-	if (handle != NULL)
-		*handle = (int) IPC_GET_ARG1(answer);	
-		
-	return retval;
-}
-
-int devman_add_device_to_class(devman_handle_t devman_handle, const char *class_name)
+	if (retval == EOK)
+		fun_handle = (int) IPC_GET_ARG1(answer);
+	else
+		fun_handle = -1;
+	
+	*funh = fun_handle;
+
+	return retval;
+}
+
+int devman_add_device_to_class(devman_handle_t devman_handle,
+    const char *class_name)
 {
 	int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
@@ -202,7 +221,9 @@
 	async_serialize_start();
 	ipc_call_t answer;
-	aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS, devman_handle, &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, class_name, str_size(class_name));
+	aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS,
+	    devman_handle, &answer);
+	
+	sysarg_t retval = async_data_write_start(phone, class_name,
+	    str_size(class_name));
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
@@ -214,5 +235,5 @@
 	async_serialize_end();
 	
-	return retval;	
+	return retval;
 }
 
@@ -222,5 +243,5 @@
 	case DEVMAN_DRIVER:
 		if (devman_phone_driver >= 0) {
-			ipc_hangup(devman_phone_driver);
+			async_hangup(devman_phone_driver);
 			devman_phone_driver = -1;
 		}
@@ -228,5 +249,5 @@
 	case DEVMAN_CLIENT:
 		if (devman_phone_client >= 0) {
-			ipc_hangup(devman_phone_client);
+			async_hangup(devman_phone_client);
 			devman_phone_client = -1;
 		}
@@ -267,5 +288,6 @@
 }
 
-int devman_device_get_handle(const char *pathname, devman_handle_t *handle, unsigned int flags)
+int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
+    unsigned int flags)
 {
 	int phone = devman_get_phone(DEVMAN_CLIENT, flags);
@@ -280,5 +302,6 @@
 	    &answer);
 	
-	sysarg_t retval = async_data_write_start(phone, pathname, str_size(pathname));
+	sysarg_t retval = async_data_write_start(phone, pathname,
+	    str_size(pathname));
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
Index: uspace/lib/c/generic/devmap.c
===================================================================
--- uspace/lib/c/generic/devmap.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/devmap.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -29,6 +29,6 @@
 
 #include <str.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
+#include <ipc/ns.h>
 #include <ipc/devmap.h>
 #include <devmap.h>
@@ -50,9 +50,9 @@
 		
 		if (flags & IPC_FLAG_BLOCKING)
-			devmap_phone_driver = ipc_connect_me_to_blocking(PHONE_NS,
-			    SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
+			devmap_phone_driver = service_connect_blocking(SERVICE_DEVMAP,
+			    DEVMAP_DRIVER, 0);
 		else
-			devmap_phone_driver = ipc_connect_me_to(PHONE_NS,
-			    SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
+			devmap_phone_driver = service_connect(SERVICE_DEVMAP,
+			    DEVMAP_DRIVER, 0);
 		
 		return devmap_phone_driver;
@@ -62,9 +62,9 @@
 		
 		if (flags & IPC_FLAG_BLOCKING)
-			devmap_phone_client = ipc_connect_me_to_blocking(PHONE_NS,
-			    SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
+			devmap_phone_client = service_connect_blocking(SERVICE_DEVMAP,
+			    DEVMAP_CLIENT, 0);
 		else
-			devmap_phone_client = ipc_connect_me_to(PHONE_NS,
-			    SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
+			devmap_phone_client = service_connect(SERVICE_DEVMAP,
+			    DEVMAP_CLIENT, 0);
 		
 		return devmap_phone_client;
@@ -79,5 +79,5 @@
 	case DEVMAP_DRIVER:
 		if (devmap_phone_driver >= 0) {
-			ipc_hangup(devmap_phone_driver);
+			async_hangup(devmap_phone_driver);
 			devmap_phone_driver = -1;
 		}
@@ -85,5 +85,5 @@
 	case DEVMAP_CLIENT:
 		if (devmap_phone_client >= 0) {
-			ipc_hangup(devmap_phone_client);
+			async_hangup(devmap_phone_client);
 			devmap_phone_client = -1;
 		}
@@ -116,6 +116,5 @@
 	async_set_client_connection(conn);
 	
-	sysarg_t callback_phonehash;
-	ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
+	async_connect_to_me(phone, 0, 0, 0, NULL);
 	async_wait_for(req, &retval);
 	
Index: pace/lib/c/generic/err.c
===================================================================
--- uspace/lib/c/generic/err.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * 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 libc
- * @{
- */
-/** @file
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/* TODO
-void errx(int __status, __const char *__format, ...)
-{
-	_exit(0);
-}
-*/
-
-/** @}
- */
Index: uspace/lib/c/generic/event.c
===================================================================
--- uspace/lib/c/generic/event.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/event.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,10 +35,9 @@
  */
 /** @file
- */ 
+ */
 
 #include <libc.h>
 #include <event.h>
 #include <kernel/ipc/event_types.h>
-#include <ipc/ipc.h>
 
 /** Subscribe for event notifications.
Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/fibril.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -115,4 +115,6 @@
 	fibril->retval = 0;
 	fibril->flags = 0;
+	
+	fibril->waits_for = NULL;
 	
 	return fibril;
@@ -276,6 +278,4 @@
 	fibril->arg = arg;
 
-	fibril->waits_for = NULL;
-	
 	context_save(&fibril->ctx);
 	context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack,
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/fibril_synch.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
 #include <fibril.h>
 #include <async.h>
-#include <async_priv.h>
 #include <adt/list.h>
 #include <futex.h>
@@ -44,4 +43,5 @@
 #include <stacktrace.h>
 #include <stdlib.h>
+#include "private/async.h"
 
 static void optimize_execution_power(void)
@@ -55,5 +55,5 @@
 	 */
 	if (atomic_get(&threads_in_ipc_wait) > 0)
-		ipc_poke();
+		async_poke();
 }
 
@@ -105,5 +105,5 @@
 
 	if (fibril_get_sercount() != 0)
-		core();
+		abort();
 
 	futex_down(&async_futex);
@@ -198,5 +198,5 @@
 	
 	if (fibril_get_sercount() != 0)
-		core();
+		abort();
 
 	futex_down(&async_futex);
@@ -226,5 +226,5 @@
 	
 	if (fibril_get_sercount() != 0)
-		core();
+		abort();
 
 	futex_down(&async_futex);
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/io/io.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,8 +41,10 @@
 #include <bool.h>
 #include <malloc.h>
+#include <async.h>
 #include <io/klog.h>
 #include <vfs/vfs.h>
 #include <ipc/devmap.h>
 #include <adt/list.h>
+#include "../private/io.h"
 
 static void _ffillbuf(FILE *stream);
@@ -322,5 +324,5 @@
 	
 	if (stream->phone >= 0)
-		ipc_hangup(stream->phone);
+		async_hangup(stream->phone);
 	
 	if (stream->fd >= 0)
Index: uspace/lib/c/generic/ipc.c
===================================================================
--- uspace/lib/c/generic/ipc.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/ipc.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,21 +45,17 @@
 #include <errno.h>
 #include <adt/list.h>
-#include <stdio.h>
-#include <unistd.h>
 #include <futex.h>
-#include <kernel/synch/synch.h>
-#include <async.h>
 #include <fibril.h>
-#include <assert.h>
 
 /**
- * Structures of this type are used for keeping track of sent asynchronous calls
- * and queing unsent calls.
+ * Structures of this type are used for keeping track
+ * of sent asynchronous calls and queing unsent calls.
  */
 typedef struct {
 	link_t list;
-
+	
 	ipc_async_callback_t callback;
 	void *private;
+	
 	union {
 		ipc_callid_t callid;
@@ -69,5 +65,7 @@
 		} msg;
 	} u;
-	fid_t fid;	/**< Fibril waiting for sending this call. */
+	
+	/** Fibril waiting for sending this call. */
+	fid_t fid;
 } async_call_t;
 
@@ -76,6 +74,7 @@
 /** List of asynchronous calls that were not accepted by kernel.
  *
- * It is protected by async_futex, because if the call cannot be sent into the
- * kernel, the async framework is used automatically.
+ * Protected by async_futex, because if the call is not accepted
+ * by the kernel, the async framework is used automatically.
+ *
  */
 LIST_INITIALIZE(queued_calls);
@@ -83,36 +82,35 @@
 static atomic_t ipc_futex = FUTEX_INITIALIZER;
 
-/** Make a fast synchronous call.
- *
- * Only three payload arguments can be passed using this function. However, this
- * function is faster than the generic ipc_call_sync_slow() because the payload
- * is passed directly in registers.
- *
- * @param phoneid	Phone handle for the call.
- * @param method	Requested method.
- * @param arg1		Service-defined payload argument.
- * @param arg2		Service-defined payload argument.
- * @param arg3		Service-defined payload argument.
- * @param result1	If non-NULL, the return ARG1 will be stored there.
- * @param result2	If non-NULL, the return ARG2 will be stored there.
- * @param result3	If non-NULL, the return ARG3 will be stored there.
- * @param result4	If non-NULL, the return ARG4 will be stored there.
- * @param result5	If non-NULL, the return ARG5 will be stored there.
- *
- * @return		Negative values represent errors returned by IPC.
- *			Otherwise the RETVAL of the answer is returned.
- */
-int
-ipc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3, sysarg_t *result1, sysarg_t *result2, sysarg_t *result3,
-    sysarg_t *result4, sysarg_t *result5)
+/** Fast synchronous call.
+ *
+ * Only three payload arguments can be passed using this function. However,
+ * this function is faster than the generic ipc_call_sync_slow() because
+ * the payload is passed directly in registers.
+ *
+ * @param phoneid Phone handle for the call.
+ * @param method  Requested method.
+ * @param arg1    Service-defined payload argument.
+ * @param arg2    Service-defined payload argument.
+ * @param arg3    Service-defined payload argument.
+ * @param result1 If non-NULL, the return ARG1 will be stored there.
+ * @param result2 If non-NULL, the return ARG2 will be stored there.
+ * @param result3 If non-NULL, the return ARG3 will be stored there.
+ * @param result4 If non-NULL, the return ARG4 will be stored there.
+ * @param result5 If non-NULL, the return ARG5 will be stored there.
+ *
+ * @return Negative values representing IPC errors.
+ * @return Otherwise the RETVAL of the answer.
+ *
+ */
+int ipc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t *result1, sysarg_t *result2,
+    sysarg_t *result3, sysarg_t *result4, sysarg_t *result5)
 {
 	ipc_call_t resdata;
-	int callres;
-	
-	callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
+	int callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
 	    arg2, arg3, (sysarg_t) &resdata);
 	if (callres)
 		return callres;
+	
 	if (result1)
 		*result1 = IPC_GET_ARG1(resdata);
@@ -125,9 +123,9 @@
 	if (result5)
 		*result5 = IPC_GET_ARG5(resdata);
-
+	
 	return IPC_GET_RETVAL(resdata);
 }
 
-/** Make a synchronous call transmitting 5 arguments of payload.
+/** Synchronous call transmitting 5 arguments of payload.
  *
  * @param phoneid Phone handle for the call.
@@ -144,12 +142,12 @@
  * @param result5 If non-NULL, storage for the fifth return argument.
  *
- * @return Negative value means IPC error.
- *         Otherwise the RETVAL of the answer.
- *
- */
-int
-ipc_call_sync_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *result1,
-    sysarg_t *result2, sysarg_t *result3, sysarg_t *result4, sysarg_t *result5)
+ * @return Negative values representing IPC errors.
+ * @return Otherwise the RETVAL of the answer.
+ *
+ */
+int ipc_call_sync_slow(int phoneid, sysarg_t imethod, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
+    sysarg_t *result1, sysarg_t *result2, sysarg_t *result3, sysarg_t *result4,
+    sysarg_t *result5)
 {
 	ipc_call_t data;
@@ -181,5 +179,5 @@
 }
 
-/** Syscall to send asynchronous message.
+/** Send asynchronous message via syscall.
  *
  * @param phoneid Phone handle for the call.
@@ -189,66 +187,72 @@
  *
  */
-static ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data)
+static ipc_callid_t ipc_call_async_internal(int phoneid, ipc_call_t *data)
 {
 	return __SYSCALL2(SYS_IPC_CALL_ASYNC_SLOW, phoneid, (sysarg_t) data);
 }
 
-/** Prolog to ipc_call_async_*() functions.
- *
- * @param private	Argument for the answer/error callback.
- * @param callback	Answer/error callback.
- *
- * @return		New, partially initialized async_call structure or NULL.
+/** Prolog for ipc_call_async_*() functions.
+ *
+ * @param private  Argument for the answer/error callback.
+ * @param callback Answer/error callback.
+ *
+ * @return New, partially initialized async_call structure or NULL.
+ *
  */
 static inline async_call_t *ipc_prepare_async(void *private,
     ipc_async_callback_t callback)
 {
-	async_call_t *call;
-
-	call = malloc(sizeof(*call));
+	async_call_t *call =
+	    (async_call_t *) malloc(sizeof(async_call_t));
 	if (!call) {
 		if (callback)
 			callback(private, ENOMEM, NULL);
+		
 		return NULL;
 	}
+	
 	call->callback = callback;
 	call->private = private;
-
+	
 	return call;
 }
 
-/** Epilogue of ipc_call_async_*() functions.
- *
- * @param callid	Value returned by the SYS_IPC_CALL_ASYNC_* syscall.
- * @param phoneid	Phone handle through which the call was made.
- * @param call		async_call structure returned by ipc_prepare_async().
- * @param can_preempt	If non-zero, the current fibril can be preempted in this
- *			call.
+/** Epilog for ipc_call_async_*() functions.
+ *
+ * @param callid      Value returned by the SYS_IPC_CALL_ASYNC_* syscall.
+ * @param phoneid     Phone handle through which the call was made.
+ * @param call        Structure returned by ipc_prepare_async().
+ * @param can_preempt If true, the current fibril can be preempted
+ *                    in this call.
+ *
  */
 static inline void ipc_finish_async(ipc_callid_t callid, int phoneid,
-    async_call_t *call, int can_preempt)
-{
-	if (!call) { /* Nothing to do regardless if failed or not */
+    async_call_t *call, bool can_preempt)
+{
+	if (!call) {
+		/* Nothing to do regardless if failed or not */
 		futex_up(&ipc_futex);
 		return;
 	}
-
+	
 	if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
 		futex_up(&ipc_futex);
+		
 		/* Call asynchronous handler with error code */
 		if (call->callback)
 			call->callback(call->private, ENOENT, NULL);
+		
 		free(call);
 		return;
 	}
-
+	
 	if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
 		futex_up(&ipc_futex);
-
+		
 		call->u.msg.phoneid = phoneid;
 		
 		futex_down(&async_futex);
 		list_append(&call->list, &queued_calls);
-
+		
 		if (can_preempt) {
 			call->fid = fibril_get_id();
@@ -259,14 +263,16 @@
 			futex_up(&async_futex);
 		}
+		
 		return;
 	}
+	
 	call->u.callid = callid;
+	
 	/* Add call to the list of dispatched calls */
 	list_append(&call->list, &dispatched_calls);
 	futex_up(&ipc_futex);
-	
-}
-
-/** Make a fast asynchronous call.
+}
+
+/** Fast asynchronous call.
  *
  * This function can only handle four arguments of payload. It is, however,
@@ -274,7 +280,8 @@
  *
  * Note that this function is a void function.
- * During normal opertation, answering this call will trigger the callback.
- * In case of fatal error, call the callback handler with the proper error code.
- * If the call cannot be temporarily made, queue it.
+ *
+ * During normal operation, answering this call will trigger the callback.
+ * In case of fatal error, the callback handler is called with the proper
+ * error code. If the call cannot be temporarily made, it is queued.
  *
  * @param phoneid     Phone handle for the call.
@@ -286,5 +293,5 @@
  * @param private     Argument to be passed to the answer/error callback.
  * @param callback    Answer or error callback.
- * @param can_preempt If non-zero, the current fibril will be preempted in
+ * @param can_preempt If true, the current fibril will be preempted in
  *                    case the kernel temporarily refuses to accept more
  *                    asynchronous calls.
@@ -293,5 +300,5 @@
 void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private,
-    ipc_async_callback_t callback, int can_preempt)
+    ipc_async_callback_t callback, bool can_preempt)
 {
 	async_call_t *call = NULL;
@@ -304,7 +311,8 @@
 	
 	/*
-	 * We need to make sure that we get callid before another thread
-	 * accesses the queue again.
+	 * We need to make sure that we get callid
+	 * before another thread accesses the queue again.
 	 */
+	
 	futex_down(&ipc_futex);
 	ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid,
@@ -317,4 +325,5 @@
 				return;
 		}
+		
 		IPC_SET_IMETHOD(call->u.msg.data, imethod);
 		IPC_SET_ARG1(call->u.msg.data, arg1);
@@ -322,19 +331,23 @@
 		IPC_SET_ARG3(call->u.msg.data, arg3);
 		IPC_SET_ARG4(call->u.msg.data, arg4);
+		
 		/*
 		 * To achieve deterministic behavior, we always zero out the
 		 * arguments that are beyond the limits of the fast version.
 		 */
+		
 		IPC_SET_ARG5(call->u.msg.data, 0);
 	}
+	
 	ipc_finish_async(callid, phoneid, call, can_preempt);
 }
 
-/** Make an asynchronous call transmitting the entire payload.
+/** Asynchronous call transmitting the entire payload.
  *
  * Note that this function is a void function.
- * During normal opertation, answering this call will trigger the callback.
- * In case of fatal error, call the callback handler with the proper error code.
- * If the call cannot be temporarily made, queue it.
+ *
+ * During normal operation, answering this call will trigger the callback.
+ * In case of fatal error, the callback handler is called with the proper
+ * error code. If the call cannot be temporarily made, it is queued.
  *
  * @param phoneid     Phone handle for the call.
@@ -347,5 +360,5 @@
  * @param private     Argument to be passed to the answer/error callback.
  * @param callback    Answer or error callback.
- * @param can_preempt If non-zero, the current fibril will be preempted in
+ * @param can_preempt If true, the current fibril will be preempted in
  *                    case the kernel temporarily refuses to accept more
  *                    asynchronous calls.
@@ -354,13 +367,10 @@
 void ipc_call_async_slow(int phoneid, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, void *private,
-    ipc_async_callback_t callback, int can_preempt)
-{
-	async_call_t *call;
-	ipc_callid_t callid;
-
-	call = ipc_prepare_async(private, callback);
+    ipc_async_callback_t callback, bool can_preempt)
+{
+	async_call_t *call = ipc_prepare_async(private, callback);
 	if (!call)
 		return;
-
+	
 	IPC_SET_IMETHOD(call->u.msg.data, imethod);
 	IPC_SET_ARG1(call->u.msg.data, arg1);
@@ -369,28 +379,32 @@
 	IPC_SET_ARG4(call->u.msg.data, arg4);
 	IPC_SET_ARG5(call->u.msg.data, arg5);
+	
 	/*
-	 * We need to make sure that we get callid before another thread
-	 * accesses the queue again.
+	 * We need to make sure that we get callid
+	 * before another threadaccesses the queue again.
 	 */
+	
 	futex_down(&ipc_futex);
-	callid = _ipc_call_async(phoneid, &call->u.msg.data);
-
+	ipc_callid_t callid =
+	    ipc_call_async_internal(phoneid, &call->u.msg.data);
+	
 	ipc_finish_async(callid, phoneid, call, can_preempt);
 }
 
-
-/** Answer a received call - fast version.
+/** Answer received call (fast version).
  *
  * The fast answer makes use of passing retval and first four arguments in
  * registers. If you need to return more, use the ipc_answer_slow() instead.
  *
- * @param callid	Hash of the call being answered.
- * @param retval	Return value.
- * @param arg1		First return argument.
- * @param arg2		Second return argument.
- * @param arg3		Third return argument.
- * @param arg4		Fourth return argument.
- *
- * @return		Zero on success or a value from @ref errno.h on failure.
+ * @param callid Hash of the call being answered.
+ * @param retval Return value.
+ * @param arg1   First return argument.
+ * @param arg2   Second return argument.
+ * @param arg3   Third return argument.
+ * @param arg4   Fourth return argument.
+ *
+ * @return Zero on success.
+ * @return Value from @ref errno.h on failure.
+ *
  */
 sysarg_t ipc_answer_fast(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
@@ -401,15 +415,17 @@
 }
 
-/** Answer a received call - slow full version.
- *
- * @param callid	Hash of the call being answered.
- * @param retval	Return value.
- * @param arg1		First return argument.
- * @param arg2		Second return argument.
- * @param arg3		Third return argument.
- * @param arg4		Fourth return argument.
- * @param arg5		Fifth return argument.
- *
- * @return		Zero on success or a value from @ref errno.h on failure.
+/** Answer received call (entire payload).
+ *
+ * @param callid Hash of the call being answered.
+ * @param retval Return value.
+ * @param arg1   First return argument.
+ * @param arg2   Second return argument.
+ * @param arg3   Third return argument.
+ * @param arg4   Fourth return argument.
+ * @param arg5   Fifth return argument.
+ *
+ * @return Zero on success.
+ * @return Value from @ref errno.h on failure.
+ *
  */
 sysarg_t ipc_answer_slow(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
@@ -417,5 +433,5 @@
 {
 	ipc_call_t data;
-
+	
 	IPC_SET_RETVAL(data, retval);
 	IPC_SET_ARG1(data, arg1);
@@ -424,30 +440,33 @@
 	IPC_SET_ARG4(data, arg4);
 	IPC_SET_ARG5(data, arg5);
-
+	
 	return __SYSCALL2(SYS_IPC_ANSWER_SLOW, callid, (sysarg_t) &data);
 }
 
-
-/** Try to dispatch queued calls from the async queue. */
-static void try_dispatch_queued_calls(void)
-{
-	async_call_t *call;
-	ipc_callid_t callid;
-
+/** Try to dispatch queued calls from the async queue.
+ *
+ */
+static void dispatch_queued_calls(void)
+{
 	/** @todo
-	 * Integrate intelligently ipc_futex, so that it is locked during
-	 * ipc_call_async_*(), until it is added to dispatched_calls.
+	 * Integrate intelligently ipc_futex so that it is locked during
+	 * ipc_call_async_*() until it is added to dispatched_calls.
 	 */
+	
 	futex_down(&async_futex);
+	
 	while (!list_empty(&queued_calls)) {
-		call = list_get_instance(queued_calls.next, async_call_t, list);
-		callid = _ipc_call_async(call->u.msg.phoneid,
-		    &call->u.msg.data);
-		if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
+		async_call_t *call =
+		    list_get_instance(queued_calls.next, async_call_t, list);
+		ipc_callid_t callid =
+		    ipc_call_async_internal(call->u.msg.phoneid, &call->u.msg.data);
+		
+		if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY)
 			break;
-		}
+		
 		list_remove(&call->list);
-
+		
 		futex_up(&async_futex);
+		
 		if (call->fid)
 			fibril_add_ready(call->fid);
@@ -456,94 +475,114 @@
 			if (call->callback)
 				call->callback(call->private, ENOENT, NULL);
+			
 			free(call);
 		} else {
 			call->u.callid = callid;
+			
 			futex_down(&ipc_futex);
 			list_append(&call->list, &dispatched_calls);
 			futex_up(&ipc_futex);
 		}
+		
 		futex_down(&async_futex);
 	}
+	
 	futex_up(&async_futex);
 }
 
-/** Handle a received answer.
+/** Handle received answer.
  *
  * Find the hash of the answer and call the answer callback.
  *
- * @todo Make it use hash table.
- *
- * @param callid	Hash of the received answer.
- *			The answer has the same hash as the request OR'ed with
- *			the IPC_CALLID_ANSWERED bit.
- * @param data		Call data of the answer.
+ * The answer has the same hash as the request OR'ed with
+ * the IPC_CALLID_ANSWERED bit.
+ *
+ * @todo Use hash table.
+ *
+ * @param callid Hash of the received answer.
+ * @param data   Call data of the answer.
+ *
  */
 static void handle_answer(ipc_callid_t callid, ipc_call_t *data)
 {
+	callid &= ~IPC_CALLID_ANSWERED;
+	
+	futex_down(&ipc_futex);
+	
 	link_t *item;
-	async_call_t *call;
-
-	callid &= ~IPC_CALLID_ANSWERED;
-	
-	futex_down(&ipc_futex);
 	for (item = dispatched_calls.next; item != &dispatched_calls;
 	    item = item->next) {
-		call = list_get_instance(item, async_call_t, list);
+		async_call_t *call =
+		    list_get_instance(item, async_call_t, list);
+		
 		if (call->u.callid == callid) {
 			list_remove(&call->list);
+			
 			futex_up(&ipc_futex);
+			
 			if (call->callback)
-				call->callback(call->private, 
+				call->callback(call->private,
 				    IPC_GET_RETVAL(*data), data);
+			
 			free(call);
 			return;
 		}
 	}
+	
 	futex_up(&ipc_futex);
 }
 
-
-/** Wait for a first call to come.
- *
- * @param call		Storage where the incoming call data will be stored.
- * @param usec		Timeout in microseconds
- * @param flags		Flags passed to SYS_IPC_WAIT (blocking, nonblocking).
- *
- * @return		Hash of the call. Note that certain bits have special
- *			meaning. IPC_CALLID_ANSWERED will be set in an answer
- *			and IPC_CALLID_NOTIFICATION is used for notifications.
- *			
- */
-ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags)
-{
-	ipc_callid_t callid;
-
-	callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
+/** Wait for first IPC call to come.
+ *
+ * @param call  Incoming call storage.
+ * @param usec  Timeout in microseconds
+ * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking).
+ *
+ * @return Hash of the call. Note that certain bits have special
+ *         meaning: IPC_CALLID_ANSWERED is set in an answer
+ *         and IPC_CALLID_NOTIFICATION is used for notifications.
+ *
+ */
+ipc_callid_t ipc_wait_cycle(ipc_call_t *call, sysarg_t usec,
+    unsigned int flags)
+{
+	ipc_callid_t callid =
+	    __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
+	
 	/* Handle received answers */
 	if (callid & IPC_CALLID_ANSWERED) {
 		handle_answer(callid, call);
-		try_dispatch_queued_calls();
+		dispatch_queued_calls();
 	}
-
+	
 	return callid;
 }
 
-/** Wait some time for an IPC call.
- *
- * The call will return after an answer is received.
- *
- * @param call		Storage where the incoming call data will be stored.
- * @param usec		Timeout in microseconds.
- *
- * @return		Hash of the answer.
- */
-ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec)
+/** Interrupt one thread of this task from waiting for IPC.
+ *
+ */
+void ipc_poke(void)
+{
+	__SYSCALL0(SYS_IPC_POKE);
+}
+
+/** Wait for first IPC call to come.
+ *
+ * Only requests are returned, answers are processed internally.
+ *
+ * @param call Incoming call storage.
+ * @param usec Timeout in microseconds
+ *
+ * @return Hash of the call.
+ *
+ */
+ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, sysarg_t usec)
 {
 	ipc_callid_t callid;
-
+	
 	do {
 		callid = ipc_wait_cycle(call, usec, SYNCH_FLAGS_NONE);
 	} while (callid & IPC_CALLID_ANSWERED);
-
+	
 	return callid;
 }
@@ -551,87 +590,90 @@
 /** Check if there is an IPC call waiting to be picked up.
  *
- * @param call		Storage where the incoming call will be stored.
- * @return		Hash of the answer.
+ * Only requests are returned, answers are processed internally.
+ *
+ * @param call Incoming call storage.
+ *
+ * @return Hash of the call.
+ *
  */
 ipc_callid_t ipc_trywait_for_call(ipc_call_t *call)
 {
 	ipc_callid_t callid;
-
+	
 	do {
 		callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT,
 		    SYNCH_FLAGS_NON_BLOCKING);
 	} while (callid & IPC_CALLID_ANSWERED);
-
+	
 	return callid;
 }
 
-/** Interrupt one thread of this task from waiting for IPC. */
-void ipc_poke(void)
-{
-	__SYSCALL0(SYS_IPC_POKE);
-}
-
-/** Ask destination to do a callback connection.
- *
- * @param phoneid	Phone handle used for contacting the other side.
- * @param arg1		Service-defined argument.
- * @param arg2		Service-defined argument.
- * @param arg3		Service-defined argument.
- * @param phonehash	Storage where the library will store an opaque
- *			identifier of the phone that will be used for incoming
- *			calls. This identifier can be used for connection
- *			tracking.
- *
- * @return		Zero on success or a negative error code.
- */
-int ipc_connect_to_me(int phoneid, int arg1, int arg2, int arg3, 
-    sysarg_t *phonehash)
+/** Request callback connection.
+ *
+ * The @a taskhash and @a phonehash identifiers returned
+ * by the kernel can be used for connection tracking.
+ *
+ * @param phoneid   Phone handle used for contacting the other side.
+ * @param arg1      User defined argument.
+ * @param arg2      User defined argument.
+ * @param arg3      User defined argument.
+ * @param taskhash  Opaque identifier of the client task.
+ * @param phonehash Opaque identifier of the phone that will
+ *                  be used for incoming calls.
+ *
+ * @return Zero on success or a negative error code.
+ *
+ */
+int ipc_connect_to_me(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
+    sysarg_t *taskhash, sysarg_t *phonehash)
 {
 	return ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2,
-	    arg3, NULL, NULL, NULL, NULL, phonehash);
-}
-
-/** Ask through phone for a new connection to some service.
- *
- * @param phoneid	Phone handle used for contacting the other side.
- * @param arg1		User defined argument.
- * @param arg2		User defined argument.
- * @param arg3		User defined argument.
- *
- * @return		New phone handle on success or a negative error code.
- */
-int ipc_connect_me_to(int phoneid, int arg1, int arg2, int arg3)
+	    arg3, NULL, NULL, NULL, taskhash, phonehash);
+}
+
+/** Request new connection.
+ *
+ * @param phoneid Phone handle used for contacting the other side.
+ * @param arg1    User defined argument.
+ * @param arg2    User defined argument.
+ * @param arg3    User defined argument.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int ipc_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
 {
 	sysarg_t newphid;
-	int res;
-
-	res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
+	int res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
 	    NULL, NULL, NULL, NULL, &newphid);
 	if (res)
 		return res;
+	
 	return newphid;
 }
 
-/** Ask through phone for a new connection to some service.
+/** Request new connection (blocking)
  *
  * If the connection is not available at the moment, the
- * call will block.
- *
- * @param phoneid	Phone handle used for contacting the other side.
- * @param arg1		User defined argument.
- * @param arg2		User defined argument.
- * @param arg3		User defined argument.
- *
- * @return		New phone handle on success or a negative error code.
- */
-int ipc_connect_me_to_blocking(int phoneid, int arg1, int arg2, int arg3)
+ * call should block. This has to be, however, implemented
+ * on the server side.
+ *
+ * @param phoneid Phone handle used for contacting the other side.
+ * @param arg1    User defined argument.
+ * @param arg2    User defined argument.
+ * @param arg3    User defined argument.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int ipc_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3)
 {
 	sysarg_t newphid;
-	int res;
-
-	res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
+	int res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
 	    IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
 	if (res)
 		return res;
+	
 	return newphid;
 }
@@ -639,7 +681,8 @@
 /** Hang up a phone.
  *
- * @param phoneid	Handle of the phone to be hung up.
- *
- * @return		Zero on success or a negative error code.
+ * @param phoneid Handle of the phone to be hung up.
+ *
+ * @return Zero on success or a negative error code.
+ *
  */
 int ipc_hangup(int phoneid)
@@ -648,32 +691,10 @@
 }
 
-/** Register IRQ notification.
- *
- * @param inr		IRQ number.
- * @param devno		Device number of the device generating inr.
- * @param method	Use this method for notifying me.
- * @param ucode		Top-half pseudocode handler.
- *
- * @return		Value returned by the kernel.
- */
-int ipc_register_irq(int inr, int devno, int method, irq_code_t *ucode)
-{
-	return __SYSCALL4(SYS_IPC_REGISTER_IRQ, inr, devno, method,
-	    (sysarg_t) ucode);
-}
-
-/** Unregister IRQ notification.
- *
- * @param inr		IRQ number.
- * @param devno		Device number of the device generating inr.
- *
- * @return		Value returned by the kernel.
- */
-int ipc_unregister_irq(int inr, int devno)
-{
-	return __SYSCALL2(SYS_IPC_UNREGISTER_IRQ, inr, devno);
-}
-
 /** Forward a received call to another destination.
+ *
+ * For non-system methods, the old method, arg1 and arg2 are rewritten
+ * by the new values. For system methods, the new method, arg1 and arg2
+ * are written to the old arg1, arg2 and arg3, respectivelly. Calls with
+ * immutable methods are forwarded verbatim.
  *
  * @param callid  Hash of the call to forward.
@@ -686,11 +707,7 @@
  * @return Zero on success or an error code.
  *
- * For non-system methods, the old method, arg1 and arg2 are rewritten by the
- * new values. For system methods, the new method, arg1 and arg2 are written 
- * to the old arg1, arg2 and arg3, respectivelly. Calls with immutable 
- * methods are forwarded verbatim.
- */
-int ipc_forward_fast(ipc_callid_t callid, int phoneid, int imethod,
-    sysarg_t arg1, sysarg_t arg2, int mode)
+ */
+int ipc_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
+    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
 {
 	return __SYSCALL6(SYS_IPC_FORWARD_FAST, callid, phoneid, imethod, arg1,
@@ -698,8 +715,7 @@
 }
 
-
-int ipc_forward_slow(ipc_callid_t callid, int phoneid, int imethod,
+int ipc_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
     sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
-    int mode)
+    unsigned int mode)
 {
 	ipc_call_t data;
@@ -712,20 +728,21 @@
 	IPC_SET_ARG5(data, arg5);
 	
-	return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, mode);
-}
-
-/** Wrapper for making IPC_M_SHARE_IN calls.
- *
- * @param phoneid	Phone that will be used to contact the receiving side.
- * @param dst		Destination address space area base.
- * @param size		Size of the destination address space area.
- * @param arg		User defined argument.
- * @param flags		Storage where the received flags will be stored. Can be
- *			NULL.
- *
- * @return		Zero on success or a negative error code from errno.h.
+	return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data,
+	    mode);
+}
+
+/** Wrapper for IPC_M_SHARE_IN calls.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst     Destination address space area base.
+ * @param size    Size of the destination address space area.
+ * @param arg     User defined argument.
+ * @param flags   Storage for received flags. Can be NULL.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
  */
 int ipc_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
-    int *flags)
+    unsigned int *flags)
 {
 	sysarg_t tmp_flags = 0;
@@ -734,5 +751,5 @@
 	
 	if (flags)
-		*flags = tmp_flags;
+		*flags = (unsigned int) tmp_flags;
 	
 	return res;
@@ -741,27 +758,30 @@
 /** Wrapper for answering the IPC_M_SHARE_IN calls.
  *
- * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
- *
- * @param callid	Hash of the IPC_M_DATA_READ call to answer.
- * @param src		Source address space base.
- * @param flags		Flags to be used for sharing. Bits can be only cleared.
- *
- * @return		Zero on success or a value from @ref errno.h on failure.
- */
-int ipc_share_in_finalize(ipc_callid_t callid, void *src, int flags)
+ * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
+ * calls so that the user doesn't have to remember the meaning of each
+ * IPC argument.
+ *
+ * @param callid Hash of the IPC_M_DATA_READ call to answer.
+ * @param src    Source address space base.
+ * @param flags Flags to be used for sharing. Bits can be only cleared.
+ *
+ * @return Zero on success or a value from @ref errno.h on failure.
+ *
+ */
+int ipc_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
 {
 	return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) flags);
 }
 
-/** Wrapper for making IPC_M_SHARE_OUT calls.
- *
- * @param phoneid	Phone that will be used to contact the receiving side.
- * @param src		Source address space area base address.
- * @param flags		Flags to be used for sharing. Bits can be only cleared.
- *
- * @return		Zero on success or a negative error code from errno.h.
- */
-int ipc_share_out_start(int phoneid, void *src, int flags)
+/** Wrapper for IPC_M_SHARE_OUT calls.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param src     Source address space area base address.
+ * @param flags   Flags to be used for sharing. Bits can be only cleared.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
+ */
+int ipc_share_out_start(int phoneid, void *src, unsigned int flags)
 {
 	return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
@@ -771,11 +791,13 @@
 /** Wrapper for answering the IPC_M_SHARE_OUT calls.
  *
- * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
- *
- * @param callid	Hash of the IPC_M_DATA_WRITE call to answer.
- * @param dst		Destination address space area base address.	
- *
- * @return		Zero on success or a value from @ref errno.h on failure.
+ * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT
+ * calls so that the user doesn't have to remember the meaning of each
+ * IPC argument.
+ *
+ * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
+ * @param dst    Destination address space area base address.
+ *
+ * @return Zero on success or a value from @ref errno.h on failure.
+ *
  */
 int ipc_share_out_finalize(ipc_callid_t callid, void *dst)
@@ -784,12 +806,12 @@
 }
 
-
-/** Wrapper for making IPC_M_DATA_READ calls.
- *
- * @param phoneid	Phone that will be used to contact the receiving side.
- * @param dst		Address of the beginning of the destination buffer.
- * @param size		Size of the destination buffer.
- *
- * @return		Zero on success or a negative error code from errno.h.
+/** Wrapper for IPC_M_DATA_READ calls.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst     Address of the beginning of the destination buffer.
+ * @param size    Size of the destination buffer.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
  */
 int ipc_data_read_start(int phoneid, void *dst, size_t size)
@@ -801,13 +823,15 @@
 /** Wrapper for answering the IPC_M_DATA_READ calls.
  *
- * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
- *
- * @param callid	Hash of the IPC_M_DATA_READ call to answer.
- * @param src		Source address for the IPC_M_DATA_READ call.
- * @param size		Size for the IPC_M_DATA_READ call. Can be smaller than
- *			the maximum size announced by the sender.
- *
- * @return		Zero on success or a value from @ref errno.h on failure.
+ * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
+ * calls so that the user doesn't have to remember the meaning of each
+ * IPC argument.
+ *
+ * @param callid Hash of the IPC_M_DATA_READ call to answer.
+ * @param src    Source address for the IPC_M_DATA_READ call.
+ * @param size   Size for the IPC_M_DATA_READ call. Can be smaller than
+ *               the maximum size announced by the sender.
+ *
+ * @return Zero on success or a value from @ref errno.h on failure.
+ *
  */
 int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
@@ -816,11 +840,12 @@
 }
 
-/** Wrapper for making IPC_M_DATA_WRITE calls.
- *
- * @param phoneid	Phone that will be used to contact the receiving side.
- * @param src		Address of the beginning of the source buffer.
- * @param size		Size of the source buffer.
- *
- * @return		Zero on success or a negative error code from errno.h.
+/** Wrapper for IPC_M_DATA_WRITE calls.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param src     Address of the beginning of the source buffer.
+ * @param size    Size of the source buffer.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
  */
 int ipc_data_write_start(int phoneid, const void *src, size_t size)
@@ -832,12 +857,14 @@
 /** Wrapper for answering the IPC_M_DATA_WRITE calls.
  *
- * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls
- * so that the user doesn't have to remember the meaning of each IPC argument.
- *
- * @param callid	Hash of the IPC_M_DATA_WRITE call to answer.
- * @param dst		Final destination address for the IPC_M_DATA_WRITE call.
- * @param size		Final size for the IPC_M_DATA_WRITE call.
- *
- * @return		Zero on success or a value from @ref errno.h on failure.
+ * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE
+ * calls so that the user doesn't have to remember the meaning of each
+ * IPC argument.
+ *
+ * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
+ * @param dst    Final destination address for the IPC_M_DATA_WRITE call.
+ * @param size   Final size for the IPC_M_DATA_WRITE call.
+ *
+ * @return Zero on success or a value from @ref errno.h on failure.
+ *
  */
 int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
Index: uspace/lib/c/generic/ipc/ns.c
===================================================================
--- uspace/lib/c/generic/ipc/ns.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/c/generic/ipc/ns.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <ipc/ns.h>
+
+int service_register(sysarg_t service)
+{
+	return async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
+}
+
+int service_connect(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
+{
+	return async_connect_me_to(PHONE_NS, service, arg2, arg3);
+}
+
+int service_connect_blocking(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
+{
+	return async_connect_me_to_blocking(PHONE_NS, service, arg2, arg3);
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/libc.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -42,28 +42,28 @@
 
 #include <libc.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <tls.h>
-#include <thread.h>
 #include <fibril.h>
-#include <ipc/ipc.h>
-#include <async.h>
-#include <as.h>
+#include <task.h>
 #include <loader/pcb.h>
+#include "private/libc.h"
+#include "private/async.h"
+#include "private/async_sess.h"
+#include "private/malloc.h"
+#include "private/io.h"
 
-extern int main(int argc, char *argv[]);
-
-void _exit(int status)
-{
-	thread_exit(status);
-}
+static bool env_setup = false;
 
 void __main(void *pcb_ptr)
 {
 	/* Initialize user task run-time environment */
-	__heap_init();
+	__malloc_init();
 	__async_init();
+	__async_sess_init();
+	
 	fibril_t *fibril = fibril_setup();
+	if (fibril == NULL)
+		abort();
+	
 	__tcb_set(fibril->tcb);
 	
@@ -71,9 +71,14 @@
 	__pcb = (pcb_t *) pcb_ptr;
 	
+	/* The basic run-time environment is setup */
+	env_setup = true;
+	
 	int argc;
 	char **argv;
 	
-	/* Get command line arguments and initialize
-	   standard input and output */
+	/*
+	 * Get command line arguments and initialize
+	 * standard input and output
+	 */
 	if (__pcb == NULL) {
 		argc = 0;
@@ -87,14 +92,32 @@
 	}
 	
-	/* Run main() and set task return value
-	   according the result */
-	(void) task_retval(main(argc, argv));
+	/*
+	 * Run main() and set task return value
+	 * according the result
+	 */
+	int retval = main(argc, argv);
+	exit(retval);
 }
 
-void __exit(void)
+void exit(int status)
 {
-	__stdio_done();
-	fibril_teardown(__tcb_get()->fibril_data);
-	_exit(0);
+	if (env_setup) {
+		__stdio_done();
+		task_retval(status);
+		fibril_teardown(__tcb_get()->fibril_data);
+	}
+	
+	__SYSCALL1(SYS_TASK_EXIT, false);
+	
+	/* Unreachable */
+	while (1);
+}
+
+void abort(void)
+{
+	__SYSCALL1(SYS_TASK_EXIT, true);
+	
+	/* Unreachable */
+	while (1);
 }
 
Index: uspace/lib/c/generic/loader.c
===================================================================
--- uspace/lib/c/generic/loader.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/loader.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,7 +33,7 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/loader.h>
 #include <ipc/services.h>
+#include <ipc/ns.h>
 #include <libc.h>
 #include <task.h>
@@ -63,5 +63,5 @@
 loader_t *loader_connect(void)
 {
-	int phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
+	int phone_id = service_connect_blocking(SERVICE_LOAD, 0, 0);
 	if (phone_id < 0)
 		return NULL;
@@ -319,5 +319,5 @@
 		return rc;
 	
-	ipc_hangup(ldr->phone_id);
+	async_hangup(ldr->phone_id);
 	ldr->phone_id = 0;
 	return EOK;
@@ -337,5 +337,5 @@
 void loader_abort(loader_t *ldr)
 {
-	ipc_hangup(ldr->phone_id);
+	async_hangup(ldr->phone_id);
 	ldr->phone_id = 0;
 }
Index: uspace/lib/c/generic/malloc.c
===================================================================
--- uspace/lib/c/generic/malloc.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/malloc.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,34 +45,79 @@
 #include <futex.h>
 #include <adt/gcdlcm.h>
-
-/* Magic used in heap headers. */
-#define HEAP_BLOCK_HEAD_MAGIC  0xBEEF0101
-
-/* Magic used in heap footers. */
-#define HEAP_BLOCK_FOOT_MAGIC  0xBEEF0202
-
-/** Allocation alignment (this also covers the alignment of fields
-    in the heap header and footer) */
+#include "private/malloc.h"
+
+/** Magic used in heap headers. */
+#define HEAP_BLOCK_HEAD_MAGIC  UINT32_C(0xBEEF0101)
+
+/** Magic used in heap footers. */
+#define HEAP_BLOCK_FOOT_MAGIC  UINT32_C(0xBEEF0202)
+
+/** Magic used in heap descriptor. */
+#define HEAP_AREA_MAGIC  UINT32_C(0xBEEFCAFE)
+
+/** Allocation alignment.
+ *
+ * This also covers the alignment of fields
+ * in the heap header and footer.
+ *
+ */
 #define BASE_ALIGN  16
 
-/**
- * Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures
- */
-#define MAX_HEAP_SIZE  (sizeof(uintptr_t) << 28)
-
-/**
- *
- */
-#define STRUCT_OVERHEAD  (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
-
-/**
- * Calculate real size of a heap block (with header and footer)
+/** Overhead of each heap block. */
+#define STRUCT_OVERHEAD \
+	(sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
+
+/** Calculate real size of a heap block.
+ *
+ * Add header and footer size.
+ *
  */
 #define GROSS_SIZE(size)  ((size) + STRUCT_OVERHEAD)
 
-/**
- * Calculate net size of a heap block (without header and footer)
+/** Calculate net size of a heap block.
+ *
+ * Subtract header and footer size.
+ *
  */
 #define NET_SIZE(size)  ((size) - STRUCT_OVERHEAD)
+
+/** Get first block in heap area.
+ *
+ */
+#define AREA_FIRST_BLOCK(area) \
+	(ALIGN_UP(((uintptr_t) (area)) + sizeof(heap_area_t), BASE_ALIGN))
+
+/** Get footer in heap block.
+ *
+ */
+#define BLOCK_FOOT(head) \
+	((heap_block_foot_t *) \
+	    (((uintptr_t) head) + head->size - sizeof(heap_block_foot_t)))
+
+/** Heap area.
+ *
+ * The memory managed by the heap allocator is divided into
+ * multiple discontinuous heaps. Each heap is represented
+ * by a separate address space area which has this structure
+ * at its very beginning.
+ *
+ */
+typedef struct heap_area {
+	/** Start of the heap area (including this structure)
+	 *
+	 * Aligned on page boundary.
+	 *
+	 */
+	void *start;
+	
+	/** End of the heap area (aligned on page boundary) */
+	void *end;
+	
+	/** Next heap area */
+	struct heap_area *next;
+	
+	/** A magic value */
+	uint32_t magic;
+} heap_area_t;
 
 /** Header of a heap block
@@ -86,4 +131,7 @@
 	bool free;
 	
+	/** Heap area this block belongs to */
+	heap_area_t *area;
+	
 	/* A magic value to detect overwrite of heap header */
 	uint32_t magic;
@@ -101,25 +149,19 @@
 } heap_block_foot_t;
 
-/** Linker heap symbol */
-extern char _heap;
+/** First heap area */
+static heap_area_t *first_heap_area = NULL;
+
+/** Last heap area */
+static heap_area_t *last_heap_area = NULL;
+
+/** Next heap block to examine (next fit algorithm) */
+static heap_block_head_t *next = NULL;
 
 /** Futex for thread-safe heap manipulation */
 static futex_t malloc_futex = FUTEX_INITIALIZER;
 
-/** Address of heap start */
-static void *heap_start = 0;
-
-/** Address of heap end */
-static void *heap_end = 0;
-
-/** Maximum heap size */
-static size_t max_heap_size = (size_t) -1;
-
-/** Current number of pages of heap area */
-static size_t heap_pages = 0;
-
 /** Initialize a heap block
  *
- * Fills in the structures related to a heap block.
+ * Fill in the structures related to a heap block.
  * Should be called only inside the critical section.
  *
@@ -127,16 +169,18 @@
  * @param size Size of the block including the header and the footer.
  * @param free Indication of a free block.
- *
- */
-static void block_init(void *addr, size_t size, bool free)
+ * @param area Heap area the block belongs to.
+ *
+ */
+static void block_init(void *addr, size_t size, bool free, heap_area_t *area)
 {
 	/* Calculate the position of the header and the footer */
 	heap_block_head_t *head = (heap_block_head_t *) addr;
-	heap_block_foot_t *foot =
-	    (heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t));
 	
 	head->size = size;
 	head->free = free;
+	head->area = area;
 	head->magic = HEAP_BLOCK_HEAD_MAGIC;
+	
+	heap_block_foot_t *foot = BLOCK_FOOT(head);
 	
 	foot->size = size;
@@ -159,6 +203,5 @@
 	assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
 	
-	heap_block_foot_t *foot =
-	    (heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t));
+	heap_block_foot_t *foot = BLOCK_FOOT(head);
 	
 	assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
@@ -166,92 +209,143 @@
 }
 
-/** Increase the heap area size
- *
- * Should be called only inside the critical section.
- *
- * @param size Number of bytes to grow the heap by.
- *
- */
-static bool grow_heap(size_t size)
+/** Check a heap area structure
+ *
+ * @param addr Address of the heap area.
+ *
+ */
+static void area_check(void *addr)
+{
+	heap_area_t *area = (heap_area_t *) addr;
+	
+	assert(area->magic == HEAP_AREA_MAGIC);
+	assert(area->start < area->end);
+	assert(((uintptr_t) area->start % PAGE_SIZE) == 0);
+	assert(((uintptr_t) area->end % PAGE_SIZE) == 0);
+}
+
+/** Create new heap area
+ *
+ * @param start Preffered starting address of the new area.
+ * @param size  Size of the area.
+ *
+ */
+static bool area_create(size_t size)
+{
+	void *start = as_get_mappable_page(size);
+	if (start == NULL)
+		return false;
+	
+	/* Align the heap area on page boundary */
+	void *astart = (void *) ALIGN_UP((uintptr_t) start, PAGE_SIZE);
+	size_t asize = ALIGN_UP(size, PAGE_SIZE);
+	
+	astart = as_area_create(astart, asize, AS_AREA_WRITE | AS_AREA_READ);
+	if (astart == (void *) -1)
+		return false;
+	
+	heap_area_t *area = (heap_area_t *) astart;
+	
+	area->start = astart;
+	area->end = (void *)
+	    ALIGN_DOWN((uintptr_t) astart + asize, BASE_ALIGN);
+	area->next = NULL;
+	area->magic = HEAP_AREA_MAGIC;
+	
+	void *block = (void *) AREA_FIRST_BLOCK(area);
+	size_t bsize = (size_t) (area->end - block);
+	
+	block_init(block, bsize, true, area);
+	
+	if (last_heap_area == NULL) {
+		first_heap_area = area;
+		last_heap_area = area;
+	} else {
+		last_heap_area->next = area;
+		last_heap_area = area;
+	}
+	
+	return true;
+}
+
+/** Try to enlarge a heap area
+ *
+ * @param area Heap area to grow.
+ * @param size Gross size of item to allocate (bytes).
+ *
+ */
+static bool area_grow(heap_area_t *area, size_t size)
 {
 	if (size == 0)
+		return true;
+	
+	area_check(area);
+	
+	size_t asize = ALIGN_UP((size_t) (area->end - area->start) + size,
+	    PAGE_SIZE);
+	
+	/* New heap area size */
+	void *end = (void *)
+	    ALIGN_DOWN((uintptr_t) area->start + asize, BASE_ALIGN);
+	
+	/* Check for overflow */
+	if (end < area->start)
 		return false;
-
-	if ((heap_start + size < heap_start) || (heap_end + size < heap_end))
+	
+	/* Resize the address space area */
+	int ret = as_area_resize(area->start, asize, 0);
+	if (ret != EOK)
 		return false;
 	
-	size_t heap_size = (size_t) (heap_end - heap_start);
-	
-	if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size))
-		return false;
-	
-	size_t pages = (size - 1) / PAGE_SIZE + 1;
-	
-	if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0)
-	    == EOK) {
-		void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) +
-		    (heap_pages + pages) * PAGE_SIZE, BASE_ALIGN);
-		block_init(heap_end, end - heap_end, true);
-		heap_pages += pages;
-		heap_end = end;
+	/* Add new free block */
+	block_init(area->end, (size_t) (end - area->end), true, area);
+	
+	/* Update heap area parameters */
+	area->end = end;
+	
+	return true;
+}
+
+/** Try to enlarge any of the heap areas
+ *
+ * @param size Gross size of item to allocate (bytes).
+ *
+ */
+static bool heap_grow(size_t size)
+{
+	if (size == 0)
 		return true;
-	}
-	
-	return false;
-}
-
-/** Decrease the heap area
- *
- * Should be called only inside the critical section.
- *
- * @param size Number of bytes to shrink the heap by.
- *
- */
-static void shrink_heap(void)
-{
-	// TODO
+	
+	/* First try to enlarge some existing area */
+	heap_area_t *area;
+	for (area = first_heap_area; area != NULL; area = area->next) {
+		if (area_grow(area, size))
+			return true;
+	}
+	
+	/* Eventually try to create a new area */
+	return area_create(AREA_FIRST_BLOCK(size));
+}
+
+/** Try to shrink heap space
+ *
+ * In all cases the next pointer is reset.
+ *
+ */
+static void heap_shrink(void)
+{
+	next = NULL;
 }
 
 /** Initialize the heap allocator
  *
- * Find how much physical memory we have and create
- * the heap management structures that mark the whole
- * physical memory as a single free block.
- *
- */
-void __heap_init(void)
-{
-	futex_down(&malloc_futex);
-	
-	if (as_area_create((void *) &_heap, PAGE_SIZE,
-	    AS_AREA_WRITE | AS_AREA_READ)) {
-		heap_pages = 1;
-		heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN);
-		heap_end =
-		    (void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN);
-		
-		/* Make the entire area one large block. */
-		block_init(heap_start, heap_end - heap_start, true);
-	}
-	
-	futex_up(&malloc_futex);
-}
-
-/** Get maximum heap address
- *
- */
-uintptr_t get_max_heap_addr(void)
-{
-	futex_down(&malloc_futex);
-	
-	if (max_heap_size == (size_t) -1)
-		max_heap_size =
-		    max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE);
-	
-	uintptr_t max_heap_addr = (uintptr_t) heap_start + max_heap_size;
-	
-	futex_up(&malloc_futex);
-	
-	return max_heap_addr;
+ * Create initial heap memory area. This routine is
+ * only called from libc initialization, thus we do not
+ * take any locks.
+ *
+ */
+void __malloc_init(void)
+{
+	if (!area_create(PAGE_SIZE))
+		abort();
 }
 
@@ -275,6 +369,6 @@
 		/* Block big enough -> split. */
 		void *next = ((void *) cur) + size;
-		block_init(next, cur->size - size, true);
-		block_init(cur, size, false);
+		block_init(next, cur->size - size, true, cur->area);
+		block_init(cur, size, false, cur->area);
 	} else {
 		/* Block too small -> use as is. */
@@ -283,43 +377,53 @@
 }
 
-/** Allocate a memory block
+/** Allocate memory from heap area starting from given block
  *
  * Should be called only inside the critical section.
- *
- * @param size  The size of the block to allocate.
- * @param align Memory address alignment.
- *
- * @return the address of the block or NULL when not enough memory.
- *
- */
-static void *malloc_internal(const size_t size, const size_t align)
-{
-	if (align == 0)
-		return NULL;
-	
-	size_t falign = lcm(align, BASE_ALIGN);
-	size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
-	
-	bool grown = false;
-	void *result;
-	
-loop:
-	result = NULL;
-	heap_block_head_t *cur = (heap_block_head_t *) heap_start;
-	
-	while ((result == NULL) && ((void *) cur < heap_end)) {
+ * As a side effect this function also sets the current
+ * pointer on successful allocation.
+ *
+ * @param area        Heap area where to allocate from.
+ * @param first_block Starting heap block.
+ * @param final_block Heap block where to finish the search
+ *                    (may be NULL).
+ * @param real_size   Gross number of bytes to allocate.
+ * @param falign      Physical alignment of the block.
+ *
+ * @return Address of the allocated block or NULL on not enough memory.
+ *
+ */
+static void *malloc_area(heap_area_t *area, heap_block_head_t *first_block,
+    heap_block_head_t *final_block, size_t real_size, size_t falign)
+{
+	area_check((void *) area);
+	assert((void *) first_block >= (void *) AREA_FIRST_BLOCK(area));
+	assert((void *) first_block < area->end);
+	
+	heap_block_head_t *cur;
+	for (cur = first_block; (void *) cur < area->end;
+	    cur = (heap_block_head_t *) (((void *) cur) + cur->size)) {
 		block_check(cur);
+		
+		/* Finish searching on the final block */
+		if ((final_block != NULL) && (cur == final_block))
+			break;
 		
 		/* Try to find a block that is free and large enough. */
 		if ((cur->free) && (cur->size >= real_size)) {
-			/* We have found a suitable block.
-			   Check for alignment properties. */
-			void *addr = ((void *) cur) + sizeof(heap_block_head_t);
-			void *aligned = (void *) ALIGN_UP(addr, falign);
+			/*
+			 * We have found a suitable block.
+			 * Check for alignment properties.
+			 */
+			void *addr = (void *)
+			    ((uintptr_t) cur + sizeof(heap_block_head_t));
+			void *aligned = (void *)
+			    ALIGN_UP((uintptr_t) addr, falign);
 			
 			if (addr == aligned) {
 				/* Exact block start including alignment. */
 				split_mark(cur, real_size);
-				result = addr;
+				
+				next = cur;
+				return addr;
 			} else {
 				/* Block start has to be aligned */
@@ -327,15 +431,19 @@
 				
 				if (cur->size >= real_size + excess) {
-					/* The current block is large enough to fit
-					   data in including alignment */
-					if ((void *) cur > heap_start) {
-						/* There is a block before the current block.
-						   This previous block can be enlarged to compensate
-						   for the alignment excess */
-						heap_block_foot_t *prev_foot =
-						    ((void *) cur) - sizeof(heap_block_foot_t);
+					/*
+					 * The current block is large enough to fit
+					 * data in (including alignment).
+					 */
+					if ((void *) cur > (void *) AREA_FIRST_BLOCK(area)) {
+						/*
+						 * There is a block before the current block.
+						 * This previous block can be enlarged to
+						 * compensate for the alignment excess.
+						 */
+						heap_block_foot_t *prev_foot = (heap_block_foot_t *)
+						    ((void *) cur - sizeof(heap_block_foot_t));
 						
-						heap_block_head_t *prev_head =
-						    (heap_block_head_t *) (((void *) cur) - prev_foot->size);
+						heap_block_head_t *prev_head = (heap_block_head_t *)
+						    ((void *) cur - prev_foot->size);
 						
 						block_check(prev_head);
@@ -344,25 +452,38 @@
 						heap_block_head_t *next_head = ((void *) cur) + excess;
 						
-						if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) {
-							/* The previous block is not free and there is enough
-							   space to fill in a new free block between the previous
-							   and current block */
-							block_init(cur, excess, true);
+						if ((!prev_head->free) &&
+						    (excess >= STRUCT_OVERHEAD)) {
+							/*
+							 * The previous block is not free and there
+							 * is enough free space left to fill in
+							 * a new free block between the previous
+							 * and current block.
+							 */
+							block_init(cur, excess, true, area);
 						} else {
-							/* The previous block is free (thus there is no need to
-							   induce additional fragmentation to the heap) or the
-							   excess is small, thus just enlarge the previous block */
-							block_init(prev_head, prev_head->size + excess, prev_head->free);
+							/*
+							 * The previous block is free (thus there
+							 * is no need to induce additional
+							 * fragmentation to the heap) or the
+							 * excess is small. Therefore just enlarge
+							 * the previous block.
+							 */
+							block_init(prev_head, prev_head->size + excess,
+							    prev_head->free, area);
 						}
 						
-						block_init(next_head, reduced_size, true);
+						block_init(next_head, reduced_size, true, area);
 						split_mark(next_head, real_size);
-						result = aligned;
-						cur = next_head;
+						
+						next = next_head;
+						return aligned;
 					} else {
-						/* The current block is the first block on the heap.
-						   We have to make sure that the alignment excess
-						   is large enough to fit a new free block just
-						   before the current block */
+						/*
+						 * The current block is the first block
+						 * in the heap area. We have to make sure
+						 * that the alignment excess is large enough
+						 * to fit a new free block just before the
+						 * current block.
+						 */
 						while (excess < STRUCT_OVERHEAD) {
 							aligned += falign;
@@ -373,10 +494,14 @@
 						if (cur->size >= real_size + excess) {
 							size_t reduced_size = cur->size - excess;
-							cur = (heap_block_head_t *) (heap_start + excess);
+							cur = (heap_block_head_t *)
+							    (AREA_FIRST_BLOCK(area) + excess);
 							
-							block_init(heap_start, excess, true);
-							block_init(cur, reduced_size, true);
+							block_init((void *) AREA_FIRST_BLOCK(area), excess,
+							    true, area);
+							block_init(cur, reduced_size, true, area);
 							split_mark(cur, real_size);
-							result = aligned;
+							
+							next = cur;
+							return aligned;
 						}
 					}
@@ -384,17 +509,67 @@
 			}
 		}
-		
-		/* Advance to the next block. */
-		cur = (heap_block_head_t *) (((void *) cur) + cur->size);
-	}
-	
-	if ((result == NULL) && (!grown)) {
-		if (grow_heap(real_size)) {
-			grown = true;
+	}
+	
+	return NULL;
+}
+
+/** Allocate a memory block
+ *
+ * Should be called only inside the critical section.
+ *
+ * @param size  The size of the block to allocate.
+ * @param align Memory address alignment.
+ *
+ * @return Address of the allocated block or NULL on not enough memory.
+ *
+ */
+static void *malloc_internal(const size_t size, const size_t align)
+{
+	assert(first_heap_area != NULL);
+	
+	if (align == 0)
+		return NULL;
+	
+	size_t falign = lcm(align, BASE_ALIGN);
+	size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
+	
+	bool retry = false;
+	heap_block_head_t *split;
+	
+loop:
+	
+	/* Try the next fit approach */
+	split = next;
+	
+	if (split != NULL) {
+		void *addr = malloc_area(split->area, split, NULL, real_size,
+		    falign);
+		
+		if (addr != NULL)
+			return addr;
+	}
+	
+	/* Search the entire heap */
+	heap_area_t *area;
+	for (area = first_heap_area; area != NULL; area = area->next) {
+		heap_block_head_t *first = (heap_block_head_t *)
+		    AREA_FIRST_BLOCK(area);
+		
+		void *addr = malloc_area(area, first, split, real_size,
+		    falign);
+		
+		if (addr != NULL)
+			return addr;
+	}
+	
+	if (!retry) {
+		/* Try to grow the heap space */
+		if (heap_grow(real_size)) {
+			retry = true;
 			goto loop;
 		}
 	}
 	
-	return result;
+	return NULL;
 }
 
@@ -475,9 +650,12 @@
 	    (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
 	
-	assert((void *) head >= heap_start);
-	assert((void *) head < heap_end);
-	
 	block_check(head);
 	assert(!head->free);
+	
+	heap_area_t *area = head->area;
+	
+	area_check(area);
+	assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
+	assert((void *) head < area->end);
 	
 	void *ptr = NULL;
@@ -489,29 +667,34 @@
 		/* Shrink */
 		if (orig_size - real_size >= STRUCT_OVERHEAD) {
-			/* Split the original block to a full block
-			   and a trailing free block */
-			block_init((void *) head, real_size, false);
+			/*
+			 * Split the original block to a full block
+			 * and a trailing free block.
+			 */
+			block_init((void *) head, real_size, false, area);
 			block_init((void *) head + real_size,
-			    orig_size - real_size, true);
-			shrink_heap();
+			    orig_size - real_size, true, area);
+			heap_shrink();
 		}
 		
 		ptr = ((void *) head) + sizeof(heap_block_head_t);
 	} else {
-		/* Look at the next block. If it is free and the size is
-		   sufficient then merge the two. Otherwise just allocate
-		   a new block, copy the original data into it and
-		   free the original block. */
+		/*
+		 * Look at the next block. If it is free and the size is
+		 * sufficient then merge the two. Otherwise just allocate
+		 * a new block, copy the original data into it and
+		 * free the original block.
+		 */
 		heap_block_head_t *next_head =
 		    (heap_block_head_t *) (((void *) head) + head->size);
 		
-		if (((void *) next_head < heap_end) &&
+		if (((void *) next_head < area->end) &&
 		    (head->size + next_head->size >= real_size) &&
 		    (next_head->free)) {
 			block_check(next_head);
-			block_init(head, head->size + next_head->size, false);
+			block_init(head, head->size + next_head->size, false, area);
 			split_mark(head, real_size);
 			
 			ptr = ((void *) head) + sizeof(heap_block_head_t);
+			next = NULL;
 		} else
 			reloc = true;
@@ -544,9 +727,12 @@
 	    = (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
 	
-	assert((void *) head >= heap_start);
-	assert((void *) head < heap_end);
-	
 	block_check(head);
 	assert(!head->free);
+	
+	heap_area_t *area = head->area;
+	
+	area_check(area);
+	assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
+	assert((void *) head < area->end);
 	
 	/* Mark the block itself as free. */
@@ -557,12 +743,12 @@
 	    = (heap_block_head_t *) (((void *) head) + head->size);
 	
-	if ((void *) next_head < heap_end) {
+	if ((void *) next_head < area->end) {
 		block_check(next_head);
 		if (next_head->free)
-			block_init(head, head->size + next_head->size, true);
+			block_init(head, head->size + next_head->size, true, area);
 	}
 	
 	/* Look at the previous block. If it is free, merge the two. */
-	if ((void *) head > heap_start) {
+	if ((void *) head > (void *) AREA_FIRST_BLOCK(area)) {
 		heap_block_foot_t *prev_foot =
 		    (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
@@ -574,8 +760,9 @@
 		
 		if (prev_head->free)
-			block_init(prev_head, prev_head->size + head->size, true);
-	}
-	
-	shrink_heap();
+			block_init(prev_head, prev_head->size + head->size, true,
+			    area);
+	}
+	
+	heap_shrink();
 	
 	futex_up(&malloc_futex);
Index: uspace/lib/c/generic/net/icmp_api.c
===================================================================
--- uspace/lib/c/generic/net/icmp_api.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/net/icmp_api.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,11 +41,8 @@
 #include <net/modules.h>
 #include <net/ip_codes.h>
-
 #include <async.h>
 #include <sys/types.h>
 #include <sys/time.h>
 #include <errno.h>
-
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/icmp.h>
Index: uspace/lib/c/generic/net/icmp_common.c
===================================================================
--- uspace/lib/c/generic/net/icmp_common.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/net/icmp_common.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libc 
+/** @addtogroup libc
  *  @{
  */
@@ -38,28 +38,21 @@
 #include <net/modules.h>
 #include <net/icmp_common.h>
-
 #include <ipc/services.h>
 #include <ipc/icmp.h>
-
 #include <sys/time.h>
 #include <async.h>
 
-/** Connects to the ICMP module.
+/** Connect to the ICMP module.
  *
- * @param service	The ICMP module service. Ignored parameter.
- * @param[in] timeout	The connection timeout in microseconds. No timeout if
- *			set to zero.
- * @return		The ICMP module phone on success.
- * @return		ETIMEOUT if the connection timeouted.
+ * @param[in] timeout Connection timeout in microseconds, zero
+ *                    for no timeout.
+ *
+ * @return ICMP module phone on success.
+ * @return ETIMEOUT if the connection timeouted.
+ *
  */
-int icmp_connect_module(services_t service, suseconds_t timeout)
+int icmp_connect_module(suseconds_t timeout)
 {
-	int phone;
-
-	phone = connect_to_service_timeout(SERVICE_ICMP, timeout);
-	if (phone >= 0)
-		async_req_0_0(phone, NET_ICMP_INIT);
-
-	return phone;
+	return connect_to_service_timeout(SERVICE_ICMP, timeout);
 }
 
Index: uspace/lib/c/generic/net/modules.c
===================================================================
--- uspace/lib/c/generic/net/modules.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/net/modules.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -43,8 +43,5 @@
 #include <errno.h>
 #include <sys/time.h>
-
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <net/modules.h>
 
@@ -67,21 +64,21 @@
 		switch (count) {
 		case 0:
-			ipc_answer_0(callid, (sysarg_t) result);
+			async_answer_0(callid, (sysarg_t) result);
 			break;
 		case 1:
-			ipc_answer_1(callid, (sysarg_t) result,
+			async_answer_1(callid, (sysarg_t) result,
 			    IPC_GET_ARG1(*answer));
 			break;
 		case 2:
-			ipc_answer_2(callid, (sysarg_t) result,
+			async_answer_2(callid, (sysarg_t) result,
 			    IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer));
 			break;
 		case 3:
-			ipc_answer_3(callid, (sysarg_t) result,
+			async_answer_3(callid, (sysarg_t) result,
 			    IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer),
 			    IPC_GET_ARG3(*answer));
 			break;
 		case 4:
-			ipc_answer_4(callid, (sysarg_t) result,
+			async_answer_4(callid, (sysarg_t) result,
 			    IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer),
 			    IPC_GET_ARG3(*answer), IPC_GET_ARG4(*answer));
@@ -89,5 +86,5 @@
 		case 5:
 		default:
-			ipc_answer_5(callid, (sysarg_t) result,
+			async_answer_5(callid, (sysarg_t) result,
 			    IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer),
 			    IPC_GET_ARG3(*answer), IPC_GET_ARG4(*answer),
@@ -137,18 +134,13 @@
     sysarg_t arg3, async_client_conn_t client_receiver, suseconds_t timeout)
 {
-	int rc;
-	
 	/* Connect to the needed service */
 	int phone = connect_to_service_timeout(need, timeout);
 	if (phone >= 0) {
 		/* Request the bidirectional connection */
-		sysarg_t phonehash;
-		
-		rc = ipc_connect_to_me(phone, arg1, arg2, arg3, &phonehash);
+		int rc = async_connect_to_me(phone, arg1, arg2, arg3, client_receiver);
 		if (rc != EOK) {
-			ipc_hangup(phone);
+			async_hangup(phone);
 			return rc;
 		}
-		async_new_connection(phonehash, 0, NULL, client_receiver);
 	}
 	
Index: uspace/lib/c/generic/net/socket_client.c
===================================================================
--- uspace/lib/c/generic/net/socket_client.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/net/socket_client.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -43,8 +43,7 @@
 #include <stdlib.h>
 #include <errno.h>
-
+#include <task.h>
 #include <ipc/services.h>
 #include <ipc/socket.h>
-
 #include <net/modules.h>
 #include <net/in.h>
@@ -278,5 +277,5 @@
 	}
 
-	ipc_answer_0(callid, (sysarg_t) rc);
+	async_answer_0(callid, (sysarg_t) rc);
 	goto loop;
 }
@@ -687,5 +686,5 @@
 
 	/* Read address */
-	ipc_data_read_start(socket->phone, cliaddr, *addrlen);
+	async_data_read_start(socket->phone, cliaddr, *addrlen);
 	fibril_rwlock_write_unlock(&socket_globals.lock);
 	async_wait_for(message_id, &ipc_result);
Index: uspace/lib/c/generic/private/async.h
===================================================================
--- uspace/lib/c/generic/private/async.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/c/generic/private/async.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_ASYNC_H_
+#define LIBC_PRIVATE_ASYNC_H_
+
+#include <adt/list.h>
+#include <fibril.h>
+#include <sys/time.h>
+#include <bool.h>
+
+/** Structures of this type are used to track the timeout events. */
+typedef struct {
+	/** If true, this struct is in the timeout list. */
+	bool inlist;
+	
+	/** Timeout list link. */
+	link_t link;
+	
+	/** If true, we have timed out. */
+	bool occurred;
+	
+	/** Expiration time. */
+	struct timeval expires;
+} to_event_t;
+
+/** Structures of this type are used to track the wakeup events. */
+typedef struct {
+	/** If true, this struct is in a synchronization object wait queue. */
+	bool inlist;
+	
+	/** Wait queue linkage. */
+	link_t link;
+} wu_event_t;
+
+/** Structures of this type represent a waiting fibril. */
+typedef struct {
+	/** Identification of and link to the waiting fibril. */
+	fid_t fid;
+	
+	/** If true, this fibril is currently active. */
+	bool active;
+	
+	/** Timeout wait data. */
+	to_event_t to_event;
+	/** Wakeup wait data. */
+	wu_event_t wu_event;
+} awaiter_t;
+
+extern void __async_init(void);
+extern void async_insert_timeout(awaiter_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/async_sess.h
===================================================================
--- uspace/lib/c/generic/private/async_sess.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/c/generic/private/async_sess.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_ASYNC_SESS_H_
+#define LIBC_PRIVATE_ASYNC_SESS_H_
+
+extern void __async_sess_init(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/io.h
===================================================================
--- uspace/lib/c/generic/private/io.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/c/generic/private/io.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_IO_H_
+#define LIBC_PRIVATE_IO_H_
+
+#include <vfs/vfs.h>
+
+extern void __stdio_init(int filc, fdi_node_t *filv[]);
+extern void __stdio_done(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/libc.h
===================================================================
--- uspace/lib/c/generic/private/libc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/c/generic/private/libc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_LIBC_H_
+#define LIBC_PRIVATE_LIBC_H_
+
+extern void __entry(void);
+extern void __main(void *) __attribute__((noreturn));
+extern int main(int, char *[]);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/malloc.h
===================================================================
--- uspace/lib/c/generic/private/malloc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/c/generic/private/malloc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_MALLOC_H_
+#define LIBC_PRIVATE_MALLOC_H_
+
+extern void __malloc_init(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/thread.h
===================================================================
--- uspace/lib/c/generic/private/thread.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/c/generic/private/thread.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_THREAD_H_
+#define LIBC_PRIVATE_THREAD_H_
+
+#include <kernel/proc/uarg.h>
+
+extern void __thread_entry(void);
+extern void __thread_main(uspace_arg_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/stats.c
===================================================================
--- uspace/lib/c/generic/stats.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/stats.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,8 +36,8 @@
 #include <stats.h>
 #include <sysinfo.h>
-#include <assert.h>
 #include <errno.h>
 #include <stdio.h>
 #include <inttypes.h>
+#include <malloc.h>
 
 #define SYSINFO_STATS_MAX_PATH  64
@@ -71,5 +71,10 @@
 	    (stats_cpu_t *) sysinfo_get_data("system.cpus", &size);
 	
-	assert((size % sizeof(stats_cpu_t)) == 0);
+	if ((size % sizeof(stats_cpu_t)) != 0) {
+		if (stats_cpus != NULL)
+			free(stats_cpus);
+		*count = 0;
+		return NULL;
+	}
 	
 	*count = size / sizeof(stats_cpu_t);
@@ -91,5 +96,9 @@
 	    (stats_physmem_t *) sysinfo_get_data("system.physmem", &size);
 	
-	assert((size == sizeof(stats_physmem_t)) || (size == 0));
+	if (size != sizeof(stats_physmem_t)) {
+		if (stats_physmem != NULL)
+			free(stats_physmem);
+		return NULL;
+	}
 	
 	return stats_physmem;
@@ -111,5 +120,10 @@
 	    (stats_task_t *) sysinfo_get_data("system.tasks", &size);
 	
-	assert((size % sizeof(stats_task_t)) == 0);
+	if ((size % sizeof(stats_task_t)) != 0) {
+		if (stats_tasks != NULL)
+			free(stats_tasks);
+		*count = 0;
+		return NULL;
+	}
 	
 	*count = size / sizeof(stats_task_t);
@@ -135,5 +149,9 @@
 	    (stats_task_t *) sysinfo_get_data(name, &size);
 	
-	assert((size == sizeof(stats_task_t)) || (size == 0));
+	if (size != sizeof(stats_task_t)) {
+		if (stats_task != NULL)
+			free(stats_task);
+		return NULL;
+	}
 	
 	return stats_task;
@@ -155,5 +173,10 @@
 	    (stats_thread_t *) sysinfo_get_data("system.threads", &size);
 	
-	assert((size % sizeof(stats_thread_t)) == 0);
+	if ((size % sizeof(stats_thread_t)) != 0) {
+		if (stats_threads != NULL)
+			free(stats_threads);
+		*count = 0;
+		return NULL;
+	}
 	
 	*count = size / sizeof(stats_thread_t);
@@ -179,5 +202,9 @@
 	    (stats_thread_t *) sysinfo_get_data(name, &size);
 	
-	assert((size == sizeof(stats_thread_t)) || (size == 0));
+	if (size != sizeof(stats_thread_t)) {
+		if (stats_thread != NULL)
+			free(stats_thread);
+		return NULL;
+	}
 	
 	return stats_thread;
@@ -199,5 +226,10 @@
 	    (stats_exc_t *) sysinfo_get_data("system.exceptions", &size);
 	
-	assert((size % sizeof(stats_exc_t)) == 0);
+	if ((size % sizeof(stats_exc_t)) != 0) {
+		if (stats_exceptions != NULL)
+			free(stats_exceptions);
+		*count = 0;
+		return NULL;
+	}
 	
 	*count = size / sizeof(stats_exc_t);
@@ -217,5 +249,5 @@
 {
 	char name[SYSINFO_STATS_MAX_PATH];
-	snprintf(name, SYSINFO_STATS_MAX_PATH, "system.exceptionss.%u", excn);
+	snprintf(name, SYSINFO_STATS_MAX_PATH, "system.exceptions.%u", excn);
 	
 	size_t size = 0;
@@ -223,5 +255,9 @@
 	    (stats_exc_t *) sysinfo_get_data(name, &size);
 	
-	assert((size == sizeof(stats_exc_t)) || (size == 0));
+	if (size != sizeof(stats_exc_t)) {
+		if (stats_exception != NULL)
+			free(stats_exception);
+		return NULL;
+	}
 	
 	return stats_exception;
@@ -243,5 +279,10 @@
 	    (load_t *) sysinfo_get_data("system.load", &size);
 	
-	assert((size % sizeof(load_t)) == 0);
+	if ((size % sizeof(load_t)) != 0) {
+		if (load != NULL)
+			free(load);
+		*count = 0;
+		return NULL;
+	}
 	
 	*count = size / sizeof(load_t);
Index: uspace/lib/c/generic/str_error.c
===================================================================
--- uspace/lib/c/generic/str_error.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/str_error.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,4 +33,5 @@
  */
 
+#include <errno.h>
 #include <str_error.h>
 #include <stdio.h>
@@ -63,10 +64,24 @@
 static fibril_local char noerr[NOERR_LEN];
 
-const char *str_error(const int errno)
+const char *str_error(const int e)
 {
-	if ((errno <= 0) && (errno >= MIN_ERRNO))
-		return err_desc[-errno];
+	if ((e <= 0) && (e >= MIN_ERRNO))
+		return err_desc[-e];
 	
-	snprintf(noerr, NOERR_LEN, "Unkown error code %d", errno);
+	/* Ad hoc descriptions of error codes interesting for USB. */
+	switch (e) {
+		case EBADCHECKSUM:
+			return "Bad checksum";
+		case ESTALL:
+			return "Operation stalled";
+		case EAGAIN:
+			return "Resource temporarily unavailable";
+		case EEMPTY:
+			return "Resource is empty";
+		default:
+			break;
+	}
+
+	snprintf(noerr, NOERR_LEN, "Unkown error code %d", e);
 	return noerr;
 }
Index: uspace/lib/c/generic/sysinfo.c
===================================================================
--- uspace/lib/c/generic/sysinfo.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/sysinfo.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -96,42 +96,38 @@
 void *sysinfo_get_data(const char *path, size_t *size)
 {
-	/* The binary data size might change during time.
-	   Unfortunatelly we cannot allocate the buffer
-	   and transfer the data as a single atomic operation.
+	/*
+	 * The binary data size might change during time.
+	 * Unfortunatelly we cannot allocate the buffer
+	 * and transfer the data as a single atomic operation.
+	 */
 	
-	   Let's hope that the number of iterations is bounded
-	   in common cases. */
-	
-	void *data = NULL;
-	
-	while (true) {
-		/* Get the binary data size */
-		int ret = sysinfo_get_data_size(path, size);
-		if ((ret != EOK) || (size == 0)) {
-			/* Not a binary data item
-			   or an empty item */
-			break;
-		}
-		
-		data = realloc(data, *size);
-		if (data == NULL)
-			break;
-		
-		/* Get the data */
-		ret = __SYSCALL4(SYS_SYSINFO_GET_DATA, (sysarg_t) path,
-		    (sysarg_t) str_size(path), (sysarg_t) data, (sysarg_t) *size);
-		if (ret == EOK)
-			return data;
-		
-		if (ret != ENOMEM) {
-			/* The failure to get the data was not caused
-			   by wrong buffer size */
-			break;
-		}
+	/* Get the binary data size */
+	int ret = sysinfo_get_data_size(path, size);
+	if ((ret != EOK) || (size == 0)) {
+		/*
+		 * Not a binary data item
+		 * or an empty item.
+		 */
+		*size = 0;
+		return NULL;
 	}
 	
-	if (data != NULL)
-		free(data);
+	void *data = malloc(*size);
+	if (data == NULL) {
+		*size = 0;
+		return NULL;
+	}
 	
+	/* Get the data */
+	size_t sz;
+	ret = __SYSCALL5(SYS_SYSINFO_GET_DATA, (sysarg_t) path,
+	    (sysarg_t) str_size(path), (sysarg_t) data, (sysarg_t) *size,
+	    (sysarg_t) &sz);
+	if (ret == EOK) {
+		*size = sz;
+		return data;
+	}
+	
+	free(data);
 	*size = 0;
 	return NULL;
Index: uspace/lib/c/generic/thread.c
===================================================================
--- uspace/lib/c/generic/thread.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/thread.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -31,5 +31,5 @@
  */
 /** @file
- */ 
+ */
 
 #include <thread.h>
@@ -41,4 +41,5 @@
 #include <str.h>
 #include <async.h>
+#include "private/thread.h"
 
 #ifndef THREAD_INITIAL_STACK_PAGES_NO
@@ -50,25 +51,27 @@
  * This function is called from __thread_entry() and is used
  * to call the thread's implementing function and perform cleanup
- * and exit when thread returns back. Do not call this function
- * directly.
+ * and exit when thread returns back.
  *
  * @param uarg Pointer to userspace argument structure.
+ *
  */
 void __thread_main(uspace_arg_t *uarg)
 {
-	fibril_t *f;
-
-	f = fibril_setup();
-	__tcb_set(f->tcb);
-
+	fibril_t *fibril = fibril_setup();
+	if (fibril == NULL)
+		thread_exit(0);
+	
+	__tcb_set(fibril->tcb);
+	
 	uarg->uspace_thread_function(uarg->uspace_thread_arg);
-	/* XXX: we cannot free the userspace stack while running on it */
-//	free(uarg->uspace_stack);
-//	free(uarg);
-
+	/* XXX: we cannot free the userspace stack while running on it
+		free(uarg->uspace_stack);
+		free(uarg);
+	*/
+	
 	/* If there is a manager, destroy it */
 	async_destroy_manager();
-	fibril_teardown(f);
-
+	fibril_teardown(fibril);
+	
 	thread_exit(0);
 }
@@ -127,10 +130,12 @@
  *
  * @param status Exit status. Currently not used.
+ *
  */
 void thread_exit(int status)
 {
 	__SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status);
-	for (;;)
-		;
+	
+	/* Unreachable */
+	while (1);
 }
 
Index: uspace/lib/c/generic/time.c
===================================================================
--- uspace/lib/c/generic/time.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/time.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,21 +34,15 @@
 
 #include <sys/time.h>
-#include <unistd.h>
-#include <ipc/ipc.h>
-#include <stdio.h>
+#include <time.h>
+#include <bool.h>
 #include <arch/barrier.h>
-#include <unistd.h>
-#include <atomic.h>
-#include <sysinfo.h>
-#include <ipc/services.h>
-#include <libc.h>
-
+#include <macros.h>
+#include <errno.h>
 #include <sysinfo.h>
 #include <as.h>
 #include <ddi.h>
-
-#include <time.h>
-
-/* Pointers to public variables with time */
+#include <libc.h>
+
+/** Pointer to kernel shared variables with time */
 struct {
 	volatile sysarg_t seconds1;
@@ -59,6 +53,7 @@
 /** Add microseconds to given timeval.
  *
- * @param tv		Destination timeval.
- * @param usecs		Number of microseconds to add.
+ * @param tv    Destination timeval.
+ * @param usecs Number of microseconds to add.
+ *
  */
 void tv_add(struct timeval *tv, suseconds_t usecs)
@@ -66,4 +61,5 @@
 	tv->tv_sec += usecs / 1000000;
 	tv->tv_usec += usecs % 1000000;
+	
 	if (tv->tv_usec > 1000000) {
 		tv->tv_sec++;
@@ -74,104 +70,117 @@
 /** Subtract two timevals.
  *
- * @param tv1		First timeval.
- * @param tv2		Second timeval.
- *
- * @return		Return difference between tv1 and tv2 (tv1 - tv2) in
- * 			microseconds.
+ * @param tv1 First timeval.
+ * @param tv2 Second timeval.
+ *
+ * @return Difference between tv1 and tv2 (tv1 - tv2) in
+ *         microseconds.
+ *
  */
 suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2)
 {
-	suseconds_t result;
-
-	result = tv1->tv_usec - tv2->tv_usec;
-	result += (tv1->tv_sec - tv2->tv_sec) * 1000000;
-
-	return result;
+	return (tv1->tv_usec - tv2->tv_usec) +
+	    ((tv1->tv_sec - tv2->tv_sec) * 1000000);
 }
 
 /** Decide if one timeval is greater than the other.
  *
- * @param t1		First timeval.
- * @param t2		Second timeval.
- *
- * @return		Return true tv1 is greater than tv2. Otherwise return
- * 			false.
+ * @param t1 First timeval.
+ * @param t2 Second timeval.
+ *
+ * @return True if tv1 is greater than tv2.
+ * @return False otherwise.
+ *
  */
 int tv_gt(struct timeval *tv1, struct timeval *tv2)
 {
 	if (tv1->tv_sec > tv2->tv_sec)
-		return 1;
-	if (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec > tv2->tv_usec)
-		return 1;
-	return 0;
+		return true;
+	
+	if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec > tv2->tv_usec))
+		return true;
+	
+	return false;
 }
 
 /** Decide if one timeval is greater than or equal to the other.
  *
- * @param tv1		First timeval.
- * @param tv2		Second timeval.
- *
- * @return		Return true if tv1 is greater than or equal to tv2.
- * 			Otherwise return false.
+ * @param tv1 First timeval.
+ * @param tv2 Second timeval.
+ *
+ * @return True if tv1 is greater than or equal to tv2.
+ * @return False otherwise.
+ *
  */
 int tv_gteq(struct timeval *tv1, struct timeval *tv2)
 {
 	if (tv1->tv_sec > tv2->tv_sec)
-		return 1;
-	if (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec >= tv2->tv_usec)
-		return 1;
-	return 0;
-}
-
-
-/** POSIX gettimeofday
- *
- * The time variables are memory mapped(RO) from kernel, which updates
- * them periodically. As it is impossible to read 2 values atomically, we
- * use a trick: First read a seconds, then read microseconds, then
- * read seconds again. If a second elapsed in the meantime, set it to zero. 
- * This provides assurance, that at least the
- * sequence of subsequent gettimeofday calls is ordered.
+		return true;
+	
+	if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec >= tv2->tv_usec))
+		return true;
+	
+	return false;
+}
+
+/** Get time of day
+ *
+ * The time variables are memory mapped (read-only) from kernel which
+ * updates them periodically.
+ *
+ * As it is impossible to read 2 values atomically, we use a trick:
+ * First we read the seconds, then we read the microseconds, then we
+ * read the seconds again. If a second elapsed in the meantime, set
+ * the microseconds to zero.
+ *
+ * This assures that the values returned by two subsequent calls
+ * to gettimeofday() are monotonous.
+ *
  */
 int gettimeofday(struct timeval *tv, struct timezone *tz)
 {
-	void *mapping;
-	sysarg_t s1, s2;
-	int rights;
-	int res;
-
-	if (!ktime) {
-		mapping = as_get_mappable_page(PAGE_SIZE);
-		/* Get the mapping of kernel clock */
-		res = ipc_share_in_start_1_1(PHONE_NS, mapping, PAGE_SIZE,
-		    SERVICE_MEM_REALTIME, &rights);
-		if (res) {
-			printf("Failed to initialize timeofday memarea\n");
-			_exit(1);
+	if (ktime == NULL) {
+		uintptr_t faddr;
+		int rc = sysinfo_get_value("clock.faddr", &faddr);
+		if (rc != EOK) {
+			errno = rc;
+			return -1;
 		}
-		if (!(rights & AS_AREA_READ)) {
-			printf("Received bad rights on time area: %X\n",
-			    rights);
-			as_area_destroy(mapping);
-			_exit(1);
+		
+		void *addr = as_get_mappable_page(PAGE_SIZE);
+		if (addr == NULL) {
+			errno = ENOMEM;
+			return -1;
 		}
-		ktime = mapping;
-	}
+		
+		rc = physmem_map((void *) faddr, addr, 1,
+		    AS_AREA_READ | AS_AREA_CACHEABLE);
+		if (rc != EOK) {
+			as_area_destroy(addr);
+			errno = rc;
+			return -1;
+		}
+		
+		ktime = addr;
+	}
+	
 	if (tz) {
 		tz->tz_minuteswest = 0;
 		tz->tz_dsttime = DST_NONE;
 	}
-
-	s2 = ktime->seconds2;
+	
+	sysarg_t s2 = ktime->seconds2;
+	
 	read_barrier();
 	tv->tv_usec = ktime->useconds;
+	
 	read_barrier();
-	s1 = ktime->seconds1;
+	sysarg_t s1 = ktime->seconds1;
+	
 	if (s1 != s2) {
+		tv->tv_sec = max(s1, s2);
 		tv->tv_usec = 0;
-		tv->tv_sec = s1 > s2 ? s1 : s2;
 	} else
 		tv->tv_sec = s1;
-
+	
 	return 0;
 }
@@ -180,13 +189,16 @@
 {
 	struct timeval tv;
-
 	if (gettimeofday(&tv, NULL))
 		return (time_t) -1;
+	
 	if (tloc)
 		*tloc = tv.tv_sec;
+	
 	return tv.tv_sec;
 }
 
-/** Wait unconditionally for specified number of microseconds */
+/** Wait unconditionally for specified number of microseconds
+ *
+ */
 int usleep(useconds_t usec)
 {
@@ -195,15 +207,21 @@
 }
 
-/** Wait unconditionally for specified number of seconds */
+/** Wait unconditionally for specified number of seconds
+ *
+ */
 unsigned int sleep(unsigned int sec)
 {
-	/* Sleep in 1000 second steps to support
-	   full argument range */
+	/*
+	 * Sleep in 1000 second steps to support
+	 * full argument range
+	 */
+	
 	while (sec > 0) {
 		unsigned int period = (sec > 1000) ? 1000 : sec;
-	
+		
 		usleep(period * 1000000);
 		sec -= period;
 	}
+	
 	return 0;
 }
Index: uspace/lib/c/generic/udebug.c
===================================================================
--- uspace/lib/c/generic/udebug.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/udebug.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -31,9 +31,8 @@
  */
 /** @file
- */ 
+ */
 
 #include <udebug.h>
 #include <sys/types.h>
-#include <ipc/ipc.h>
 #include <async.h>
 
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2008 Jakub Jermar 
+ * Copyright (c) 2008 Jakub Jermar
  * All rights reserved.
  *
@@ -43,10 +43,10 @@
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
+#include <ipc/ns.h>
 #include <async.h>
-#include <atomic.h>
-#include <futex.h>
+#include <fibril_synch.h>
 #include <errno.h>
+#include <assert.h>
 #include <str.h>
 #include <devmap.h>
@@ -54,7 +54,10 @@
 #include <ipc/devmap.h>
 
+static async_sess_t vfs_session;
+
+static FIBRIL_MUTEX_INITIALIZE(vfs_phone_mutex);
 static int vfs_phone = -1;
-static futex_t vfs_phone_futex = FUTEX_INITIALIZER;
-static futex_t cwd_futex = FUTEX_INITIALIZER;
+
+static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
 
 static int cwd_fd = -1;
@@ -67,14 +70,14 @@
 	char *ncwd_path_nc;
 
-	futex_down(&cwd_futex);
+	fibril_mutex_lock(&cwd_mutex);
 	size_t size = str_size(path);
 	if (*path != '/') {
 		if (!cwd_path) {
-			futex_up(&cwd_futex);
+			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
 		}
 		ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
 		if (!ncwd_path_nc) {
-			futex_up(&cwd_futex);
+			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
 		}
@@ -85,5 +88,5 @@
 		ncwd_path_nc = malloc(size + 1);
 		if (!ncwd_path_nc) {
-			futex_up(&cwd_futex);
+			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
 		}
@@ -93,5 +96,5 @@
 	ncwd_path = canonify(ncwd_path_nc, retlen);
 	if (!ncwd_path) {
-		futex_up(&cwd_futex);
+		fibril_mutex_unlock(&cwd_mutex);
 		free(ncwd_path_nc);
 		return NULL;
@@ -105,15 +108,41 @@
 	free(ncwd_path_nc);
 	if (!ncwd_path) {
-		futex_up(&cwd_futex);
+		fibril_mutex_unlock(&cwd_mutex);
 		return NULL;
 	}
-	futex_up(&cwd_futex);
+	fibril_mutex_unlock(&cwd_mutex);
 	return ncwd_path;
 }
 
+/** Connect to VFS service and create session. */
 static void vfs_connect(void)
 {
 	while (vfs_phone < 0)
-		vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
+		vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
+	
+	async_session_create(&vfs_session, vfs_phone, 0);
+}
+
+/** Start an async exchange on the VFS session.
+ *
+ * @return		New phone to be used during the exchange.
+ */
+static int vfs_exchange_begin(void)
+{
+	fibril_mutex_lock(&vfs_phone_mutex);
+	if (vfs_phone < 0)
+		vfs_connect();
+	fibril_mutex_unlock(&vfs_phone_mutex);
+
+	return async_exchange_begin(&vfs_session);
+}
+
+/** End an async exchange on the VFS session.
+ *
+ * @param phone		Phone used during the exchange.
+ */
+static void vfs_exchange_end(int phone)
+{
+	async_exchange_end(&vfs_session, phone);
 }
 
@@ -154,16 +183,13 @@
 	}
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
-	
+	int vfs_phone = vfs_exchange_begin();
+
 	sysarg_t rc_orig;
 	aid_t req = async_send_2(vfs_phone, VFS_IN_MOUNT, devmap_handle, flags, NULL);
 	sysarg_t rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(mpa);
+		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
@@ -178,8 +204,7 @@
 	rc = async_data_write_start(vfs_phone, (void *) opts, str_size(opts));
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(mpa);
+		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
@@ -194,8 +219,7 @@
 	rc = async_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(mpa);
+		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
@@ -211,8 +235,7 @@
 	rc = async_req_0_0(vfs_phone, IPC_M_PING);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(mpa);
+		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
@@ -225,8 +248,7 @@
 	}
 	
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	free(mpa);
+	async_wait_for(req, &rc);
 	
 	if ((rc != EOK) && (null_id != -1))
@@ -248,26 +270,22 @@
 		return ENOMEM;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_0(vfs_phone, VFS_IN_UNMOUNT, NULL);
 	rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(mpa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	
+
+	vfs_exchange_end(vfs_phone);
 	free(mpa);
+	async_wait_for(req, &rc);
 	
 	return (int) rc;
@@ -276,7 +294,5 @@
 static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
 {
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	ipc_call_t answer;
@@ -285,19 +301,17 @@
 	
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+
 		sysarg_t rc_orig;
 		async_wait_for(req, &rc_orig);
 		
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
-		
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	
+	vfs_exchange_end(vfs_phone);
+	async_wait_for(req, &rc);
 	
 	if (rc != EOK)
@@ -322,7 +336,5 @@
 int open_node(fdi_node_t *node, int oflag)
 {
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	ipc_call_t answer;
@@ -330,8 +342,8 @@
 	    node->devmap_handle, node->index, oflag, &answer);
 	
-	sysarg_t rc;
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
+
+	sysarg_t rc;
+	async_wait_for(req, &rc);
 	
 	if (rc != EOK)
@@ -345,12 +357,9 @@
 	sysarg_t rc;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
 	
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	
 	return (int)rc;
@@ -363,16 +372,14 @@
 	aid_t req;
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
 	rc = async_data_read_start(vfs_phone, (void *)buf, nbyte);
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+
 		sysarg_t rc_orig;
-	
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+
 		if (rc_orig == EOK)
 			return (ssize_t) rc;
@@ -380,7 +387,6 @@
 			return (ssize_t) rc_orig;
 	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
+	async_wait_for(req, &rc);
 	if (rc == EOK)
 		return (ssize_t) IPC_GET_ARG1(answer);
@@ -395,16 +401,14 @@
 	aid_t req;
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
 	rc = async_data_write_start(vfs_phone, (void *)buf, nbyte);
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+
 		sysarg_t rc_orig;
-	
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+
 		if (rc_orig == EOK)
 			return (ssize_t) rc;
@@ -412,7 +416,6 @@
 			return (ssize_t) rc_orig;
 	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
+	async_wait_for(req, &rc);
 	if (rc == EOK)
 		return (ssize_t) IPC_GET_ARG1(answer);
@@ -423,12 +426,9 @@
 int fsync(int fildes)
 {
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	sysarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
 	
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	
 	return (int) rc;
@@ -437,7 +437,5 @@
 off64_t lseek(int fildes, off64_t offset, int whence)
 {
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	sysarg_t newoff_lo;
@@ -447,6 +445,5 @@
 	    &newoff_lo, &newoff_hi);
 	
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	
 	if (rc != EOK)
@@ -460,12 +457,9 @@
 	sysarg_t rc;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	rc = async_req_3_0(vfs_phone, VFS_IN_TRUNCATE, fildes,
 	    LOWER32(length), UPPER32(length));
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	
 	return (int) rc;
@@ -477,16 +471,14 @@
 	aid_t req;
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL);
 	rc = async_data_read_start(vfs_phone, (void *) stat, sizeof(struct stat));
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+
 		sysarg_t rc_orig;
-		
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+
 		if (rc_orig == EOK)
 			return (ssize_t) rc;
@@ -494,7 +486,6 @@
 			return (ssize_t) rc_orig;
 	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
+	async_wait_for(req, &rc);
 
 	return rc;
@@ -512,15 +503,12 @@
 		return ENOMEM;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
 	rc = async_data_write_start(vfs_phone, pa, pa_size);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(pa);
+		async_wait_for(req, &rc_orig);
 		if (rc_orig == EOK)
 			return (int) rc;
@@ -530,17 +518,15 @@
 	rc = async_data_read_start(vfs_phone, stat, sizeof(struct stat));
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(pa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	vfs_exchange_end(vfs_phone);
 	free(pa);
+	async_wait_for(req, &rc);
 	return rc;
 }
@@ -601,26 +587,23 @@
 		return ENOMEM;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
 	rc = async_data_write_start(vfs_phone, pa, pa_size);
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+		free(pa);
+
 		sysarg_t rc_orig;
-	
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
-		free(pa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	vfs_exchange_end(vfs_phone);
 	free(pa);
+	async_wait_for(req, &rc);
 	return rc;
 }
@@ -636,26 +619,23 @@
 		return ENOMEM;
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
 	rc = async_data_write_start(vfs_phone, pa, pa_size);
 	if (rc != EOK) {
+		vfs_exchange_end(vfs_phone);
+		free(pa);
+
 		sysarg_t rc_orig;
-
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
-		free(pa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	vfs_exchange_end(vfs_phone);
 	free(pa);
+	async_wait_for(req, &rc);
 	return rc;
 }
@@ -689,16 +669,13 @@
 	}
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
 	rc = async_data_write_start(vfs_phone, olda, olda_size);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(olda);
 		free(newa);
+		async_wait_for(req, &rc_orig);
 		if (rc_orig == EOK)
 			return (int) rc;
@@ -708,19 +685,17 @@
 	rc = async_data_write_start(vfs_phone, newa, newa_size);
 	if (rc != EOK) {
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+		vfs_exchange_end(vfs_phone);
 		free(olda);
 		free(newa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+		async_wait_for(req, &rc_orig);
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	vfs_exchange_end(vfs_phone);
 	free(olda);
 	free(newa);
+	async_wait_for(req, &rc);
 	return rc;
 }
@@ -740,5 +715,5 @@
 	}
 	
-	futex_down(&cwd_futex);
+	fibril_mutex_lock(&cwd_mutex);
 	
 	if (cwd_fd >= 0)
@@ -753,5 +728,5 @@
 	cwd_size = abs_size;
 	
-	futex_up(&cwd_futex);
+	fibril_mutex_unlock(&cwd_mutex);
 	return EOK;
 }
@@ -762,13 +737,13 @@
 		return NULL;
 	
-	futex_down(&cwd_futex);
+	fibril_mutex_lock(&cwd_mutex);
 	
 	if ((cwd_size == 0) || (size < cwd_size + 1)) {
-		futex_up(&cwd_futex);
+		fibril_mutex_unlock(&cwd_mutex);
 		return NULL;
 	}
 	
 	str_cpy(buf, size, cwd_path);
-	futex_up(&cwd_futex);
+	fibril_mutex_unlock(&cwd_mutex);
 	
 	return buf;
@@ -806,13 +781,10 @@
 int dup2(int oldfd, int newfd)
 {
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
+	int vfs_phone = vfs_exchange_begin();
 	
 	sysarg_t ret;
 	sysarg_t rc = async_req_2_1(vfs_phone, VFS_IN_DUP, oldfd, newfd, &ret);
 	
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
+	vfs_exchange_end(vfs_phone);
 	
 	if (rc == EOK)
Index: uspace/lib/c/include/adt/hash_table.h
===================================================================
--- uspace/lib/c/include/adt/hash_table.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/adt/hash_table.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,41 +41,42 @@
 typedef unsigned long hash_count_t;
 typedef unsigned long hash_index_t;
-typedef struct hash_table hash_table_t;
-typedef struct hash_table_operations hash_table_operations_t;
+
+/** Set of operations for hash table. */
+typedef struct {
+	/** Hash function.
+	 *
+	 * @param key Array of keys needed to compute hash index.
+	 *            All keys must be passed.
+	 *
+	 * @return Index into hash table.
+	 *
+	 */
+	hash_index_t (*hash)(unsigned long key[]);
+	
+	/** Hash table item comparison function.
+	 *
+	 * @param key Array of keys that will be compared with item. It is
+	 *            not necessary to pass all keys.
+	 *
+	 * @return True if the keys match, false otherwise.
+	 *
+	 */
+	int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
+	
+	/** Hash table item removal callback.
+	 *
+	 * @param item Item that was removed from the hash table.
+	 *
+	 */
+	void (*remove_callback)(link_t *item);
+} hash_table_operations_t;
 
 /** Hash table structure. */
-struct hash_table {
+typedef struct {
 	link_t *entry;
 	hash_count_t entries;
 	hash_count_t max_keys;
 	hash_table_operations_t *op;
-};
-
-/** Set of operations for hash table. */
-struct hash_table_operations {
-	/** Hash function.
-	 *
-	 * @param key 	Array of keys needed to compute hash index. All keys
-	 *		must be passed.
-	 *
-	 * @return	Index into hash table.
-	 */
-	hash_index_t (* hash)(unsigned long key[]);
-	
-	/** Hash table item comparison function.
-	 *
-	 * @param key 	Array of keys that will be compared with item. It is
-	 *		not necessary to pass all keys.
-	 *
-	 * @return 	true if the keys match, false otherwise.
-	 */
-	int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
-
-	/** Hash table item removal callback.
-	 *
-	 * @param item 	Item that was removed from the hash table.
-	 */
-	void (*remove_callback)(link_t *item);
-};
+} hash_table_t;
 
 #define hash_table_get_instance(item, type, member) \
Index: uspace/lib/c/include/as.h
===================================================================
--- uspace/lib/c/include/as.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/as.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,4 +41,17 @@
 #include <libarch/config.h>
 
+static inline size_t SIZE2PAGES(size_t size)
+{
+	if (size == 0)
+		return 0;
+	
+	return (size_t) ((size - 1) >> PAGE_WIDTH) + 1;
+}
+
+static inline size_t PAGES2SIZE(size_t pages)
+{
+	return (size_t) (pages << PAGE_WIDTH);
+}
+
 extern void *as_area_create(void *address, size_t size, int flags);
 extern int as_area_resize(void *address, size_t size, int flags);
@@ -47,4 +60,5 @@
 extern void *set_maxheapsize(size_t mhs);
 extern void * as_get_mappable_page(size_t sz);
+extern int as_get_physical_mapping(void *address, uintptr_t *frame);
 
 #endif
Index: uspace/lib/c/include/assert.h
===================================================================
--- uspace/lib/c/include/assert.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/assert.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -57,6 +57,4 @@
 			printf("Assertion failed (%s) at file '%s', " \
 			    "line %d.\n", #expr, __FILE__, __LINE__); \
-			stacktrace_print(); \
-			core(); \
 			abort(); \
 		} \
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/async.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,8 +33,12 @@
  */
 
+#if ((defined(LIBC_IPC_H_)) && (!defined(LIBC_ASYNC_C_)))
+	#error Do not intermix low-level IPC interface and async framework
+#endif
+
 #ifndef LIBC_ASYNC_H_
 #define LIBC_ASYNC_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 #include <async_sess.h>
 #include <fibril.h>
@@ -42,24 +46,22 @@
 #include <atomic.h>
 #include <bool.h>
+#include <task.h>
 
 typedef ipc_callid_t aid_t;
-typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call);
-
-extern atomic_t async_futex;
+
+typedef void *(*async_client_data_ctor_t)(void);
+typedef void (*async_client_data_dtor_t)(void *);
+
+typedef void (*async_client_conn_t)(ipc_callid_t, ipc_call_t *);
 
 extern atomic_t threads_in_ipc_wait;
 
-extern int __async_init(void);
-extern ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
-
-static inline ipc_callid_t async_get_call(ipc_call_t *data)
-{
-	return async_get_call_timeout(data, 0);
-}
-
-static inline void async_manager(void)
-{
-	fibril_switch(FIBRIL_TO_MANAGER);
-}
+#define async_manager() \
+	fibril_switch(FIBRIL_TO_MANAGER)
+
+#define async_get_call(data) \
+	async_get_call_timeout(data, 0)
+
+extern ipc_callid_t async_get_call_timeout(ipc_call_t *, suseconds_t);
 
 /*
@@ -85,40 +87,59 @@
 	    (arg5), (dataptr))
 
-extern aid_t async_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr);
-extern aid_t async_send_slow(int phoneid, sysarg_t method, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
-    ipc_call_t *dataptr);
-extern void async_wait_for(aid_t amsgid, sysarg_t *result);
-extern int async_wait_timeout(aid_t amsgid, sysarg_t *retval,
-    suseconds_t timeout);
-
-extern fid_t async_new_connection(sysarg_t in_phone_hash, ipc_callid_t callid,
-    ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *));
-extern void async_usleep(suseconds_t timeout);
+extern aid_t async_send_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, ipc_call_t *);
+extern aid_t async_send_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, ipc_call_t *);
+extern void async_wait_for(aid_t, sysarg_t *);
+extern int async_wait_timeout(aid_t, sysarg_t *, suseconds_t);
+
+extern fid_t async_new_connection(sysarg_t, sysarg_t, ipc_callid_t,
+    ipc_call_t *, void (*)(ipc_callid_t, ipc_call_t *));
+extern void async_usleep(suseconds_t);
 extern void async_create_manager(void);
 extern void async_destroy_manager(void);
 
-extern void async_set_client_connection(async_client_conn_t conn);
-extern void async_set_interrupt_received(async_client_conn_t conn);
-
-/* Wrappers for simple communication */
-#define async_msg_0(phone, method) \
-	ipc_call_async_0((phone), (method), NULL, NULL, true)
-#define async_msg_1(phone, method, arg1) \
-	ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \
-	    true)
-#define async_msg_2(phone, method, arg1, arg2) \
-	ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \
-	    true)
-#define async_msg_3(phone, method, arg1, arg2, arg3) \
-	ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \
-	    true)
-#define async_msg_4(phone, method, arg1, arg2, arg3, arg4) \
-	ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
-	    NULL, true)
-#define async_msg_5(phone, method, arg1, arg2, arg3, arg4, arg5) \
-	ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), NULL, NULL, true)
+extern void async_set_client_data_constructor(async_client_data_ctor_t);
+extern void async_set_client_data_destructor(async_client_data_dtor_t);
+
+extern void *async_client_data_get(void);
+
+extern void async_set_client_connection(async_client_conn_t);
+extern void async_set_interrupt_received(async_client_conn_t);
+
+/*
+ * Wrappers for simple communication.
+ */
+
+extern void async_msg_0(int, sysarg_t);
+extern void async_msg_1(int, sysarg_t, sysarg_t);
+extern void async_msg_2(int, sysarg_t, sysarg_t, sysarg_t);
+extern void async_msg_3(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern void async_msg_4(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern void async_msg_5(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t);
+
+/*
+ * Wrappers for answer routines.
+ */
+
+extern sysarg_t async_answer_0(ipc_callid_t, sysarg_t);
+extern sysarg_t async_answer_1(ipc_callid_t, sysarg_t, sysarg_t);
+extern sysarg_t async_answer_2(ipc_callid_t, sysarg_t, sysarg_t, sysarg_t);
+extern sysarg_t async_answer_3(ipc_callid_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t);
+extern sysarg_t async_answer_4(ipc_callid_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t);
+extern sysarg_t async_answer_5(ipc_callid_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t);
+
+/*
+ * Wrappers for forwarding routines.
+ */
+
+extern int async_forward_fast(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
+    unsigned int);
+extern int async_forward_slow(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, unsigned int);
 
 /*
@@ -128,4 +149,5 @@
  * and slow verion based on m.
  */
+
 #define async_req_0_0(phoneid, method) \
 	async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
@@ -243,10 +265,9 @@
 	    (arg5), (rc1), (rc2), (rc3), (rc4), (rc5))
 
-extern sysarg_t async_req_fast(int phoneid, sysarg_t method, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
-    sysarg_t *r3, sysarg_t *r4, sysarg_t *r5);
-extern sysarg_t async_req_slow(int phoneid, sysarg_t method, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
-    sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5);
+extern sysarg_t async_req_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *);
+extern sysarg_t async_req_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *,
+    sysarg_t *);
 
 static inline void async_serialize_start(void)
@@ -260,10 +281,16 @@
 }
 
+extern int async_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t,
+    async_client_conn_t);
 extern int async_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t);
 extern int async_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t);
+extern int async_connect_kbox(task_id_t);
+extern int async_hangup(int);
+extern void async_poke(void);
 
 /*
  * User-friendly wrappers for async_share_in_start().
  */
+
 #define async_share_in_start_0_0(phoneid, dst, size) \
 	async_share_in_start((phoneid), (dst), (size), 0, NULL)
@@ -275,9 +302,10 @@
 	async_share_in_start((phoneid), (dst), (size), (arg), (flags))
 
-extern int async_share_in_start(int, void *, size_t, sysarg_t, int *);
-extern int async_share_in_receive(ipc_callid_t *, size_t *);
-extern int async_share_in_finalize(ipc_callid_t, void *, int );
-extern int async_share_out_start(int, void *, int);
-extern int async_share_out_receive(ipc_callid_t *, size_t *, int *);
+extern int async_share_in_start(int, void *, size_t, sysarg_t, unsigned int *);
+extern bool async_share_in_receive(ipc_callid_t *, size_t *);
+extern int async_share_in_finalize(ipc_callid_t, void *, unsigned int);
+
+extern int async_share_out_start(int, void *, unsigned int);
+extern bool async_share_out_receive(ipc_callid_t *, size_t *, unsigned int *);
 extern int async_share_out_finalize(ipc_callid_t, void *);
 
@@ -285,4 +313,5 @@
  * User-friendly wrappers for async_data_read_forward_fast().
  */
+
 #define async_data_read_forward_0_0(phoneid, method, answer) \
 	async_data_read_forward_fast((phoneid), (method), 0, 0, 0, 0, NULL)
@@ -311,6 +340,7 @@
 	    (arg4), (answer))
 
+extern aid_t async_data_read(int, void *, size_t, ipc_call_t *);
 extern int async_data_read_start(int, void *, size_t);
-extern int async_data_read_receive(ipc_callid_t *, size_t *);
+extern bool async_data_read_receive(ipc_callid_t *, size_t *);
 extern int async_data_read_finalize(ipc_callid_t, const void *, size_t);
 
@@ -321,4 +351,5 @@
  * User-friendly wrappers for async_data_write_forward_fast().
  */
+
 #define async_data_write_forward_0_0(phoneid, method, answer) \
 	async_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, NULL)
@@ -350,10 +381,10 @@
 
 extern int async_data_write_start(int, const void *, size_t);
-extern int async_data_write_receive(ipc_callid_t *, size_t *);
+extern bool async_data_write_receive(ipc_callid_t *, size_t *);
 extern int async_data_write_finalize(ipc_callid_t, void *, size_t);
 
 extern int async_data_write_accept(void **, const bool, const size_t,
     const size_t, const size_t, size_t *);
-extern void async_data_write_void(const int);
+extern void async_data_write_void(sysarg_t);
 
 extern int async_data_write_forward_fast(int, sysarg_t, sysarg_t, sysarg_t,
Index: pace/lib/c/include/async_priv.h
===================================================================
--- uspace/lib/c/include/async_priv.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,87 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * 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 libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ASYNC_PRIV_H_
-#define LIBC_ASYNC_PRIV_H_
-
-#include <adt/list.h>
-#include <fibril.h>
-#include <sys/time.h>
-#include <bool.h>
-
-/** Structures of this type are used to track the timeout events. */
-typedef struct {
-	/** If true, this struct is in the timeout list. */
-	bool inlist;
-	
-	/** Timeout list link. */
-	link_t link;
-	
-	/** If true, we have timed out. */
-	bool occurred;
-
-	/** Expiration time. */
-	struct timeval expires;
-} to_event_t;
-
-/** Structures of this type are used to track the wakeup events. */
-typedef struct {
-	/** If true, this struct is in a synchronization object wait queue. */
-	bool inlist;
-	
-	/** Wait queue linkage. */
-	link_t link;
-} wu_event_t;
-
-
-/** Structures of this type represent a waiting fibril. */
-typedef struct {
-	/** Identification of and link to the waiting fibril. */
-	fid_t fid;
-	
-	/** If true, this fibril is currently active. */
-	bool active;
-
-	/** Timeout wait data. */
-	to_event_t to_event;
-	/** Wakeup wait data. */
-	wu_event_t wu_event;
-} awaiter_t;
-
-extern void async_insert_timeout(awaiter_t *wd);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/async_sess.h
===================================================================
--- uspace/lib/c/include/async_sess.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/async_sess.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,5 +45,4 @@
 } async_sess_t;
 
-extern void _async_sess_init(void);
 extern void async_session_create(async_sess_t *, int, sysarg_t);
 extern void async_session_destroy(async_sess_t *);
Index: uspace/lib/c/include/byteorder.h
===================================================================
--- uspace/lib/c/include/byteorder.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/byteorder.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -80,8 +80,8 @@
 #endif
 
-#define htons(n)	host2uint16_t_be((n))
-#define htonl(n)	host2uint32_t_be((n))
-#define ntohs(n)	uint16_t_be2host((n))
-#define ntohl(n)	uint32_t_be2host((n))
+#define htons(n)  host2uint16_t_be((n))
+#define htonl(n)  host2uint32_t_be((n))
+#define ntohs(n)  uint16_t_be2host((n))
+#define ntohl(n)  uint32_t_be2host((n))
 
 static inline uint64_t uint64_t_byteorder_swap(uint64_t n)
Index: uspace/lib/c/include/ddi.h
===================================================================
--- uspace/lib/c/include/ddi.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ddi.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,4 +36,6 @@
 #define LIBC_DDI_H_
 
+#include <sys/types.h>
+#include <kernel/ddi/irq.h>
 #include <task.h>
 
@@ -42,4 +44,6 @@
 extern int iospace_enable(task_id_t, void *, unsigned long);
 extern int pio_enable(void *, size_t, void **);
+extern int register_irq(int, int, int, irq_code_t *);
+extern int unregister_irq(int, int);
 
 #endif
Index: uspace/lib/c/include/devman.h
===================================================================
--- uspace/lib/c/include/devman.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/devman.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,10 +41,9 @@
 #include <bool.h>
 
-
 extern int devman_get_phone(devman_interface_t, unsigned int);
 extern void devman_hangup_phone(devman_interface_t);
 
 extern int devman_driver_register(const char *, async_client_conn_t);
-extern int devman_child_device_register(const char *, match_id_list_t *,
+extern int devman_add_function(const char *, fun_type_t, match_id_list_t *,
     devman_handle_t, devman_handle_t *);
 
Index: uspace/lib/c/include/err.h
===================================================================
--- uspace/lib/c/include/err.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/err.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,8 +39,8 @@
 
 #define errx(status, fmt, ...) \
-	{ \
+	do { \
 		printf((fmt), ##__VA_ARGS__); \
-		_exit(status); \
-	}
+		exit(status); \
+	} while (0)
 
 #endif
Index: uspace/lib/c/include/errno.h
===================================================================
--- uspace/lib/c/include/errno.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/errno.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,7 +39,7 @@
 #include <fibril.h>
 
+#define errno _errno
+
 extern int _errno;
-
-#define errno _errno
 
 #define EMFILE        (-18)
@@ -56,37 +56,45 @@
 #define EMLINK        (-266)
 
+/** Bad checksum. */
+#define EBADCHECKSUM  (-300)
+
+/** USB: stalled operation. */
+#define ESTALL (-301)
+
+/** Empty resource (no data). */
+#define EEMPTY (-302)
+
 /** An API function is called while another blocking function is in progress. */
-#define EINPROGRESS	(-10036)
+#define EINPROGRESS  (-10036)
 
 /** The socket identifier is not valid. */
-#define ENOTSOCK	(-10038)
+#define ENOTSOCK  (-10038)
 
 /** The destination address required. */
-#define EDESTADDRREQ	(-10039)
+#define EDESTADDRREQ  (-10039)
 
 /** Protocol is not supported.  */
-#define EPROTONOSUPPORT	(-10043)
+#define EPROTONOSUPPORT  (-10043)
 
 /** Socket type is not supported. */
-#define ESOCKTNOSUPPORT	(-10044)
+#define ESOCKTNOSUPPORT  (-10044)
 
 /** Protocol family is not supported. */
-#define EPFNOSUPPORT	(-10046)
+#define EPFNOSUPPORT  (-10046)
 
 /** Address family is not supported. */
-#define EAFNOSUPPORT	(-10047)
+#define EAFNOSUPPORT  (-10047)
 
 /** Address is already in use. */
-#define EADDRINUSE	(-10048)
+#define EADDRINUSE  (-10048)
 
 /** The socket is not connected or bound. */
-#define ENOTCONN	(-10057)
+#define ENOTCONN  (-10057)
 
 /** The requested operation was not performed. Try again later. */
-#define EAGAIN		(-11002)
+#define EAGAIN  (-11002)
 
-/** No data.
- */
-#define NO_DATA		(-11004)
+/** No data. */
+#define NO_DATA (-11004)
 
 #endif
Index: uspace/lib/c/include/event.h
===================================================================
--- uspace/lib/c/include/event.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/event.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,5 +37,4 @@
 
 #include <kernel/ipc/event_types.h>
-#include <ipc/ipc.h>
 
 extern int event_subscribe(event_type_t, sysarg_t);
Index: uspace/lib/c/include/io/console.h
===================================================================
--- uspace/lib/c/include/io/console.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/io/console.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
 #define LIBC_IO_CONSOLE_H_
 
-#include <ipc/ipc.h>
 #include <bool.h>
 
Index: uspace/lib/c/include/io/screenbuffer.h
===================================================================
--- uspace/lib/c/include/io/screenbuffer.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/io/screenbuffer.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,5 +38,4 @@
 #include <stdint.h>
 #include <sys/types.h>
-#include <ipc/ipc.h>
 #include <bool.h>
 
Index: uspace/lib/c/include/ipc/adb.h
===================================================================
--- uspace/lib/c/include/ipc/adb.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/adb.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -32,15 +32,14 @@
 /** @file
  * @brief ADB device interface.
- */ 
+ */
 
 #ifndef LIBC_IPC_ADB_H_
 #define LIBC_IPC_ADB_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 
 typedef enum {
 	ADB_REG_WRITE = IPC_FIRST_USER_METHOD
 } adb_request_t;
-
 
 typedef enum {
Index: uspace/lib/c/include/ipc/arp.h
===================================================================
--- uspace/lib/c/include/ipc/arp.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/arp.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
 #define LIBC_ARP_MESSAGES_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
Index: uspace/lib/c/include/ipc/bd.h
===================================================================
--- uspace/lib/c/include/ipc/bd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/bd.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -31,10 +31,10 @@
  */
 /** @file
- */ 
+ */
 
 #ifndef LIBC_IPC_BD_H_
 #define LIBC_IPC_BD_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 
 typedef enum {
Index: uspace/lib/c/include/ipc/char.h
===================================================================
--- uspace/lib/c/include/ipc/char.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/char.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -32,15 +32,14 @@
 /** @file
  * @brief Character device interface.
- */ 
+ */
 
 #ifndef LIBC_IPC_CHAR_H_
 #define LIBC_IPC_CHAR_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 
 typedef enum {
 	CHAR_WRITE_BYTE = IPC_FIRST_USER_METHOD
 } char_request_t;
-
 
 typedef enum {
Index: uspace/lib/c/include/ipc/clipboard.h
===================================================================
--- uspace/lib/c/include/ipc/clipboard.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/clipboard.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,6 +36,4 @@
 #define LIBC_IPC_CLIPBOARD_H_
 
-#include <ipc/ipc.h>
-
 typedef enum {
 	CLIPBOARD_PUT_DATA = IPC_FIRST_USER_METHOD,
Index: uspace/lib/c/include/ipc/common.h
===================================================================
--- uspace/lib/c/include/ipc/common.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/c/include/ipc/common.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * 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 libcipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IPC_COMMON_H_
+#define LIBC_IPC_COMMON_H_
+
+#include <sys/types.h>
+#include <atomic.h>
+#include <kernel/ipc/ipc.h>
+
+#define IPC_FLAG_BLOCKING  0x01
+
+typedef struct {
+	sysarg_t args[IPC_CALL_LEN];
+	sysarg_t in_task_hash;
+	sysarg_t in_phone_hash;
+} ipc_call_t;
+
+typedef sysarg_t ipc_callid_t;
+
+extern atomic_t async_futex;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/console.h
===================================================================
--- uspace/lib/c/include/ipc/console.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/console.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
 #define LIBC_IPC_CONSOLE_H_
 
-#include <ipc/ipc.h>
 #include <ipc/vfs.h>
 
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -30,5 +30,4 @@
 #define LIBC_IPC_DEV_IFACE_H_
 
-#include <ipc/ipc.h>
 #include <malloc.h>
 #include <unistd.h>
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/devman.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -30,17 +30,25 @@
  * @{
  */
- 
+
 #ifndef LIBC_IPC_DEVMAN_H_
 #define LIBC_IPC_DEVMAN_H_
 
+#include <ipc/common.h>
 #include <adt/list.h>
-#include <ipc/ipc.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <str.h>
+#include <malloc.h>
+#include <mem.h>
 
-#define DEVMAN_NAME_MAXLEN 256
+#define DEVMAN_NAME_MAXLEN  256
 
 typedef sysarg_t devman_handle_t;
+
+typedef enum {
+	/** Invalid value for debugging purposes */
+	fun_invalid = 0,
+	/** Function to which child devices attach */
+	fun_inner,
+	/** Fuction exported to external clients (leaf function) */
+	fun_exposed
+} fun_type_t;
 
 /** Ids of device models used for device-to-driver matching.
@@ -67,6 +75,5 @@
 } match_id_list_t;
 
-
-static inline match_id_t * create_match_id()
+static inline match_id_t *create_match_id(void)
 {
 	match_id_t *id = malloc(sizeof(match_id_t));
@@ -85,8 +92,8 @@
 }
 
-static inline void add_match_id(match_id_list_t *ids, match_id_t *id) 
+static inline void add_match_id(match_id_list_t *ids, match_id_t *id)
 {
 	match_id_t *mid = NULL;
-	link_t *link = ids->ids.next;	
+	link_t *link = ids->ids.next;
 	
 	while (link != &ids->ids) {
@@ -98,5 +105,5 @@
 	}
 	
-	list_insert_before(&id->link, link);	
+	list_insert_before(&id->link, link);
 }
 
@@ -129,5 +136,5 @@
 typedef enum {
 	DEVMAN_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
-	DEVMAN_ADD_CHILD_DEVICE,
+	DEVMAN_ADD_FUNCTION,
 	DEVMAN_ADD_MATCH_ID,
 	DEVMAN_ADD_DEVICE_TO_CLASS
Index: uspace/lib/c/include/ipc/devmap.h
===================================================================
--- uspace/lib/c/include/ipc/devmap.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/devmap.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,7 +34,5 @@
 #define DEVMAP_DEVMAP_H_
 
-#include <atomic.h>
-#include <ipc/ipc.h>
-#include <adt/list.h>
+#include <ipc/common.h>
 
 #define DEVMAP_NAME_MAXLEN  255
Index: uspace/lib/c/include/ipc/fb.h
===================================================================
--- uspace/lib/c/include/ipc/fb.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/fb.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -31,10 +31,10 @@
  */
 /** @file
- */ 
+ */
 
 #ifndef LIBC_FB_H_
 #define LIBC_FB_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 
 typedef enum {
Index: uspace/lib/c/include/ipc/icmp.h
===================================================================
--- uspace/lib/c/include/ipc/icmp.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/icmp.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,5 +33,5 @@
 /** @file
  * ICMP module messages.
- * @see icmp_interface.h
+ * @see icmp_remote.h
  */
 
@@ -39,18 +39,16 @@
 #define LIBC_ICMP_MESSAGES_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 #include <sys/types.h>
 #include <sys/time.h>
-
 #include <net/icmp_codes.h>
 
 /** ICMP module messages. */
 typedef enum {
-	/** Sends echo request. @see icmp_echo() */
+	/** Send echo request. @see icmp_echo() */
 	NET_ICMP_ECHO = NET_ICMP_FIRST,
 	
 	/**
-	 * Sends destination unreachable error message.
+	 * Send destination unreachable error message.
 	 * @see icmp_destination_unreachable_msg()
 	 */
@@ -58,5 +56,5 @@
 	
 	/**
-	 * Sends source quench error message.
+	 * Send source quench error message.
 	 * @see icmp_source_quench_msg()
 	 */
@@ -64,5 +62,5 @@
 	
 	/**
-	 * Sends time exceeded error message.
+	 * Send time exceeded error message.
 	 * @see icmp_time_exceeded_msg()
 	 */
@@ -70,12 +68,9 @@
 	
 	/**
-	 * Sends parameter problem error message.
+	 * Send parameter problem error message.
 	 * @see icmp_parameter_problem_msg()
 	 */
-	NET_ICMP_PARAMETERPROB,
-	
-	/** Initializes new connection. */
-	NET_ICMP_INIT
-} icmp_messages;
+	NET_ICMP_PARAMETERPROB
+} icmp_messages_t;
 
 /** @name ICMP specific message parameters definitions */
Index: uspace/lib/c/include/ipc/il.h
===================================================================
--- uspace/lib/c/include/ipc/il.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/il.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,5 +40,4 @@
 #define LIBC_IL_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
Index: uspace/lib/c/include/ipc/ip.h
===================================================================
--- uspace/lib/c/include/ipc/ip.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/ip.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,7 +39,5 @@
 #define LIBC_IP_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
-
 #include <net/in.h>
 #include <net/ip_codes.h>
Index: uspace/lib/c/include/ipc/ipc.h
===================================================================
--- uspace/lib/c/include/ipc/ipc.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/ipc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,23 +33,17 @@
  */
 
-#ifndef LIBIPC_IPC_H_
-#define LIBIPC_IPC_H_
-
+#if ((defined(LIBC_ASYNC_H_)) && (!defined(LIBC_ASYNC_C_)))
+	#error Do not intermix low-level IPC interface and async framework
+#endif
+
+#ifndef LIBC_IPC_H_
+#define LIBC_IPC_H_
+
+#include <sys/types.h>
+#include <ipc/common.h>
+#include <kernel/synch/synch.h>
 #include <task.h>
-#include <kernel/ipc/ipc.h>
-#include <kernel/ddi/irq.h>
-#include <sys/types.h>
-#include <kernel/synch/synch.h>
-
-#define IPC_FLAG_BLOCKING  0x01
-
-typedef struct {
-	sysarg_t args[IPC_CALL_LEN];
-	sysarg_t in_phone_hash;
-} ipc_call_t;
-
-typedef sysarg_t ipc_callid_t;
-
-typedef void (* ipc_async_callback_t)(void *, int, ipc_call_t *);
+
+typedef void (*ipc_async_callback_t)(void *, int, ipc_call_t *);
 
 /*
@@ -59,4 +53,5 @@
  * possible, the fast version is used.
  */
+
 #define ipc_call_sync_0_0(phoneid, method) \
 	ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0)
@@ -188,13 +183,11 @@
     sysarg_t *);
 
-extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, uint32_t, int);
-extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, uint32_t);
+extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, sysarg_t, unsigned int);
 extern void ipc_poke(void);
 
-static inline ipc_callid_t ipc_wait_for_call(ipc_call_t *data)
-{
-	return ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT);
-}
-
+#define ipc_wait_for_call(data) \
+	ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT);
+
+extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, sysarg_t);
 extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *);
 
@@ -205,4 +198,5 @@
  * to m.
  */
+
 #define ipc_answer_0(callid, retval) \
 	ipc_answer_fast((callid), (retval), 0, 0, 0, 0)
@@ -229,4 +223,5 @@
  * to m.
  */
+
 #define ipc_call_async_0(phoneid, method, private, callback, can_preempt) \
 	ipc_call_async_fast((phoneid), (method), 0, 0, 0, 0, (private), \
@@ -254,21 +249,24 @@
 
 extern void ipc_call_async_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, void *, ipc_async_callback_t, int);
+    sysarg_t, void *, ipc_async_callback_t, bool);
 extern void ipc_call_async_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, void *, ipc_async_callback_t, int);
-
-extern int ipc_connect_to_me(int, int, int, int, sysarg_t *);
-extern int ipc_connect_me_to(int, int, int, int);
-extern int ipc_connect_me_to_blocking(int, int, int, int);
+    sysarg_t, sysarg_t, void *, ipc_async_callback_t, bool);
+
+extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t *,
+    sysarg_t *);
+extern int ipc_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t);
+extern int ipc_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t);
+
 extern int ipc_hangup(int);
-extern int ipc_register_irq(int, int, int, irq_code_t *);
-extern int ipc_unregister_irq(int, int);
-extern int ipc_forward_fast(ipc_callid_t, int, int, sysarg_t, sysarg_t, int);
-extern int ipc_forward_slow(ipc_callid_t, int, int, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, sysarg_t, int);
+
+extern int ipc_forward_fast(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
+    unsigned int);
+extern int ipc_forward_slow(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, unsigned int);
 
 /*
  * User-friendly wrappers for ipc_share_in_start().
  */
+
 #define ipc_share_in_start_0_0(phoneid, dst, size) \
 	ipc_share_in_start((phoneid), (dst), (size), 0, NULL)
@@ -280,7 +278,7 @@
 	ipc_share_in_start((phoneid), (dst), (size), (arg), (flags))
 
-extern int ipc_share_in_start(int, void *, size_t, sysarg_t, int *);
-extern int ipc_share_in_finalize(ipc_callid_t, void *, int );
-extern int ipc_share_out_start(int, void *, int);
+extern int ipc_share_in_start(int, void *, size_t, sysarg_t, unsigned int *);
+extern int ipc_share_in_finalize(ipc_callid_t, void *, unsigned int);
+extern int ipc_share_out_start(int, void *, unsigned int);
 extern int ipc_share_out_finalize(ipc_callid_t, void *);
 extern int ipc_data_read_start(int, void *, size_t);
Index: uspace/lib/c/include/ipc/irc.h
===================================================================
--- uspace/lib/c/include/ipc/irc.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/irc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,5 @@
 #define LIBC_IRC_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 
 typedef enum {
Index: uspace/lib/c/include/ipc/kbd.h
===================================================================
--- uspace/lib/c/include/ipc/kbd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/kbd.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,5 +38,5 @@
 #define LIBC_IPC_KBD_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 #include <ipc/dev_iface.h>
 
Index: uspace/lib/c/include/ipc/loader.h
===================================================================
--- uspace/lib/c/include/ipc/loader.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/loader.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -31,10 +31,10 @@
  */
 /** @file
- */ 
+ */
 
 #ifndef LIBC_IPC_LOADER_H_
 #define LIBC_IPC_LOADER_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 
 typedef enum {
Index: uspace/lib/c/include/ipc/mouse.h
===================================================================
--- uspace/lib/c/include/ipc/mouse.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/mouse.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,5 +37,5 @@
 #define LIBC_IPC_MOUSE_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 
 typedef enum {
Index: uspace/lib/c/include/ipc/net.h
===================================================================
--- uspace/lib/c/include/ipc/net.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/net.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,7 +38,5 @@
 #define LIBC_NET_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <net/packet.h>
Index: uspace/lib/c/include/ipc/net_net.h
===================================================================
--- uspace/lib/c/include/ipc/net_net.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/net_net.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
 #define LIBC_NET_NET_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
Index: uspace/lib/c/include/ipc/netif.h
===================================================================
--- uspace/lib/c/include/ipc/netif.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/netif.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,5 +38,4 @@
 #define LIBC_NETIF_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
Index: uspace/lib/c/include/ipc/nil.h
===================================================================
--- uspace/lib/c/include/ipc/nil.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/nil.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,5 +38,4 @@
 #define LIBC_NIL_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
Index: uspace/lib/c/include/ipc/ns.h
===================================================================
--- uspace/lib/c/include/ipc/ns.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/ns.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,8 +33,9 @@
  */
 
-#ifndef LIBIPC_NS_H_
-#define LIBIPC_NS_H_
+#ifndef LIBC_NS_H_
+#define LIBC_NS_H_
 
-#include <ipc/ipc.h>
+#include <sys/types.h>
+#include <ipc/common.h>
 
 typedef enum {
@@ -45,4 +46,8 @@
 } ns_request_t;
 
+extern int service_register(sysarg_t);
+extern int service_connect(sysarg_t, sysarg_t, sysarg_t);
+extern int service_connect_blocking(sysarg_t, sysarg_t, sysarg_t);
+
 #endif
 
Index: uspace/lib/c/include/ipc/packet.h
===================================================================
--- uspace/lib/c/include/ipc/packet.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/packet.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,5 +38,4 @@
 #define LIBC_PACKET_MESSAGES_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/services.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,6 +35,6 @@
  */
 
-#ifndef LIBIPC_SERVICES_H_
-#define LIBIPC_SERVICES_H_
+#ifndef LIBC_SERVICES_H_
+#define LIBC_SERVICES_H_
 
 typedef enum {
@@ -66,8 +66,4 @@
 } services_t;
 
-/* Memory area to be received from NS */
-#define SERVICE_MEM_REALTIME    1
-#define SERVICE_MEM_KLOG        2
-
 #endif
 
Index: uspace/lib/c/include/ipc/socket.h
===================================================================
--- uspace/lib/c/include/ipc/socket.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/socket.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,5 +38,4 @@
 #define LIBC_SOCKET_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
Index: uspace/lib/c/include/ipc/tl.h
===================================================================
--- uspace/lib/c/include/ipc/tl.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/tl.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
 #define LIBC_TL_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
Index: uspace/lib/c/include/ipc/vfs.h
===================================================================
--- uspace/lib/c/include/ipc/vfs.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/ipc/vfs.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,5 @@
 #define LIBC_IPC_VFS_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 #include <sys/types.h>
 #include <bool.h>
Index: uspace/lib/c/include/l18n/langs.h
===================================================================
--- uspace/lib/c/include/l18n/langs.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/c/include/l18n/langs.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * 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 libc
+ * @{
+ */
+/** @file
+ * Language and locale ids.
+ */
+
+#ifndef LIBC_L18N_LANGS_H_
+#define LIBC_L18N_LANGS_H_
+
+/** Windows locale IDs.
+ * Codes taken from
+ * Developing International Software For Windows 95 and Windows NT
+ * by Nadine Kano (Microsoft Press).
+ * FIXME: add missing codes.
+ */
+typedef enum {
+	L18N_WIN_LOCALE_AFRIKAANS = 0x0436,
+	/* ... */
+	L18N_WIN_LOCALE_CZECH = 0x0405,
+	/* ... */
+	L18N_WIN_LOCALE_ENGLISH_UNITED_STATES = 0x0409,
+	/* ... */
+	L18N_WIN_LOCALE_SLOVAK = 0x041B,
+	/* ... */
+	L18N_WIN_LOCALE_SPANISH_TRADITIONAL = 0x040A,
+	/* ... */
+	L18N_WIN_LOCALE_ZULU = 0x0435
+} l18_win_locales_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/libc.h
===================================================================
--- uspace/lib/c/include/libc.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/libc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -62,7 +62,4 @@
 	__syscall6(p1, p2, p3, p4, p5, p6, id)
 
-extern void __main(void *pcb_ptr);
-extern void __exit(void);
-
 #endif
 
Index: uspace/lib/c/include/loader/pcb.h
===================================================================
--- uspace/lib/c/include/loader/pcb.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/loader/pcb.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -52,5 +52,5 @@
 	/** Program entry point. */
 	entry_point_t entry;
-
+	
 	/** Current working directory. */
 	char *cwd;
Index: uspace/lib/c/include/malloc.h
===================================================================
--- uspace/lib/c/include/malloc.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/malloc.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,7 +38,4 @@
 #include <sys/types.h>
 
-extern void __heap_init(void);
-extern uintptr_t get_max_heap_addr(void);
-
 extern void *malloc(const size_t size)
     __attribute__((malloc));
Index: uspace/lib/c/include/net/icmp_common.h
===================================================================
--- uspace/lib/c/include/net/icmp_common.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/net/icmp_common.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,8 +41,8 @@
 #include <sys/time.h>
 
-/** Default timeout for incoming connections in microseconds. */
-#define ICMP_CONNECT_TIMEOUT	(1 * 1000 * 1000)
+/** Default timeout for incoming connections in microseconds (1 sec). */
+#define ICMP_CONNECT_TIMEOUT  1000000
 
-extern int icmp_connect_module(services_t, suseconds_t);
+extern int icmp_connect_module(suseconds_t);
 
 #endif
Index: uspace/lib/c/include/net/modules.h
===================================================================
--- uspace/lib/c/include/net/modules.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/net/modules.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -43,8 +43,5 @@
 
 #include <async.h>
-
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <sys/time.h>
 
Index: uspace/lib/c/include/setjmp.h
===================================================================
--- uspace/lib/c/include/setjmp.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/setjmp.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,5 +41,5 @@
 
 extern int setjmp(jmp_buf env);
-extern void longjmp(jmp_buf env,int val) __attribute__((__noreturn__));
+extern void longjmp(jmp_buf env, int val) __attribute__((noreturn));
 
 #endif
Index: uspace/lib/c/include/stdlib.h
===================================================================
--- uspace/lib/c/include/stdlib.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/stdlib.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,29 +40,13 @@
 #include <stacktrace.h>
 
-#define abort() \
-	do { \
-		stacktrace_print(); \
-		_exit(1); \
-	} while (0)
+#define RAND_MAX  714025
 
-#define core() \
-	*((int *) 0) = 0xbadbad;
-
-#define exit(status)  _exit((status))
-
-#define RAND_MAX  714025
+#define rand()       random()
+#define srand(seed)  srandom(seed)
 
 extern long int random(void);
 extern void srandom(unsigned int seed);
 
-static inline int rand(void)
-{
-	return random();
-}
-
-static inline void srand(unsigned int seed)
-{
-	srandom(seed);
-}
+extern void abort(void) __attribute__((noreturn));
 
 #endif
Index: uspace/lib/c/include/syscall.h
===================================================================
--- uspace/lib/c/include/syscall.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/syscall.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -32,7 +32,7 @@
 /**
  * @file
- * @brief	Syscall function declaration for architectures that don't
- *		inline syscalls or architectures that handle syscalls
- *		according to the number of arguments.
+ * @brief Syscall function declaration for architectures that don't
+ *        inline syscalls or architectures that handle syscalls
+ *        according to the number of arguments.
  */
 
@@ -40,6 +40,6 @@
 #define LIBC_SYSCALL_H_
 
-#ifndef	LIBARCH_SYSCALL_GENERIC
-#error "You can't include this file directly."
+#ifndef LIBARCH_SYSCALL_GENERIC
+	#error You cannot include this file directly
 #endif
 
@@ -47,11 +47,11 @@
 #include <kernel/syscall/syscall.h>
 
-#define __syscall0	__syscall
-#define __syscall1	__syscall
-#define __syscall2	__syscall
-#define __syscall3	__syscall
-#define __syscall4	__syscall
-#define __syscall5	__syscall
-#define __syscall6	__syscall
+#define __syscall0  __syscall
+#define __syscall1  __syscall
+#define __syscall2  __syscall
+#define __syscall3  __syscall
+#define __syscall4  __syscall
+#define __syscall5  __syscall
+#define __syscall6  __syscall
 
 extern sysarg_t __syscall(const sysarg_t p1, const sysarg_t p2,
Index: uspace/lib/c/include/thread.h
===================================================================
--- uspace/lib/c/include/thread.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/thread.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
 #define LIBC_THREAD_H_
 
-#include <kernel/proc/uarg.h>
 #include <libarch/thread.h>
 #include <sys/types.h>
@@ -42,9 +41,6 @@
 typedef uint64_t thread_id_t;
 
-extern void __thread_entry(void);
-extern void __thread_main(uspace_arg_t *);
-
 extern int thread_create(void (*)(void *), void *, const char *, thread_id_t *);
-extern void thread_exit(int) __attribute__ ((noreturn));
+extern void thread_exit(int) __attribute__((noreturn));
 extern void thread_detach(thread_id_t);
 extern int thread_join(thread_id_t);
Index: uspace/lib/c/include/tls.h
===================================================================
--- uspace/lib/c/include/tls.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/tls.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -57,4 +57,5 @@
 extern void tls_free_variant_1(tcb_t *, size_t);
 #endif
+
 #ifdef CONFIG_TLS_VARIANT_2
 extern tcb_t *tls_alloc_variant_2(void **, size_t);
Index: uspace/lib/c/include/udebug.h
===================================================================
--- uspace/lib/c/include/udebug.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/udebug.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,23 +38,18 @@
 #include <kernel/udebug/udebug.h>
 #include <sys/types.h>
-#include <libarch/types.h>
 
 typedef sysarg_t thash_t;
 
-int udebug_begin(int phoneid);
-int udebug_end(int phoneid);
-int udebug_set_evmask(int phoneid, udebug_evmask_t mask);
-int udebug_thread_read(int phoneid, void *buffer, size_t n,
-	size_t *copied, size_t *needed);
-int udebug_name_read(int phoneid, void *buffer, size_t n,
-	size_t *copied, size_t *needed);
-int udebug_areas_read(int phoneid, void *buffer, size_t n,
-	size_t *copied, size_t *needed);
-int udebug_mem_read(int phoneid, void *buffer, uintptr_t addr, size_t n);
-int udebug_args_read(int phoneid, thash_t tid, sysarg_t *buffer);
-int udebug_regs_read(int phoneid, thash_t tid, void *buffer);
-int udebug_go(int phoneid, thash_t tid, udebug_event_t *ev_type,
-	sysarg_t *val0, sysarg_t *val1);
-int udebug_stop(int phoneid, thash_t tid);
+int udebug_begin(int);
+int udebug_end(int);
+int udebug_set_evmask(int, udebug_evmask_t);
+int udebug_thread_read(int, void *, size_t , size_t *, size_t *);
+int udebug_name_read(int, void *, size_t, size_t *, size_t *);
+int udebug_areas_read(int, void *, size_t, size_t *, size_t *);
+int udebug_mem_read(int, void *, uintptr_t, size_t);
+int udebug_args_read(int, thash_t, sysarg_t *);
+int udebug_regs_read(int, thash_t, void *);
+int udebug_go(int, thash_t, udebug_event_t *, sysarg_t *, sysarg_t *);
+int udebug_stop(int, thash_t);
 
 #endif
Index: uspace/lib/c/include/unistd.h
===================================================================
--- uspace/lib/c/include/unistd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/unistd.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,8 +41,6 @@
 
 #ifndef NULL
-	#define NULL	((void *) 0)
+	#define NULL  ((void *) 0)
 #endif
-
-#define getpagesize()  (PAGE_SIZE)
 
 #ifndef SEEK_SET
@@ -57,4 +55,6 @@
 	#define SEEK_END  2
 #endif
+
+#define getpagesize()  (PAGE_SIZE)
 
 extern int dup2(int oldfd, int newfd);
@@ -74,5 +74,5 @@
 extern int chdir(const char *);
 
-extern void _exit(int) __attribute__((noreturn));
+extern void exit(int) __attribute__((noreturn));
 extern int usleep(useconds_t);
 extern unsigned int sleep(unsigned int);
Index: uspace/lib/c/include/vfs/vfs.h
===================================================================
--- uspace/lib/c/include/vfs/vfs.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/c/include/vfs/vfs.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -57,7 +57,4 @@
 extern int unmount(const char *);
 
-extern void __stdio_init(int filc, fdi_node_t *filv[]);
-extern void __stdio_done(void);
-
 extern int open_node(fdi_node_t *, int);
 extern int fd_phone(int);
Index: uspace/lib/clui/tinput.h
===================================================================
--- uspace/lib/clui/tinput.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/clui/tinput.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,6 +36,4 @@
 #ifndef LIBCLUI_TINPUT_H_
 #define LIBCLUI_TINPUT_H_
-
-#include <ipc/ipc.h>
 
 #define HISTORY_LEN     10
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/drv/generic/driver.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -49,9 +50,11 @@
 #include <errno.h>
 #include <inttypes.h>
+#include <devman.h>
 
 #include <ipc/driver.h>
 
 #include "dev_iface.h"
-#include "driver.h"
+#include "ddf/driver.h"
+#include "ddf/interrupt.h"
 
 /** Driver structure */
@@ -59,6 +62,6 @@
 
 /** Devices */
-LIST_INITIALIZE(devices);
-FIBRIL_MUTEX_INITIALIZE(devices_mutex);
+LIST_INITIALIZE(functions);
+FIBRIL_MUTEX_INITIALIZE(functions_mutex);
 
 /** Interrupts */
@@ -76,4 +79,8 @@
 };
 
+static ddf_dev_t *create_device(void);
+static void delete_device(ddf_dev_t *);
+static remote_handler_t *function_get_default_handler(ddf_fun_t *);
+static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t);
 
 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall)
@@ -150,5 +157,5 @@
 
 interrupt_context_t *
-find_interrupt_context(interrupt_context_list_t *list, device_t *dev, int irq)
+find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
 {
 	fibril_mutex_lock(&list->mutex);
@@ -172,5 +179,5 @@
 
 int
-register_interrupt_handler(device_t *dev, int irq, interrupt_handler_t *handler,
+register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler,
     irq_code_t *pseudocode)
 {
@@ -186,5 +193,5 @@
 		pseudocode = &default_pseudocode;
 	
-	int res = ipc_register_irq(irq, dev->handle, ctx->id, pseudocode);
+	int res = register_irq(irq, dev->handle, ctx->id, pseudocode);
 	if (res != EOK) {
 		remove_interrupt_context(&interrupt_contexts, ctx);
@@ -195,9 +202,9 @@
 }
 
-int unregister_interrupt_handler(device_t *dev, int irq)
+int unregister_interrupt_handler(ddf_dev_t *dev, int irq)
 {
 	interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
 	    dev, irq);
-	int res = ipc_unregister_irq(irq, dev->handle);
+	int res = unregister_irq(irq, dev->handle);
 	
 	if (ctx != NULL) {
@@ -209,35 +216,36 @@
 }
 
-static void add_to_devices_list(device_t *dev)
-{
-	fibril_mutex_lock(&devices_mutex);
-	list_append(&dev->link, &devices);
-	fibril_mutex_unlock(&devices_mutex);
-}
-
-static void remove_from_devices_list(device_t *dev)
-{
-	fibril_mutex_lock(&devices_mutex);
-	list_remove(&dev->link);
-	fibril_mutex_unlock(&devices_mutex);
-}
-
-static device_t *driver_get_device(link_t *devices, devman_handle_t handle)
-{
-	device_t *dev = NULL;
-	
-	fibril_mutex_lock(&devices_mutex);
-	link_t *link = devices->next;
-	
-	while (link != devices) {
-		dev = list_get_instance(link, device_t, link);
-		if (dev->handle == handle) {
-			fibril_mutex_unlock(&devices_mutex);
-			return dev;
+static void add_to_functions_list(ddf_fun_t *fun)
+{
+	fibril_mutex_lock(&functions_mutex);
+	list_append(&fun->link, &functions);
+	fibril_mutex_unlock(&functions_mutex);
+}
+
+static void remove_from_functions_list(ddf_fun_t *fun)
+{
+	fibril_mutex_lock(&functions_mutex);
+	list_remove(&fun->link);
+	fibril_mutex_unlock(&functions_mutex);
+}
+
+static ddf_fun_t *driver_get_function(link_t *functions, devman_handle_t handle)
+{
+	ddf_fun_t *fun = NULL;
+	
+	fibril_mutex_lock(&functions_mutex);
+	link_t *link = functions->next;
+	
+	while (link != functions) {
+		fun = list_get_instance(link, ddf_fun_t, link);
+		if (fun->handle == handle) {
+			fibril_mutex_unlock(&functions_mutex);
+			return fun;
 		}
+		
 		link = link->next;
 	}
 	
-	fibril_mutex_unlock(&devices_mutex);
+	fibril_mutex_unlock(&functions_mutex);
 	
 	return NULL;
@@ -250,14 +258,17 @@
 	
 	devman_handle_t dev_handle = IPC_GET_ARG1(*icall);
-    	devman_handle_t parent_dev_handle = IPC_GET_ARG2(*icall);
-	
-	device_t *dev = create_device();
+    	devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);
+	
+	ddf_dev_t *dev = create_device();
 	dev->handle = dev_handle;
-	
+
 	async_data_write_accept((void **) &dev_name, true, 0, 0, 0, 0);
 	dev->name = dev_name;
-	
-	add_to_devices_list(dev);
-	dev->parent = driver_get_device(&devices, parent_dev_handle);
+
+	/*
+	 * Currently not used, parent fun handle is stored in context
+	 * of the connection to the parent device driver.
+	 */
+	(void) parent_fun_handle;
 	
 	res = driver->driver_ops->add_device(dev);
@@ -268,9 +279,8 @@
 		printf("%s: failed to add a new device with handle = %" PRIun ".\n",
 		    driver->name, dev_handle);
-		remove_from_devices_list(dev);
 		delete_device(dev);
 	}
 	
-	ipc_answer_0(iid, res);
+	async_answer_0(iid, res);
 }
 
@@ -278,5 +288,5 @@
 {
 	/* Accept connection */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	bool cont = true;
@@ -293,5 +303,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOENT);
+			async_answer_0(callid, ENOENT);
 		}
 	}
@@ -311,10 +321,10 @@
 	 */
 	devman_handle_t handle = IPC_GET_ARG2(*icall);
-	device_t *dev = driver_get_device(&devices, handle);
-
-	if (dev == NULL) {
-		printf("%s: driver_connection_gen error - no device with handle"
+	ddf_fun_t *fun = driver_get_function(&functions, handle);
+
+	if (fun == NULL) {
+		printf("%s: driver_connection_gen error - no function with handle"
 		    " %" PRIun " was found.\n", driver->name, handle);
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
@@ -327,9 +337,9 @@
 	
 	int ret = EOK;
-	/* open the device */
-	if (dev->ops != NULL && dev->ops->open != NULL)
-		ret = (*dev->ops->open)(dev);
-	
-	ipc_answer_0(iid, ret);
+	/* Open device function */
+	if (fun->ops != NULL && fun->ops->open != NULL)
+		ret = (*fun->ops->open)(fun);
+	
+	async_answer_0(iid, ret);
 	if (ret != EOK)
 		return;
@@ -344,8 +354,8 @@
 		switch  (method) {
 		case IPC_M_PHONE_HUNGUP:
-			/* close the device */
-			if (dev->ops != NULL && dev->ops->close != NULL)
-				(*dev->ops->close)(dev);
-			ipc_answer_0(callid, EOK);
+			/* Close device function */
+			if (fun->ops != NULL && fun->ops->close != NULL)
+				(*fun->ops->close)(fun);
+			async_answer_0(callid, EOK);
 			return;
 		default:
@@ -356,11 +366,12 @@
 			if (!is_valid_iface_idx(iface_idx)) {
 				remote_handler_t *default_handler =
-				    device_get_default_handler(dev);
+				    function_get_default_handler(fun);
 				if (default_handler != NULL) {
-					(*default_handler)(dev, callid, &call);
+					(*default_handler)(fun, callid, &call);
 					break;
 				}
+				
 				/*
-				 * This is not device's interface and the
+				 * Function has no such interface and
 				 * default handler is not provided.
 				 */
@@ -368,18 +379,18 @@
 				    "invalid interface id %d.",
 				    driver->name, iface_idx);
-				ipc_answer_0(callid, ENOTSUP);
+				async_answer_0(callid, ENOTSUP);
 				break;
 			}
 			
-			/* calling one of the device's interfaces */
+			/* calling one of the function's interfaces */
 			
 			/* Get the interface ops structure. */
-			void *ops = device_get_ops(dev, iface_idx);
+			void *ops = function_get_ops(fun, iface_idx);
 			if (ops == NULL) {
 				printf("%s: driver_connection_gen error - ",
 				    driver->name);
-				printf("device with handle %" PRIun " has no interface "
+				printf("Function with handle %" PRIun " has no interface "
 				    "with id %d.\n", handle, iface_idx);
-				ipc_answer_0(callid, ENOTSUP);
+				async_answer_0(callid, ENOTSUP);
 				break;
 			}
@@ -400,5 +411,5 @@
 				printf("%s: driver_connection_gen error - "
 				    "invalid interface method.", driver->name);
-				ipc_answer_0(callid, ENOTSUP);
+				async_answer_0(callid, ENOTSUP);
 				break;
 			}
@@ -408,7 +419,7 @@
 			 * receive parameters from the remote client and it will
 			 * pass it to the corresponding local interface method
-			 * associated with the device by its driver.
+			 * associated with the function by its driver.
 			 */
-			(*iface_method_ptr)(dev, ops, callid, &call);
+			(*iface_method_ptr)(fun, ops, callid, &call);
 			break;
 		}
@@ -425,5 +436,4 @@
 	driver_connection_gen(iid, icall, false);
 }
-
 
 /** Function for handling connections to device driver. */
@@ -446,5 +456,5 @@
 	default:
 		/* No such interface */
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 	}
 }
@@ -454,125 +464,200 @@
  * @return		The device structure.
  */
-device_t *create_device(void)
-{
-	device_t *dev = malloc(sizeof(device_t));
-
-	if (dev != NULL) {
-		memset(dev, 0, sizeof(device_t));
-		init_match_ids(&dev->match_ids);
-	}
-
+static ddf_dev_t *create_device(void)
+{
+	ddf_dev_t *dev;
+
+	dev = malloc(sizeof(ddf_dev_t));
+	if (dev == NULL)
+		return NULL;
+
+	memset(dev, 0, sizeof(ddf_dev_t));
 	return dev;
 }
 
+/** Create new function structure.
+ *
+ * @return		The device structure.
+ */
+static ddf_fun_t *create_function(void)
+{
+	ddf_fun_t *fun;
+
+	fun = calloc(1, sizeof(ddf_fun_t));
+	if (fun == NULL)
+		return NULL;
+
+	init_match_ids(&fun->match_ids);
+	link_initialize(&fun->link);
+
+	return fun;
+}
+
 /** Delete device structure.
  *
  * @param dev		The device structure.
  */
-void delete_device(device_t *dev)
-{
-	clean_match_ids(&dev->match_ids);
-	if (dev->name != NULL)
-		free(dev->name);
+static void delete_device(ddf_dev_t *dev)
+{
 	free(dev);
 }
 
-void *device_get_ops(device_t *dev, dev_inferface_idx_t idx)
+/** Delete device structure.
+ *
+ * @param dev		The device structure.
+ */
+static void delete_function(ddf_fun_t *fun)
+{
+	clean_match_ids(&fun->match_ids);
+	if (fun->name != NULL)
+		free(fun->name);
+	free(fun);
+}
+
+/** Create a DDF function node.
+ *
+ * Create a DDF function (in memory). Both child devices and external clients
+ * communicate with a device via its functions.
+ *
+ * The created function node is fully formed, but only exists in the memory
+ * of the client task. In order to be visible to the system, the function
+ * must be bound using ddf_fun_bind().
+ *
+ * This function should only fail if there is not enough free memory.
+ * Specifically, this function succeeds even if @a dev already has
+ * a (bound) function with the same name.
+ *
+ * Type: A function of type fun_inner indicates that DDF should attempt
+ * to attach child devices to the function. fun_exposed means that
+ * the function should be exported to external clients (applications).
+ *
+ * @param dev		Device to which we are adding function
+ * @param ftype		Type of function (fun_inner or fun_exposed)
+ * @param name		Name of function
+ *
+ * @return		New function or @c NULL if memory is not available
+ */
+ddf_fun_t *ddf_fun_create(ddf_dev_t *dev, fun_type_t ftype, const char *name)
+{
+	ddf_fun_t *fun;
+
+	fun = create_function();
+	if (fun == NULL)
+		return NULL;
+
+	fun->bound = false;
+	fun->dev = dev;
+	fun->ftype = ftype;
+
+	fun->name = str_dup(name);
+	if (fun->name == NULL) {
+		delete_function(fun);
+		return NULL;
+	}
+
+	return fun;
+}
+
+/** Destroy DDF function node.
+ *
+ * Destroy a function previously created with ddf_fun_create(). The function
+ * must not be bound.
+ *
+ * @param fun		Function to destroy
+ */
+void ddf_fun_destroy(ddf_fun_t *fun)
+{
+	assert(fun->bound == false);
+	delete_function(fun);
+}
+
+static void *function_get_ops(ddf_fun_t *fun, dev_inferface_idx_t idx)
 {
 	assert(is_valid_iface_idx(idx));
-	if (dev->ops == NULL)
+	if (fun->ops == NULL)
 		return NULL;
-	return dev->ops->interfaces[idx];
-}
-
-int child_device_register(device_t *child, device_t *parent)
-{
-	assert(child->name != NULL);
+	return fun->ops->interfaces[idx];
+}
+
+/** Bind a function node.
+ *
+ * Bind the specified function to the system. This effectively makes
+ * the function visible to the system (uploads it to the server).
+ *
+ * This function can fail for several reasons. Specifically,
+ * it will fail if the device already has a bound function of
+ * the same name.
+ *
+ * @param fun		Function to bind
+ * @return		EOK on success or negative error code
+ */
+int ddf_fun_bind(ddf_fun_t *fun)
+{
+	assert(fun->name != NULL);
 	
 	int res;
 	
-	add_to_devices_list(child);
-	res = devman_child_device_register(child->name, &child->match_ids,
-	    parent->handle, &child->handle);
+	add_to_functions_list(fun);
+	res = devman_add_function(fun->name, fun->ftype, &fun->match_ids,
+	    fun->dev->handle, &fun->handle);
 	if (res != EOK) {
-		remove_from_devices_list(child);
+		remove_from_functions_list(fun);
 		return res;
 	}
 	
+	fun->bound = true;
 	return res;
 }
 
-/** Wrapper for child_device_register for devices with single match id.
- *
- * @param parent Parent device.
- * @param child_name Child device name.
- * @param child_match_id Child device match id.
- * @param child_match_score Child device match score.
- * @return Error code.
- */
-int child_device_register_wrapper(device_t *parent, const char *child_name,
-    const char *child_match_id, int child_match_score,
-    devman_handle_t *child_handle)
-{
-	device_t *child = NULL;
-	match_id_t *match_id = NULL;
-	int rc;
-	
-	child = create_device();
-	if (child == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-	
-	child->name = child_name;
+/** Add single match ID to inner function.
+ *
+ * Construct and add a single match ID to the specified function.
+ * Cannot be called when the function node is bound.
+ *
+ * @param fun			Function
+ * @param match_id_str		Match string
+ * @param match_score		Match score
+ * @return			EOK on success, ENOMEM if out of memory.
+ */
+int ddf_fun_add_match_id(ddf_fun_t *fun, const char *match_id_str,
+    int match_score)
+{
+	match_id_t *match_id;
+	
+	assert(fun->bound == false);
+	assert(fun->ftype == fun_inner);
 	
 	match_id = create_match_id();
-	if (match_id == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-	
-	match_id->id = child_match_id;
-	match_id->score = child_match_score;
-	add_match_id(&child->match_ids, match_id);
-	
-	rc = child_device_register(child, parent);
-	if (rc != EOK)
-		goto failure;
-
-	if (child_handle != NULL) {
-		*child_handle = child->handle;
-	}
-
+	if (match_id == NULL)
+		return ENOMEM;
+	
+	match_id->id = match_id_str;
+	match_id->score = 90;
+	
+	add_match_id(&fun->match_ids, match_id);
 	return EOK;
-	
-failure:
-	if (match_id != NULL) {
-		match_id->id = NULL;
-		delete_match_id(match_id);
-	}
-	
-	if (child != NULL) {
-		child->name = NULL;
-		delete_device(child);
-	}
-	
-	return rc;
 }
 
 /** Get default handler for client requests */
-remote_handler_t *device_get_default_handler(device_t *dev)
-{
-	if (dev->ops == NULL)
+static remote_handler_t *function_get_default_handler(ddf_fun_t *fun)
+{
+	if (fun->ops == NULL)
 		return NULL;
-	return dev->ops->default_handler;
-}
-
-int add_device_to_class(device_t *dev, const char *class_name)
-{
-	return devman_add_device_to_class(dev->handle, class_name);
-}
-
-int driver_main(driver_t *drv)
+	return fun->ops->default_handler;
+}
+
+/** Add exposed function to class.
+ *
+ * Must only be called when the function is bound.
+ */
+int ddf_fun_add_to_class(ddf_fun_t *fun, const char *class_name)
+{
+	assert(fun->bound == true);
+	assert(fun->ftype == fun_exposed);
+	
+	return devman_add_device_to_class(fun->handle, class_name);
+}
+
+int ddf_driver_main(driver_t *drv)
 {
 	/*
Index: uspace/lib/drv/generic/remote_char_dev.c
===================================================================
--- uspace/lib/drv/generic/remote_char_dev.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/drv/generic/remote_char_dev.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,15 +33,14 @@
  */
 
-#include <ipc/ipc.h>
 #include <async.h>
 #include <errno.h>
 
 #include "ops/char_dev.h"
-#include "driver.h"
+#include "ddf/driver.h"
 
 #define MAX_CHAR_RW_COUNT 256
 
-static void remote_char_read(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_char_write(device_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_char_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_char_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 
 /** Remote character interface operations. */
@@ -68,9 +67,9 @@
  * local interface to the remote client.
  *
- * @param dev		The device from which the data are read.
+ * @param fun		The function from which the data are read.
  * @param ops		The local ops structure.
  */
 static void
-remote_char_read(device_t *dev, void *ops, ipc_callid_t callid,
+remote_char_read(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
     ipc_call_t *call)
 {
@@ -81,5 +80,5 @@
 	if (!async_data_read_receive(&cid, &len)) {
 		/* TODO handle protocol error. */
-		ipc_answer_0(callid, EINVAL);
+		async_answer_0(callid, EINVAL);
 		return;
 	}
@@ -87,5 +86,5 @@
 	if (!char_dev_ops->read) {
 		async_data_read_finalize(cid, NULL, 0);
-		ipc_answer_0(callid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 		return;
 	}
@@ -95,10 +94,10 @@
 	
 	char buf[MAX_CHAR_RW_COUNT];
-	int ret = (*char_dev_ops->read)(dev, buf, len);
+	int ret = (*char_dev_ops->read)(fun, buf, len);
 	
 	if (ret < 0) {
 		/* Some error occured. */
 		async_data_read_finalize(cid, buf, 0);
-		ipc_answer_0(callid, ret);
+		async_answer_0(callid, ret);
 		return;
 	}
@@ -106,5 +105,5 @@
 	/* The operation was successful, return the number of data read. */
 	async_data_read_finalize(cid, buf, ret);
-	ipc_answer_1(callid, EOK, ret);
+	async_answer_1(callid, EOK, ret);
 }
 
@@ -115,9 +114,9 @@
  * local interface to the remote client.
  *
- * @param dev		The device to which the data are written.
+ * @param fun		The function to which the data are written.
  * @param ops		The local ops structure.
  */
 static void
-remote_char_write(device_t *dev, void *ops, ipc_callid_t callid,
+remote_char_write(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
     ipc_call_t *call)
 {
@@ -128,5 +127,5 @@
 	if (!async_data_write_receive(&cid, &len)) {
 		/* TODO handle protocol error. */
-		ipc_answer_0(callid, EINVAL);
+		async_answer_0(callid, EINVAL);
 		return;
 	}
@@ -134,5 +133,5 @@
 	if (!char_dev_ops->write) {
 		async_data_write_finalize(cid, NULL, 0);
-		ipc_answer_0(callid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 		return;
 	}
@@ -145,8 +144,8 @@
 	async_data_write_finalize(cid, buf, len);
 	
-	int ret = (*char_dev_ops->write)(dev, buf, len);
+	int ret = (*char_dev_ops->write)(fun, buf, len);
 	if (ret < 0) {
 		/* Some error occured. */
-		ipc_answer_0(callid, ret);
+		async_answer_0(callid, ret);
 	} else {
 		/*
@@ -154,5 +153,5 @@
 		 * written.
 		 */
-		ipc_answer_1(callid, EOK, ret);
+		async_answer_1(callid, EOK, ret);
 	}
 }
Index: uspace/lib/drv/generic/remote_hw_res.c
===================================================================
--- uspace/lib/drv/generic/remote_hw_res.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/drv/generic/remote_hw_res.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,14 +33,13 @@
  */
 
-#include <ipc/ipc.h>
 #include <async.h>
 #include <errno.h>
 
 #include "ops/hw_res.h"
-#include "driver.h"
+#include "ddf/driver.h"
 
-static void remote_hw_res_get_resource_list(device_t *, void *, ipc_callid_t,
+static void remote_hw_res_get_resource_list(ddf_fun_t *, void *, ipc_callid_t,
     ipc_call_t *);
-static void remote_hw_res_enable_interrupt(device_t *, void *, ipc_callid_t,
+static void remote_hw_res_enable_interrupt(ddf_fun_t *, void *, ipc_callid_t,
     ipc_call_t *);
 
@@ -56,5 +55,5 @@
 };
 
-static void remote_hw_res_enable_interrupt(device_t *dev, void *ops,
+static void remote_hw_res_enable_interrupt(ddf_fun_t *fun, void *ops,
     ipc_callid_t callid, ipc_call_t *call)
 {
@@ -62,12 +61,12 @@
 	
 	if (hw_res_ops->enable_interrupt == NULL)
-		ipc_answer_0(callid, ENOTSUP);
-	else if (hw_res_ops->enable_interrupt(dev))
-		ipc_answer_0(callid, EOK);
+		async_answer_0(callid, ENOTSUP);
+	else if (hw_res_ops->enable_interrupt(fun))
+		async_answer_0(callid, EOK);
 	else
-		ipc_answer_0(callid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
 }
 
-static void remote_hw_res_get_resource_list(device_t *dev, void *ops,
+static void remote_hw_res_get_resource_list(ddf_fun_t *fun, void *ops,
     ipc_callid_t callid, ipc_call_t *call)
 {
@@ -75,15 +74,15 @@
 
 	if (hw_res_ops->get_resource_list == NULL) {
-		ipc_answer_0(callid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 		return;
 	}
 	
-	hw_resource_list_t *hw_resources = hw_res_ops->get_resource_list(dev);
+	hw_resource_list_t *hw_resources = hw_res_ops->get_resource_list(fun);
 	if (hw_resources == NULL){
-		ipc_answer_0(callid, ENOENT);
+		async_answer_0(callid, ENOENT);
 		return;
 	}
 	
-	ipc_answer_1(callid, EOK, hw_resources->count);
+	async_answer_1(callid, EOK, hw_resources->count);
 
 	size_t len;
Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/drv/generic/remote_usb.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,17 +33,20 @@
  */
 
-#include <ipc/ipc.h>
 #include <async.h>
 #include <errno.h>
 
 #include "usb_iface.h"
-#include "driver.h"
+#include "ddf/driver.h"
 
 
-static void remote_usb_get_hc_handle(device_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_get_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_get_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 //static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);
 
 /** Remote USB interface operations. */
 static remote_iface_func_ptr_t remote_usb_iface_ops [] = {
+	remote_usb_get_address,
+	remote_usb_get_interface,
 	remote_usb_get_hc_handle
 };
@@ -58,5 +61,47 @@
 
 
-void remote_usb_get_hc_handle(device_t *device, void *iface,
+void remote_usb_get_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (usb_iface->get_address == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
+
+	usb_address_t address;
+	int rc = usb_iface->get_address(fun, handle, &address);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+	} else {
+		async_answer_1(callid, EOK, address);
+	}
+}
+
+void remote_usb_get_interface(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (usb_iface->get_interface == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
+
+	int iface_no;
+	int rc = usb_iface->get_interface(fun, handle, &iface_no);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+	} else {
+		async_answer_1(callid, EOK, iface_no);
+	}
+}
+
+void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
 {
@@ -64,15 +109,15 @@
 
 	if (usb_iface->get_hc_handle == NULL) {
-		ipc_answer_0(callid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 		return;
 	}
 
 	devman_handle_t handle;
-	int rc = usb_iface->get_hc_handle(device, &handle);
+	int rc = usb_iface->get_hc_handle(fun, &handle);
 	if (rc != EOK) {
-		ipc_answer_0(callid, rc);
+		async_answer_0(callid, rc);
 	}
 
-	ipc_answer_1(callid, EOK, (sysarg_t) handle);
+	async_answer_1(callid, EOK, (sysarg_t) handle);
 }
 
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2010-2011 Vojtech Horky
  * All rights reserved.
  *
@@ -33,36 +33,30 @@
  */
 
-#include <ipc/ipc.h>
 #include <async.h>
 #include <errno.h>
+#include <assert.h>
 
 #include "usbhc_iface.h"
-#include "driver.h"
+#include "ddf/driver.h"
 
 #define USB_MAX_PAYLOAD_SIZE 1020
-
-static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_get_buffer(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_control_write_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_control_write_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_control_write_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_control_read_setup(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_control_read_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_reserve_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_release_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_request_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_bind_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbhc_release_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
-//static void remote_usbhc(device_t *, void *, ipc_callid_t, ipc_call_t *);
+#define HACK_MAX_PACKET_SIZE 8
+#define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4
+
+static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 
 /** Remote USB host controller interface operations. */
 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
-	remote_usbhc_get_address,
-
-	remote_usbhc_get_buffer,
-
 	remote_usbhc_reserve_default_address,
 	remote_usbhc_release_default_address,
@@ -75,11 +69,9 @@
 	remote_usbhc_interrupt_in,
 
-	remote_usbhc_control_write_setup,
-	remote_usbhc_control_write_data,
-	remote_usbhc_control_write_status,
-
-	remote_usbhc_control_read_setup,
-	remote_usbhc_control_read_data,
-	remote_usbhc_control_read_status
+	remote_usbhc_bulk_out,
+	remote_usbhc_bulk_in,
+
+	remote_usbhc_control_write,
+	remote_usbhc_control_read
 };
 
@@ -94,112 +86,96 @@
 typedef struct {
 	ipc_callid_t caller;
+	ipc_callid_t data_caller;
 	void *buffer;
+	void *setup_packet;
 	size_t size;
 } async_transaction_t;
 
-void remote_usbhc_get_address(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-
-	if (!usb_iface->tell_address) {
-		ipc_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
+static void async_transaction_destroy(async_transaction_t *trans)
+{
+	if (trans == NULL) {
+		return;
+	}
+
+	if (trans->setup_packet != NULL) {
+		free(trans->setup_packet);
+	}
+	if (trans->buffer != NULL) {
+		free(trans->buffer);
+	}
+
+	free(trans);
+}
+
+static async_transaction_t *async_transaction_create(ipc_callid_t caller)
+{
+	async_transaction_t *trans = malloc(sizeof(async_transaction_t));
+	if (trans == NULL) {
+		return NULL;
+	}
+
+	trans->caller = caller;
+	trans->data_caller = 0;
+	trans->buffer = NULL;
+	trans->setup_packet = NULL;
+	trans->size = 0;
+
+	return trans;
+}
+
+void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->reserve_default_address) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
+	
+	int rc = usb_iface->reserve_default_address(fun, speed);
+
+	async_answer_0(callid, rc);
+}
+
+void remote_usbhc_release_default_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->release_default_address) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	int rc = usb_iface->release_default_address(fun);
+
+	async_answer_0(callid, rc);
+}
+
+void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->request_address) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
 
 	usb_address_t address;
-	int rc = usb_iface->tell_address(device, handle, &address);
-	if (rc != EOK) {
-		ipc_answer_0(callid, rc);
+	int rc = usb_iface->request_address(fun, speed, &address);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
 	} else {
-		ipc_answer_1(callid, EOK, address);
-	}
-}
-
-void remote_usbhc_get_buffer(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	sysarg_t buffer_hash = DEV_IPC_GET_ARG1(*call);
-	async_transaction_t * trans = (async_transaction_t *)buffer_hash;
-	if (trans == NULL) {
-		ipc_answer_0(callid, ENOENT);
-		return;
-	}
-	if (trans->buffer == NULL) {
-		ipc_answer_0(callid, EINVAL);
-		free(trans);
-		return;
-	}
-
-	ipc_callid_t cid;
-	size_t accepted_size;
-	if (!async_data_read_receive(&cid, &accepted_size)) {
-		ipc_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (accepted_size > trans->size) {
-		accepted_size = trans->size;
-	}
-	async_data_read_finalize(cid, trans->buffer, accepted_size);
-
-	ipc_answer_1(callid, EOK, accepted_size);
-
-	free(trans->buffer);
-	free(trans);
-}
-
-void remote_usbhc_reserve_default_address(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-
-	if (!usb_iface->reserve_default_address) {
-		ipc_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int rc = usb_iface->reserve_default_address(device);
-
-	ipc_answer_0(callid, rc);
-}
-
-void remote_usbhc_release_default_address(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-
-	if (!usb_iface->release_default_address) {
-		ipc_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int rc = usb_iface->release_default_address(device);
-
-	ipc_answer_0(callid, rc);
-}
-
-void remote_usbhc_request_address(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-
-	if (!usb_iface->request_address) {
-		ipc_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	usb_address_t address;
-	int rc = usb_iface->request_address(device, &address);
-	if (rc != EOK) {
-		ipc_answer_0(callid, rc);
-	} else {
-		ipc_answer_1(callid, EOK, (sysarg_t) address);
-	}
-}
-
-void remote_usbhc_bind_address(device_t *device, void *iface,
+		async_answer_1(callid, EOK, (sysarg_t) address);
+	}
+}
+
+void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
 {
@@ -207,5 +183,5 @@
 
 	if (!usb_iface->bind_address) {
-		ipc_answer_0(callid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 		return;
 	}
@@ -214,10 +190,10 @@
 	devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call);
 
-	int rc = usb_iface->bind_address(device, address, handle);
-
-	ipc_answer_0(callid, rc);
-}
-
-void remote_usbhc_release_address(device_t *device, void *iface,
+	int rc = usb_iface->bind_address(fun, address, handle);
+
+	async_answer_0(callid, rc);
+}
+
+void remote_usbhc_release_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
 {
@@ -225,5 +201,5 @@
 
 	if (!usb_iface->release_address) {
-		ipc_answer_0(callid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 		return;
 	}
@@ -231,30 +207,44 @@
 	usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
 
-	int rc = usb_iface->release_address(device, address);
-
-	ipc_answer_0(callid, rc);
-}
-
-
-static void callback_out(device_t *device,
-    usb_transaction_outcome_t outcome, void *arg)
+	int rc = usb_iface->release_address(fun, address);
+
+	async_answer_0(callid, rc);
+}
+
+
+static void callback_out(ddf_fun_t *fun,
+    int outcome, void *arg)
 {
 	async_transaction_t *trans = (async_transaction_t *)arg;
 
-	// FIXME - answer according to outcome
-	ipc_answer_0(trans->caller, EOK);
-
-	free(trans);
-}
-
-static void callback_in(device_t *device,
-    usb_transaction_outcome_t outcome, size_t actual_size, void *arg)
+	async_answer_0(trans->caller, outcome);
+
+	async_transaction_destroy(trans);
+}
+
+static void callback_in(ddf_fun_t *fun,
+    int outcome, size_t actual_size, void *arg)
 {
 	async_transaction_t *trans = (async_transaction_t *)arg;
 
-	// FIXME - answer according to outcome
-	ipc_answer_1(trans->caller, EOK, (sysarg_t)trans);
+	if (outcome != EOK) {
+		async_answer_0(trans->caller, outcome);
+		if (trans->data_caller) {
+			async_answer_0(trans->data_caller, EINTR);
+		}
+		async_transaction_destroy(trans);
+		return;
+	}
 
 	trans->size = actual_size;
+
+	if (trans->data_caller) {
+		async_data_read_finalize(trans->data_caller,
+		    trans->buffer, actual_size);
+	}
+
+	async_answer_0(trans->caller, EOK);
+
+	async_transaction_destroy(trans);
 }
 
@@ -266,14 +256,14 @@
  * @param transfer_func Transfer function (might be NULL).
  */
-static void remote_usbhc_out_transfer(device_t *device,
+static void remote_usbhc_out_transfer(ddf_fun_t *fun,
     ipc_callid_t callid, ipc_call_t *call,
     usbhc_iface_transfer_out_t transfer_func)
 {
 	if (!transfer_func) {
-		ipc_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	size_t expected_len = DEV_IPC_GET_ARG3(*call);
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
 	usb_target_t target = {
 		.address = DEV_IPC_GET_ARG1(*call),
@@ -283,29 +273,33 @@
 	size_t len = 0;
 	void *buffer = NULL;
-	if (expected_len > 0) {
-		int rc = async_data_write_accept(&buffer, false,
-		    1, USB_MAX_PAYLOAD_SIZE,
-		    0, &len);
-
-		if (rc != EOK) {
-			ipc_answer_0(callid, rc);
-			return;
-		}
-	}
-
-	async_transaction_t *trans = malloc(sizeof(async_transaction_t));
-	trans->caller = callid;
-	trans->buffer = buffer;
-	trans->size = len;
-
-	int rc = transfer_func(device, target, buffer, len,
-	    callback_out, trans);
-
-	if (rc != EOK) {
-		ipc_answer_0(callid, rc);
+
+	int rc = async_data_write_accept(&buffer, false,
+	    1, USB_MAX_PAYLOAD_SIZE,
+	    0, &len);
+
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	async_transaction_t *trans = async_transaction_create(callid);
+	if (trans == NULL) {
 		if (buffer != NULL) {
 			free(buffer);
 		}
-		free(trans);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	trans->buffer = buffer;
+	trans->size = len;
+
+	rc = transfer_func(fun, target, max_packet_size,
+	    buffer, len,
+	    callback_out, trans);
+
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_transaction_destroy(trans);
 	}
 }
@@ -318,14 +312,14 @@
  * @param transfer_func Transfer function (might be NULL).
  */
-static void remote_usbhc_in_transfer(device_t *device,
+static void remote_usbhc_in_transfer(ddf_fun_t *fun,
     ipc_callid_t callid, ipc_call_t *call,
     usbhc_iface_transfer_in_t transfer_func)
 {
 	if (!transfer_func) {
-		ipc_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	size_t len = DEV_IPC_GET_ARG3(*call);
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
 	usb_target_t target = {
 		.address = DEV_IPC_GET_ARG1(*call),
@@ -333,52 +327,79 @@
 	};
 
-	async_transaction_t *trans = malloc(sizeof(async_transaction_t));
-	trans->caller = callid;
+	size_t len;
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &len)) {
+		async_answer_0(callid, EPARTY);
+		return;
+	}
+
+	async_transaction_t *trans = async_transaction_create(callid);
+	if (trans == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+	trans->data_caller = data_callid;
 	trans->buffer = malloc(len);
 	trans->size = len;
 
-	int rc = transfer_func(device, target, trans->buffer, len,
+	int rc = transfer_func(fun, target, max_packet_size,
+	    trans->buffer, len,
 	    callback_in, trans);
 
 	if (rc != EOK) {
-		ipc_answer_0(callid, rc);
-		free(trans->buffer);
-		free(trans);
-	}
-}
-
-/** Process status part of control transfer.
- *
- * @param device Target device.
- * @param callid Initiating caller.
- * @param call Initiating call.
- * @param direction Transfer direction (read ~ in, write ~ out).
- * @param transfer_in_func Transfer function for control read (might be NULL).
- * @param transfer_out_func Transfer function for control write (might be NULL).
- */
-static void remote_usbhc_status_transfer(device_t *device,
-    ipc_callid_t callid, ipc_call_t *call,
-    usb_direction_t direction,
-    int (*transfer_in_func)(device_t *, usb_target_t,
-        usbhc_iface_transfer_in_callback_t, void *),
-    int (*transfer_out_func)(device_t *, usb_target_t,
-        usbhc_iface_transfer_out_callback_t, void *))
-{
-	switch (direction) {
-		case USB_DIRECTION_IN:
-			if (!transfer_in_func) {
-				ipc_answer_0(callid, ENOTSUP);
-				return;
-			}
-			break;
-		case USB_DIRECTION_OUT:
-			if (!transfer_out_func) {
-				ipc_answer_0(callid, ENOTSUP);
-				return;
-			}
-			break;
-		default:
-			assert(false && "unreachable code");
-			break;
+		async_answer_0(callid, rc);
+		async_transaction_destroy(trans);
+	}
+}
+
+void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	return remote_usbhc_out_transfer(fun, callid, call,
+	    usb_iface->interrupt_out);
+}
+
+void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	return remote_usbhc_in_transfer(fun, callid, call,
+	    usb_iface->interrupt_in);
+}
+
+void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	return remote_usbhc_out_transfer(fun, callid, call,
+	    usb_iface->bulk_out);
+}
+
+void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	return remote_usbhc_in_transfer(fun, callid, call,
+	    usb_iface->bulk_in);
+}
+
+void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,
+ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	if (!usb_iface->control_write) {
+		async_answer_0(callid, ENOTSUP);
+		return;
 	}
 
@@ -387,111 +408,115 @@
 		.endpoint = DEV_IPC_GET_ARG2(*call)
 	};
-
-	async_transaction_t *trans = malloc(sizeof(async_transaction_t));
-	trans->caller = callid;
-	trans->buffer = NULL;
-	trans->size = 0;
+	size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
+	size_t max_packet_size = DEV_IPC_GET_ARG4(*call);
 
 	int rc;
-	switch (direction) {
-		case USB_DIRECTION_IN:
-			rc = transfer_in_func(device, target,
-			    callback_in, trans);
-			break;
-		case USB_DIRECTION_OUT:
-			rc = transfer_out_func(device, target,
-			    callback_out, trans);
-			break;
-		default:
-			assert(false && "unreachable code");
-			break;
-	}
-
-	if (rc != EOK) {
-		ipc_answer_0(callid, rc);
-		free(trans);
-	}
-	return;
-}
-
-
-void remote_usbhc_interrupt_out(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
+
+	void *setup_packet = NULL;
+	void *data_buffer = NULL;
+	size_t setup_packet_len = 0;
+
+	rc = async_data_write_accept(&setup_packet, false,
+	    1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	if (data_buffer_len > 0) {
+		rc = async_data_write_accept(&data_buffer, false,
+		    1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
+		if (rc != EOK) {
+			async_answer_0(callid, rc);
+			free(setup_packet);
+			return;
+		}
+	}
+
+	async_transaction_t *trans = async_transaction_create(callid);
+	if (trans == NULL) {
+		async_answer_0(callid, ENOMEM);
+		free(setup_packet);
+		free(data_buffer);
+		return;
+	}
+	trans->setup_packet = setup_packet;
+	trans->buffer = data_buffer;
+	trans->size = data_buffer_len;
+
+	rc = usb_iface->control_write(fun, target, max_packet_size,
+	    setup_packet, setup_packet_len,
+	    data_buffer, data_buffer_len,
+	    callback_out, trans);
+
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_transaction_destroy(trans);
+	}
+}
+
+
+void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,
+ipc_callid_t callid, ipc_call_t *call)
 {
 	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
 	assert(usb_iface != NULL);
 
-	return remote_usbhc_out_transfer(device, callid, call,
-	    usb_iface->interrupt_out);
-}
-
-void remote_usbhc_interrupt_in(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-	assert(usb_iface != NULL);
-
-	return remote_usbhc_in_transfer(device, callid, call,
-	    usb_iface->interrupt_in);
-}
-
-void remote_usbhc_control_write_setup(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-	assert(usb_iface != NULL);
-
-	return remote_usbhc_out_transfer(device, callid, call,
-	    usb_iface->control_write_setup);
-}
-
-void remote_usbhc_control_write_data(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-	assert(usb_iface != NULL);
-
-	return remote_usbhc_out_transfer(device, callid, call,
-	    usb_iface->control_write_data);
-}
-
-void remote_usbhc_control_write_status(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-	assert(usb_iface != NULL);
-
-	return remote_usbhc_status_transfer(device, callid, call,
-	    USB_DIRECTION_IN, usb_iface->control_write_status, NULL);
-}
-
-void remote_usbhc_control_read_setup(device_t *device, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-	assert(usb_iface != NULL);
-
-	return remote_usbhc_out_transfer(device, callid, call,
-	    usb_iface->control_read_setup);
-}
-
-void remote_usbhc_control_read_data(device_t *device, void *iface,
-	    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-	assert(usb_iface != NULL);
-
-	return remote_usbhc_in_transfer(device, callid, call,
-	    usb_iface->control_read_data);
-}
-
-void remote_usbhc_control_read_status(device_t *device, void *iface,
-	    ipc_callid_t callid, ipc_call_t *call)
-{
-	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
-	assert(usb_iface != NULL);
-
-	return remote_usbhc_status_transfer(device, callid, call,
-	    USB_DIRECTION_OUT, NULL, usb_iface->control_read_status);
+	if (!usb_iface->control_read) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_target_t target = {
+		.address = DEV_IPC_GET_ARG1(*call),
+		.endpoint = DEV_IPC_GET_ARG2(*call)
+	};
+	size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
+
+	int rc;
+
+	void *setup_packet = NULL;
+	size_t setup_packet_len = 0;
+	size_t data_len = 0;
+
+	rc = async_data_write_accept(&setup_packet, false,
+	    1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(callid, EPARTY);
+		free(setup_packet);
+		return;
+	}
+
+	async_transaction_t *trans = async_transaction_create(callid);
+	if (trans == NULL) {
+		async_answer_0(callid, ENOMEM);
+		free(setup_packet);
+		return;
+	}
+	trans->data_caller = data_callid;
+	trans->setup_packet = setup_packet;
+	trans->size = data_len;
+	trans->buffer = malloc(data_len);
+	if (trans->buffer == NULL) {
+		async_answer_0(callid, ENOMEM);
+		async_transaction_destroy(trans);
+		return;
+	}
+
+	rc = usb_iface->control_read(fun, target, max_packet_size,
+	    setup_packet, setup_packet_len,
+	    trans->buffer, trans->size,
+	    callback_in, trans);
+
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_transaction_destroy(trans);
+	}
 }
 
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/drv/include/ddf/driver.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef DDF_DRIVER_H_
+#define DDF_DRIVER_H_
+
+#include <ipc/devman.h>
+#include <ipc/dev_iface.h>
+
+#include "../dev_iface.h"
+
+typedef struct ddf_dev ddf_dev_t;
+typedef struct ddf_fun ddf_fun_t;
+
+/*
+ * Device
+ */
+
+/** Devices operations */
+typedef struct ddf_dev_ops {
+	/**
+	 * Optional callback function called when a client is connecting to the
+	 * device.
+	 */
+	int (*open)(ddf_fun_t *);
+	
+	/**
+	 * Optional callback function called when a client is disconnecting from
+	 * the device.
+	 */
+	void (*close)(ddf_fun_t *);
+	
+	/** The table of standard interfaces implemented by the device. */
+	void *interfaces[DEV_IFACE_COUNT];
+	
+	/**
+	 * The default handler of remote client requests. If the client's remote
+	 * request cannot be handled by any of the standard interfaces, the
+	 * default handler is used.
+	 */
+	remote_handler_t *default_handler;
+} ddf_dev_ops_t;
+
+/** Device structure */
+struct ddf_dev {
+	/**
+	 * Globally unique device identifier (assigned to the device by the
+	 * device manager).
+	 */
+	devman_handle_t handle;
+	
+	/**
+	 * Phone to the parent device driver (if it is different from this
+	 * driver)
+	 */
+	int parent_phone;
+	
+	/** Device name */
+	const char *name;
+	
+	/** Driver-specific data associated with this device */
+	void *driver_data;
+	
+	/** Link in the list of devices handled by the driver */
+	link_t link;
+};
+
+/** Function structure */
+struct ddf_fun {
+	/** True if bound to the device manager */
+	bool bound;
+	/** Function indentifier (asigned by device manager) */
+	devman_handle_t handle;
+	
+	/** Device which this function belogs to */
+	ddf_dev_t *dev;
+	
+	/** Function type */
+	fun_type_t ftype;
+	/** Function name */
+	const char *name;
+	/** List of device ids for driver matching */
+	match_id_list_t match_ids;
+	/** Driver-specific data associated with this function */
+	void *driver_data;
+	/** Implementation of operations provided by this function */
+	ddf_dev_ops_t *ops;
+	
+	/** Link in the list of functions handled by the driver */
+	link_t link;
+};
+
+/*
+ * Driver
+ */
+
+/** Generic device driver operations */
+typedef struct driver_ops {
+	/** Callback method for passing a new device to the device driver */
+	int (*add_device)(ddf_dev_t *dev);
+	/* TODO: add other generic driver operations */
+} driver_ops_t;
+
+/** Driver structure */
+typedef struct driver {
+	/** Name of the device driver */
+	const char *name;
+	/** Generic device driver operations */
+	driver_ops_t *driver_ops;
+} driver_t;
+
+extern int ddf_driver_main(driver_t *);
+
+extern ddf_fun_t *ddf_fun_create(ddf_dev_t *, fun_type_t, const char *);
+extern void ddf_fun_destroy(ddf_fun_t *);
+extern int ddf_fun_bind(ddf_fun_t *);
+extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int);
+
+extern int ddf_fun_add_to_class(ddf_fun_t *, const char *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/ddf/interrupt.h
===================================================================
--- uspace/lib/drv/include/ddf/interrupt.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/drv/include/ddf/interrupt.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef DDF_INTERRUPT_H_
+#define DDF_INTERRUPT_H_
+
+#include <kernel/ddi/irq.h>
+#include <adt/list.h>
+#include <ddi.h>
+#include <fibril_synch.h>
+
+#include "driver.h"
+#include "../dev_iface.h"
+
+/*
+ * Interrupts
+ */
+
+typedef void interrupt_handler_t(ddf_dev_t *, ipc_callid_t, ipc_call_t *);
+
+typedef struct interrupt_context {
+	int id;
+	ddf_dev_t *dev;
+	int irq;
+	interrupt_handler_t *handler;
+	link_t link;
+} interrupt_context_t;
+
+typedef struct interrupt_context_list {
+	int curr_id;
+	link_t contexts;
+	fibril_mutex_t mutex;
+} interrupt_context_list_t;
+
+extern interrupt_context_t *create_interrupt_context(void);
+extern void delete_interrupt_context(interrupt_context_t *);
+extern void init_interrupt_context_list(interrupt_context_list_t *);
+extern void add_interrupt_context(interrupt_context_list_t *,
+    interrupt_context_t *);
+extern void remove_interrupt_context(interrupt_context_list_t *,
+    interrupt_context_t *);
+extern interrupt_context_t *find_interrupt_context_by_id(
+    interrupt_context_list_t *, int);
+extern interrupt_context_t *find_interrupt_context(
+    interrupt_context_list_t *, ddf_dev_t *, int);
+
+extern int register_interrupt_handler(ddf_dev_t *, int, interrupt_handler_t *,
+    irq_code_t *);
+extern int unregister_interrupt_handler(ddf_dev_t *, int);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/dev_iface.h
===================================================================
--- uspace/lib/drv/include/dev_iface.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/drv/include/dev_iface.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,4 +36,5 @@
 #define LIBDRV_DEV_IFACE_H_
 
+#include <ipc/common.h>
 #include <ipc/dev_iface.h>
 
@@ -42,5 +43,5 @@
  */
 
-struct device;
+struct ddf_fun;
 
 /*
@@ -48,8 +49,8 @@
  * devices driver.
  */
-typedef void remote_iface_func_t(struct device *, void *, ipc_callid_t,
+typedef void remote_iface_func_t(struct ddf_fun *, void *, ipc_callid_t,
     ipc_call_t *);
 typedef remote_iface_func_t *remote_iface_func_ptr_t;
-typedef void remote_handler_t(struct device *, ipc_callid_t, ipc_call_t *);
+typedef void remote_handler_t(struct ddf_fun *, ipc_callid_t, ipc_call_t *);
 
 typedef struct {
Index: pace/lib/drv/include/driver.h
===================================================================
--- uspace/lib/drv/include/driver.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,193 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * 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 libdrv
- * @{
- */
-/** @file
- */
-
-#ifndef LIBDRV_DRIVER_H_
-#define LIBDRV_DRIVER_H_
-
-#include <adt/list.h>
-#include <ipc/ipc.h>
-#include <devman.h>
-#include <ipc/devman.h>
-#include <ipc/dev_iface.h>
-#include <assert.h>
-#include <ddi.h>
-#include <libarch/ddi.h>
-#include <fibril_synch.h>
-#include <malloc.h>
-
-#include "dev_iface.h"
-
-struct device;
-typedef struct device device_t;
-
-/*
- * Device class
- */
-
-/** Devices operations */
-typedef struct device_ops {
-	/**
-	 * Optional callback function called when a client is connecting to the
-	 * device.
-	 */
-	int (*open)(device_t *);
-	
-	/**
-	 * Optional callback function called when a client is disconnecting from
-	 * the device.
-	 */
-	void (*close)(device_t *);
-	
-	/** The table of standard interfaces implemented by the device. */
-	void *interfaces[DEV_IFACE_COUNT];
-	
-	/**
-	 * The default handler of remote client requests. If the client's remote
-	 * request cannot be handled by any of the standard interfaces, the
-	 * default handler is used.
-	 */
-	remote_handler_t *default_handler;
-} device_ops_t;
-
-
-/*
- * Device
- */
-
-/** Device structure */
-struct device {
-	/**
-	 * Globally unique device identifier (assigned to the device by the
-	 * device manager).
-	 */
-	devman_handle_t handle;
-	
-	/**
-	 * Phone to the parent device driver (if it is different from this
-	 * driver)
-	 */
-	int parent_phone;
-	
-	/** Parent device if handled by this driver, NULL otherwise */
-	device_t *parent;
-	/** Device name */
-	const char *name;
-	/** List of device ids for device-to-driver matching */
-	match_id_list_t match_ids;
-	/** Driver-specific data associated with this device */
-	void *driver_data;
-	/** The implementation of operations provided by this device */
-	device_ops_t *ops;
-	
-	/** Link in the list of devices handled by the driver */
-	link_t link;
-};
-
-/*
- * Driver
- */
-
-/** Generic device driver operations */
-typedef struct driver_ops {
-	/** Callback method for passing a new device to the device driver */
-	int (*add_device)(device_t *dev);
-	/* TODO: add other generic driver operations */
-} driver_ops_t;
-
-/** Driver structure */
-typedef struct driver {
-	/** Name of the device driver */
-	const char *name;
-	/** Generic device driver operations */
-	driver_ops_t *driver_ops;
-} driver_t;
-
-int driver_main(driver_t *);
-
-/** Create new device structure.
- *
- * @return		The device structure.
- */
-extern device_t *create_device(void);
-extern void delete_device(device_t *);
-extern void *device_get_ops(device_t *, dev_inferface_idx_t);
-
-extern int child_device_register(device_t *, device_t *);
-extern int child_device_register_wrapper(device_t *, const char *, const char *,
-    int, devman_handle_t *);
-
-/*
- * Interrupts
- */
-
-typedef void interrupt_handler_t(device_t *, ipc_callid_t, ipc_call_t *);
-
-typedef struct interrupt_context {
-	int id;
-	device_t *dev;
-	int irq;
-	interrupt_handler_t *handler;
-	link_t link;
-} interrupt_context_t;
-
-typedef struct interrupt_context_list {
-	int curr_id;
-	link_t contexts;
-	fibril_mutex_t mutex;
-} interrupt_context_list_t;
-
-extern interrupt_context_t *create_interrupt_context(void);
-extern void delete_interrupt_context(interrupt_context_t *);
-extern void init_interrupt_context_list(interrupt_context_list_t *);
-extern void add_interrupt_context(interrupt_context_list_t *,
-    interrupt_context_t *);
-extern void remove_interrupt_context(interrupt_context_list_t *,
-    interrupt_context_t *);
-extern interrupt_context_t *find_interrupt_context_by_id(
-    interrupt_context_list_t *, int);
-extern interrupt_context_t *find_interrupt_context(
-    interrupt_context_list_t *, device_t *, int);
-
-extern int register_interrupt_handler(device_t *, int, interrupt_handler_t *,
-    irq_code_t *);
-extern int unregister_interrupt_handler(device_t *, int);
-
-extern remote_handler_t *device_get_default_handler(device_t *);
-extern int add_device_to_class(device_t *, const char *);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/lib/drv/include/ops/char_dev.h
===================================================================
--- uspace/lib/drv/include/ops/char_dev.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/drv/include/ops/char_dev.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,9 +36,9 @@
 #define LIBDRV_OPS_CHAR_DEV_H_
 
-#include "../driver.h"
+#include "../ddf/driver.h"
 
 typedef struct {
-	int (*read)(device_t *, char *, size_t);
-	int (*write)(device_t *, char *, size_t);
+	int (*read)(ddf_fun_t *, char *, size_t);
+	int (*write)(ddf_fun_t *, char *, size_t);
 } char_dev_ops_t;
 
Index: uspace/lib/drv/include/ops/hw_res.h
===================================================================
--- uspace/lib/drv/include/ops/hw_res.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/drv/include/ops/hw_res.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,9 +39,9 @@
 #include <sys/types.h>
 
-#include "../driver.h"
+#include "../ddf/driver.h"
 
 typedef struct {
-	 hw_resource_list_t *(*get_resource_list)(device_t *);
-	 bool (*enable_interrupt)(device_t *);
+	 hw_resource_list_t *(*get_resource_list)(ddf_fun_t *);
+	 bool (*enable_interrupt)(ddf_fun_t *);
 } hw_res_ops_t;
 
Index: uspace/lib/drv/include/usb_iface.h
===================================================================
--- uspace/lib/drv/include/usb_iface.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/drv/include/usb_iface.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,6 @@
  */
 
-/** @addtogroup libdrv usb
+/** @addtogroup libdrv
+ * @addtogroup usb
  * @{
  */
@@ -37,7 +38,27 @@
 #define LIBDRV_USB_IFACE_H_
 
-#include "driver.h"
+#include "ddf/driver.h"
 #include <usb/usb.h>
 typedef enum {
+	/** Tell USB address assigned to device.
+	 * Parameters:
+	 * - devman handle id
+	 * Answer:
+	 * - EINVAL - unknown handle or handle not managed by this driver
+	 * - ENOTSUP - operation not supported (shall not happen)
+	 * - arbitrary error code if returned by remote implementation
+	 * - EOK - handle found, first parameter contains the USB address
+	 */
+	IPC_M_USB_GET_ADDRESS,
+
+	/** Tell interface number given device can use.
+	 * Parameters
+	 * - devman handle id of the device
+	 * Answer:
+	 * - ENOTSUP - operation not supported (can also mean any interface)
+	 * - EOK - operation okay, first parameter contains interface number
+	 */
+	IPC_M_USB_GET_INTERFACE,
+
 	/** Tell devman handle of device host controller.
 	 * Parameters:
@@ -54,5 +75,7 @@
 /** USB device communication interface. */
 typedef struct {
-	int (*get_hc_handle)(device_t *, devman_handle_t *);
+	int (*get_address)(ddf_fun_t *, devman_handle_t, usb_address_t *);
+	int (*get_interface)(ddf_fun_t *, devman_handle_t, int *);
+	int (*get_hc_handle)(ddf_fun_t *, devman_handle_t *);
 } usb_iface_t;
 
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,6 @@
  */
 
-/** @addtogroup libdrv usb
+/** @addtogroup libdrv
+ * @addtogroup usb
  * @{
  */
@@ -37,6 +38,7 @@
 #define LIBDRV_USBHC_IFACE_H_
 
-#include "driver.h"
+#include "ddf/driver.h"
 #include <usb/usb.h>
+#include <bool.h>
 
 
@@ -51,5 +53,5 @@
  *   - argument #1 is target address
  *   - argument #2 is target endpoint
- *   - argument #3 is buffer size
+ *   - argument #3 is max packet size of the endpoint
  * - this call is immediately followed by IPC data write (from caller)
  * - the initial call (and the whole transaction) is answer after the
@@ -64,22 +66,13 @@
  *   - argument #1 is target address
  *   - argument #2 is target endpoint
- *   - argument #3 is buffer size
+ *   - argument #3 is max packet size of the endpoint
+ * - this call is immediately followed by IPC data read (async version)
  * - the call is not answered until the device returns some data (or until
  *   error occurs)
- * - if the call is answered with EOK, first argument of the answer is buffer
- *   hash that could be used to retrieve the actual data
  *
  * Some special methods (NO-DATA transactions) do not send any data. These
  * might behave as both OUT or IN transactions because communication parts
  * where actual buffers are exchanged are omitted.
- *
- * The mentioned data retrieval can be done any time after receiving EOK
- * answer to IN method.
- * This retrieval is done using the IPC_M_USBHC_GET_BUFFER where
- * the first argument is buffer hash from call answer.
- * This call must be immediately followed by data read-in and after the
- * data are transferred, the initial call (IPC_M_USBHC_GET_BUFFER)
- * is answered. Each buffer can be retrieved only once.
- *
+ **
  * For all these methods, wrap functions exists. Important rule: functions
  * for IN transactions have (as parameters) buffers where retrieved data
@@ -92,23 +85,4 @@
  */
 typedef enum {
-	/** Tell USB address assigned to device.
-	 * Parameters:
-	 * - devman handle id
-	 * Answer:
-	 * - EINVAL - unknown handle or handle not managed by this driver
-	 * - ENOTSUP - operation not supported by HC (shall not happen)
-	 * - arbitrary error code if returned by remote implementation
-	 * - EOK - handle found, first parameter contains the USB address
-	 */
-	IPC_M_USBHC_GET_ADDRESS,
-
-	/** Asks for data buffer.
-	 * See explanation at usb_iface_funcs_t.
-	 * This function does not have counter part in functional interface
-	 * as it is handled by the remote part itself.
-	 */
-	IPC_M_USBHC_GET_BUFFER,
-
-
 	/** Reserve usage of default address.
 	 * This call informs the host controller that the caller will be
@@ -167,37 +141,29 @@
 	IPC_M_USBHC_INTERRUPT_IN,
 
-
-	/** Start WRITE control transfer.
+	/** Send bulk data to device.
 	 * See explanation at usb_iface_funcs_t (OUT transaction).
 	 */
-	IPC_M_USBHC_CONTROL_WRITE_SETUP,
-
-	/** Send control-transfer data to device.
-	 * See explanation at usb_iface_funcs_t (OUT transaction).
-	 */
-	IPC_M_USBHC_CONTROL_WRITE_DATA,
-
-	/** Terminate WRITE control transfer.
-	 * See explanation at usb_iface_funcs_t (NO-DATA transaction).
-	 */
-	IPC_M_USBHC_CONTROL_WRITE_STATUS,
-
-
-
-	/** Start READ control transfer.
-	 * See explanation at usb_iface_funcs_t (OUT transaction).
-	 */
-	IPC_M_USBHC_CONTROL_READ_SETUP,
-
-	/** Get control-transfer data from device.
+	IPC_M_USBHC_BULK_OUT,
+
+	/** Get bulk data from device.
 	 * See explanation at usb_iface_funcs_t (IN transaction).
 	 */
-	IPC_M_USBHC_CONTROL_READ_DATA,
-
-	/** Terminate READ control transfer.
-	 * See explanation at usb_iface_funcs_t (NO-DATA transaction).
-	 */
-	IPC_M_USBHC_CONTROL_READ_STATUS,
-
+	IPC_M_USBHC_BULK_IN,
+
+	/** Issue control WRITE transfer.
+	 * See explanation at usb_iface_funcs_t (OUT transaction) for
+	 * call parameters.
+	 * This call is immediately followed by two IPC data writes
+	 * from the caller (setup packet and actual data).
+	 */
+	IPC_M_USBHC_CONTROL_WRITE,
+
+	/** Issue control READ transfer.
+	 * See explanation at usb_iface_funcs_t (IN transaction) for
+	 * call parameters.
+	 * This call is immediately followed by IPC data write from the caller
+	 * (setup packet) and IPC data read (buffer that was read).
+	 */
+	IPC_M_USBHC_CONTROL_READ,
 
 	/* IPC_M_USB_ */
@@ -205,22 +171,22 @@
 
 /** Callback for outgoing transfer. */
-typedef void (*usbhc_iface_transfer_out_callback_t)(device_t *,
-    usb_transaction_outcome_t, void *);
+typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *,
+    int, void *);
 
 /** Callback for incoming transfer. */
-typedef void (*usbhc_iface_transfer_in_callback_t)(device_t *,
-    usb_transaction_outcome_t, size_t, void *);
+typedef void (*usbhc_iface_transfer_in_callback_t)(ddf_fun_t *,
+    int, size_t, void *);
 
 
 /** Out transfer processing function prototype. */
-typedef int (*usbhc_iface_transfer_out_t)(device_t *, usb_target_t,
+typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, size_t,
     void *, size_t,
     usbhc_iface_transfer_out_callback_t, void *);
 
-/** Setup transfer processing function prototype. */
+/** Setup transfer processing function prototype. @deprecated */
 typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t;
 
 /** In transfer processing function prototype. */
-typedef int (*usbhc_iface_transfer_in_t)(device_t *, usb_target_t,
+typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, size_t,
     void *, size_t,
     usbhc_iface_transfer_in_callback_t, void *);
@@ -228,24 +194,25 @@
 /** USB host controller communication interface. */
 typedef struct {
-	int (*tell_address)(device_t *, devman_handle_t, usb_address_t *);
-
-	int (*reserve_default_address)(device_t *);
-	int (*release_default_address)(device_t *);
-	int (*request_address)(device_t *, usb_address_t *);
-	int (*bind_address)(device_t *, usb_address_t, devman_handle_t);
-	int (*release_address)(device_t *, usb_address_t);
+	int (*reserve_default_address)(ddf_fun_t *, usb_speed_t);
+	int (*release_default_address)(ddf_fun_t *);
+	int (*request_address)(ddf_fun_t *, usb_speed_t, usb_address_t *);
+	int (*bind_address)(ddf_fun_t *, usb_address_t, devman_handle_t);
+	int (*release_address)(ddf_fun_t *, usb_address_t);
 
 	usbhc_iface_transfer_out_t interrupt_out;
 	usbhc_iface_transfer_in_t interrupt_in;
 
-	usbhc_iface_transfer_setup_t control_write_setup;
-	usbhc_iface_transfer_out_t control_write_data;
-	int (*control_write_status)(device_t *, usb_target_t,
+	usbhc_iface_transfer_out_t bulk_out;
+	usbhc_iface_transfer_in_t bulk_in;
+
+	int (*control_write)(ddf_fun_t *, usb_target_t,
+	    size_t,
+	    void *, size_t, void *, size_t,
+	    usbhc_iface_transfer_out_callback_t, void *);
+
+	int (*control_read)(ddf_fun_t *, usb_target_t,
+	    size_t,
+	    void *, size_t, void *, size_t,
 	    usbhc_iface_transfer_in_callback_t, void *);
-
-	usbhc_iface_transfer_setup_t control_read_setup;
-	usbhc_iface_transfer_in_t control_read_data;
-	int (*control_read_status)(device_t *, usb_target_t,
-	    usbhc_iface_transfer_out_callback_t, void *);
 } usbhc_iface_t;
 
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/fs/libfs.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,5 +40,4 @@
 #include <errno.h>
 #include <async.h>
-#include <ipc/ipc.h>
 #include <as.h>
 #include <assert.h>
@@ -58,5 +57,5 @@
 #define answer_and_return(rid, rc) \
 	do { \
-		ipc_answer_0((rid), (rc)); \
+		async_answer_0((rid), (rc)); \
 		return; \
 	} while (0)
@@ -102,5 +101,5 @@
 	 * Ask VFS for callback connection.
 	 */
-	ipc_connect_to_me(vfs_phone, 0, 0, 0, &reg->vfs_phonehash);
+	async_connect_to_me(vfs_phone, 0, 0, 0, conn);
 	
 	/*
@@ -127,9 +126,4 @@
 	async_wait_for(req, NULL);
 	reg->fs_handle = (int) IPC_GET_ARG1(answer);
-	
-	/*
-	 * Create a connection fibril to handle the callback connection.
-	 */
-	async_new_connection(reg->vfs_phonehash, 0, NULL, conn);
 	
 	/*
@@ -165,26 +159,26 @@
 	if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECTION_CLONE) ||
 	    (mountee_phone < 0)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
 	
 	/* Acknowledge the mountee_phone */
-	ipc_answer_0(callid, EOK);
+	async_answer_0(callid, EOK);
 	
 	fs_node_t *fn;
 	res = ops->node_get(&fn, mp_devmap_handle, mp_fs_index);
 	if ((res != EOK) || (!fn)) {
-		ipc_hangup(mountee_phone);
+		async_hangup(mountee_phone);
 		async_data_write_void(combine_rc(res, ENOENT));
-		ipc_answer_0(rid, combine_rc(res, ENOENT));
+		async_answer_0(rid, combine_rc(res, ENOENT));
 		return;
 	}
 	
 	if (fn->mp_data.mp_active) {
-		ipc_hangup(mountee_phone);
+		async_hangup(mountee_phone);
 		(void) ops->node_put(fn);
 		async_data_write_void(EBUSY);
-		ipc_answer_0(rid, EBUSY);
+		async_answer_0(rid, EBUSY);
 		return;
 	}
@@ -192,8 +186,8 @@
 	rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
 	if (rc != EOK) {
-		ipc_hangup(mountee_phone);
+		async_hangup(mountee_phone);
 		(void) ops->node_put(fn);
 		async_data_write_void(rc);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -213,5 +207,5 @@
 	 * Do not release the FS node so that it stays in memory.
 	 */
-	ipc_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
+	async_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
 	    IPC_GET_ARG3(answer));
 }
@@ -226,5 +220,5 @@
 	res = ops->node_get(&fn, mp_devmap_handle, mp_fs_index);
 	if ((res != EOK) || (!fn)) {
-		ipc_answer_0(rid, combine_rc(res, ENOENT));
+		async_answer_0(rid, combine_rc(res, ENOENT));
 		return;
 	}
@@ -235,5 +229,5 @@
 	if (!fn->mp_data.mp_active) {
 		(void) ops->node_put(fn);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -249,5 +243,5 @@
 	 */
 	if (res == EOK) {
-		ipc_hangup(fn->mp_data.phone);
+		async_hangup(fn->mp_data.phone);
 		fn->mp_data.mp_active = false;
 		fn->mp_data.fs_handle = 0;
@@ -259,5 +253,5 @@
 
 	(void) ops->node_put(fn);
-	ipc_answer_0(rid, res);
+	async_answer_0(rid, res);
 }
 
@@ -299,5 +293,5 @@
 	
 	if (cur->mp_data.mp_active) {
-		ipc_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP,
+		async_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP,
 		    next, last, cur->mp_data.devmap_handle, lflag, index,
 		    IPC_FF_ROUTE_FROM_ME);
@@ -323,5 +317,5 @@
 			if (len + 1 == NAME_MAX) {
 				/* Component length overflow */
-				ipc_answer_0(rid, ENAMETOOLONG);
+				async_answer_0(rid, ENAMETOOLONG);
 				goto out;
 			}
@@ -357,5 +351,5 @@
 				next--;
 			
-			ipc_forward_slow(rid, tmp->mp_data.phone,
+			async_forward_slow(rid, tmp->mp_data.phone,
 			    VFS_OUT_LOOKUP, next, last, tmp->mp_data.devmap_handle,
 			    lflag, index, IPC_FF_ROUTE_FROM_ME);
@@ -371,5 +365,5 @@
 			if (next <= last) {
 				/* There are unprocessed components */
-				ipc_answer_0(rid, ENOENT);
+				async_answer_0(rid, ENOENT);
 				goto out;
 			}
@@ -379,5 +373,5 @@
 				/* Request to create a new link */
 				if (!ops->is_directory(cur)) {
-					ipc_answer_0(rid, ENOTDIR);
+					async_answer_0(rid, ENOTDIR);
 					goto out;
 				}
@@ -397,8 +391,8 @@
 						if (lflag & L_CREATE)
 							(void) ops->destroy(fn);
-						ipc_answer_0(rid, rc);
+						async_answer_0(rid, rc);
 					} else {
 						aoff64_t size = ops->size_get(fn);
-						ipc_answer_5(rid, fs_handle,
+						async_answer_5(rid, fs_handle,
 						    devmap_handle,
 						    ops->index_get(fn),
@@ -409,10 +403,10 @@
 					}
 				} else
-					ipc_answer_0(rid, ENOSPC);
+					async_answer_0(rid, ENOSPC);
 				
 				goto out;
 			}
 			
-			ipc_answer_0(rid, ENOENT);
+			async_answer_0(rid, ENOENT);
 			goto out;
 		}
@@ -440,5 +434,5 @@
 		if (lflag & (L_CREATE | L_LINK)) {
 			if (!ops->is_directory(cur)) {
-				ipc_answer_0(rid, ENOTDIR);
+				async_answer_0(rid, ENOTDIR);
 				goto out;
 			}
@@ -449,5 +443,5 @@
 				if (ops->plb_get_char(next) == '/') {
 					/* More than one component */
-					ipc_answer_0(rid, ENOENT);
+					async_answer_0(rid, ENOENT);
 					goto out;
 				}
@@ -455,5 +449,5 @@
 				if (len + 1 == NAME_MAX) {
 					/* Component length overflow */
-					ipc_answer_0(rid, ENAMETOOLONG);
+					async_answer_0(rid, ENAMETOOLONG);
 					goto out;
 				}
@@ -479,8 +473,8 @@
 					if (lflag & L_CREATE)
 						(void) ops->destroy(fn);
-					ipc_answer_0(rid, rc);
+					async_answer_0(rid, rc);
 				} else {
 					aoff64_t size = ops->size_get(fn);
-					ipc_answer_5(rid, fs_handle,
+					async_answer_5(rid, fs_handle,
 					    devmap_handle,
 					    ops->index_get(fn),
@@ -491,10 +485,10 @@
 				}
 			} else
-				ipc_answer_0(rid, ENOSPC);
+				async_answer_0(rid, ENOSPC);
 			
 			goto out;
 		}
 		
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		goto out;
 	}
@@ -509,9 +503,9 @@
 		if (rc == EOK) {
 			aoff64_t size = ops->size_get(cur);
-			ipc_answer_5(rid, fs_handle, devmap_handle,
+			async_answer_5(rid, fs_handle, devmap_handle,
 			    ops->index_get(cur), LOWER32(size), UPPER32(size),
 			    old_lnkcnt);
 		} else
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 		
 		goto out;
@@ -520,20 +514,20 @@
 	if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) ||
 	    (lflag & L_LINK)) {
-		ipc_answer_0(rid, EEXIST);
+		async_answer_0(rid, EEXIST);
 		goto out;
 	}
 	
 	if ((lflag & L_FILE) && (ops->is_directory(cur))) {
-		ipc_answer_0(rid, EISDIR);
+		async_answer_0(rid, EISDIR);
 		goto out;
 	}
 	
 	if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) {
-		ipc_answer_0(rid, ENOTDIR);
+		async_answer_0(rid, ENOTDIR);
 		goto out;
 	}
 
 	if ((lflag & L_ROOT) && par) {
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		goto out;
 	}
@@ -547,12 +541,12 @@
 		if (rc == EOK) {
 			aoff64_t size = ops->size_get(cur);
-			ipc_answer_5(rid, fs_handle, devmap_handle,
+			async_answer_5(rid, fs_handle, devmap_handle,
 			    ops->index_get(cur), LOWER32(size), UPPER32(size),
 			    ops->lnkcnt_get(cur));
 		} else
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 		
 	} else
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 	
 out:
@@ -583,6 +577,6 @@
 	    (size != sizeof(struct stat))) {
 		ops->node_put(fn);
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -603,5 +597,5 @@
 	
 	async_data_read_finalize(callid, &stat, sizeof(struct stat));
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
@@ -625,5 +619,5 @@
 	
 	if (fn == NULL) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -631,5 +625,5 @@
 	rc = ops->node_open(fn);
 	aoff64_t size = ops->size_get(fn);
-	ipc_answer_4(rid, rc, LOWER32(size), UPPER32(size), ops->lnkcnt_get(fn),
+	async_answer_4(rid, rc, LOWER32(size), UPPER32(size), ops->lnkcnt_get(fn),
 	    (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0));
 	
Index: uspace/lib/fs/libfs.h
===================================================================
--- uspace/lib/fs/libfs.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/fs/libfs.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
 #include <ipc/vfs.h>
 #include <stdint.h>
-#include <ipc/ipc.h>
 #include <async.h>
 #include <devmap.h>
@@ -86,5 +85,4 @@
 typedef struct {
 	int fs_handle;           /**< File system handle. */
-	sysarg_t vfs_phonehash;  /**< Initial VFS phonehash. */
 	uint8_t *plb_ro;         /**< Read-only PLB view. */
 } fs_reg_t;
Index: uspace/lib/net/generic/generic.c
===================================================================
--- uspace/lib/net/generic/generic.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/generic/generic.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,9 +36,6 @@
 
 #include <generic.h>
-
 #include <async.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <adt/measured_strings.h>
Index: uspace/lib/net/generic/packet_remote.c
===================================================================
--- uspace/lib/net/generic/packet_remote.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/generic/packet_remote.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,5 +38,4 @@
 #include <async.h>
 #include <errno.h>
-#include <ipc/ipc.h>
 #include <ipc/packet.h>
 #include <sys/mman.h>
Index: uspace/lib/net/il/arp_remote.c
===================================================================
--- uspace/lib/net/il/arp_remote.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/il/arp_remote.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,5 +41,4 @@
 #include <async.h>
 #include <errno.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/arp.h>
Index: uspace/lib/net/il/il_skel.c
===================================================================
--- uspace/lib/net/il/il_skel.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/il/il_skel.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -54,5 +54,5 @@
 	 * the initial IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
@@ -115,6 +115,5 @@
 		goto out;
 	
-	sysarg_t phonehash;
-	rc = ipc_connect_to_me(PHONE_NS, service, 0, 0, &phonehash);
+	rc = async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
 	if (rc != EOK)
 		goto out;
Index: uspace/lib/net/include/generic.h
===================================================================
--- uspace/lib/net/include/generic.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/include/generic.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
 
 #include <async.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 
Index: uspace/lib/net/include/icmp_header.h
===================================================================
--- uspace/lib/net/include/icmp_header.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/include/icmp_header.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,26 +45,16 @@
 
 /** ICMP header size in bytes. */
-#define ICMP_HEADER_SIZE	sizeof(icmp_header_t)
-
-/** Type definition of the echo specific data.
- * @see icmp_echo
- */
-typedef struct icmp_echo icmp_echo_t;
+#define ICMP_HEADER_SIZE  sizeof(icmp_header_t)
 
 /** Echo specific data. */
-struct icmp_echo {
+typedef struct icmp_echo {
 	/** Message idintifier. */
 	icmp_param_t identifier;
 	/** Message sequence number. */
 	icmp_param_t sequence_number;
-} __attribute__ ((packed));
-
-/** Type definition of the internet control message header.
- * @see icmp_header
- */
-typedef struct icmp_header icmp_header_t;
+} __attribute__((packed)) icmp_echo_t;
 
 /** Internet control message header. */
-struct icmp_header {
+typedef struct icmp_header {
 	/** The type of the message. */
 	uint8_t type;
@@ -83,9 +73,9 @@
 	 */
 	uint16_t checksum;
-
+	
 	/** Message specific data. */
 	union {
 		/** Echo specific data. */
-		icmp_echo_t  echo;
+		icmp_echo_t echo;
 		/** Proposed gateway value. */
 		in_addr_t gateway;
@@ -107,5 +97,5 @@
 		} param;
 	} un;
-} __attribute__ ((packed));
+} __attribute__((packed)) icmp_header_t;
 
 #endif
Index: pace/lib/net/include/icmp_interface.h
===================================================================
--- uspace/lib/net/include/icmp_interface.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,63 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 libnet 
- *  @{
- */
-
-#ifndef LIBNET_ICMP_INTERFACE_H_
-#define LIBNET_ICMP_INTERFACE_H_
-
-#include <net/socket_codes.h>
-#include <sys/types.h>
-
-#include <net/device.h>
-#include <adt/measured_strings.h>
-#include <net/packet.h>
-#include <net/inet.h>
-#include <net/ip_codes.h>
-#include <net/icmp_codes.h>
-#include <net/icmp_common.h>
-
-/** @name ICMP module interface
- * This interface is used by other modules.
- */
-/*@{*/
-
-extern int icmp_destination_unreachable_msg(int, icmp_code_t, icmp_param_t,
-    packet_t *);
-extern int icmp_source_quench_msg(int, packet_t *);
-extern int icmp_time_exceeded_msg(int, icmp_code_t, packet_t *);
-extern int icmp_parameter_problem_msg(int, icmp_code_t, icmp_param_t, packet_t *);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: uspace/lib/net/include/icmp_remote.h
===================================================================
--- uspace/lib/net/include/icmp_remote.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/net/include/icmp_remote.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * 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 libnet
+ *  @{
+ */
+
+#ifndef LIBNET_ICMP_REMOTE_H_
+#define LIBNET_ICMP_REMOTE_H_
+
+#include <net/socket_codes.h>
+#include <sys/types.h>
+
+#include <net/device.h>
+#include <adt/measured_strings.h>
+#include <net/packet.h>
+#include <net/inet.h>
+#include <net/ip_codes.h>
+#include <net/icmp_codes.h>
+#include <net/icmp_common.h>
+
+/** @name ICMP module interface
+ * This interface is used by other modules.
+ */
+/*@{*/
+
+extern int icmp_destination_unreachable_msg(int, icmp_code_t, icmp_param_t,
+    packet_t *);
+extern int icmp_source_quench_msg(int, packet_t *);
+extern int icmp_time_exceeded_msg(int, icmp_code_t, packet_t *);
+extern int icmp_parameter_problem_msg(int, icmp_code_t, icmp_param_t,
+    packet_t *);
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/net/include/il_skel.h
===================================================================
--- uspace/lib/net/include/il_skel.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/include/il_skel.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,5 +41,4 @@
 #include <async.h>
 #include <fibril_synch.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 
Index: uspace/lib/net/include/netif_skel.h
===================================================================
--- uspace/lib/net/include/netif_skel.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/include/netif_skel.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,5 +41,4 @@
 #include <async.h>
 #include <fibril_synch.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 
Index: uspace/lib/net/include/nil_skel.h
===================================================================
--- uspace/lib/net/include/nil_skel.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/include/nil_skel.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,5 +41,4 @@
 #include <async.h>
 #include <fibril_synch.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 
Index: uspace/lib/net/include/tl_skel.h
===================================================================
--- uspace/lib/net/include/tl_skel.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/include/tl_skel.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,5 +41,4 @@
 #include <async.h>
 #include <fibril_synch.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 
@@ -61,4 +60,11 @@
 extern int tl_initialize(int net_phone);
 
+/** Per-connection module initialization.
+ *
+ * This has to be implemented in user code.
+ *
+ */
+extern void tl_connection(void);
+
 /** Process the transport layer module message.
  *
@@ -74,5 +80,5 @@
  *
  */
-extern int tl_module_message(ipc_callid_t, ipc_call_t *,
+extern int tl_message(ipc_callid_t, ipc_call_t *,
     ipc_call_t *, size_t *);
 
Index: uspace/lib/net/netif/netif_skel.c
===================================================================
--- uspace/lib/net/netif/netif_skel.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/netif/netif_skel.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,5 +40,4 @@
 #include <fibril_synch.h>
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/netif.h>
@@ -369,5 +368,5 @@
 	 * the initial IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
Index: uspace/lib/net/nil/nil_skel.c
===================================================================
--- uspace/lib/net/nil/nil_skel.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/nil/nil_skel.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -54,5 +54,5 @@
 	 * the initial IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
@@ -115,6 +115,5 @@
 		goto out;
 	
-	sysarg_t phonehash;
-	rc = ipc_connect_to_me(PHONE_NS, service, 0, 0, &phonehash);
+	rc = async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
 	if (rc != EOK)
 		goto out;
Index: uspace/lib/net/tl/icmp_remote.c
===================================================================
--- uspace/lib/net/tl/icmp_remote.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/tl/icmp_remote.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,8 +33,8 @@
 /** @file
  * ICMP interface implementation for remote modules.
- * @see icmp_interface.h
+ * @see icmp_remote.h
  */
 
-#include <icmp_interface.h>
+#include <icmp_remote.h>
 #include <net/modules.h>
 #include <packet_client.h>
@@ -42,5 +42,4 @@
 #include <async.h>
 #include <errno.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/icmp.h>
Index: uspace/lib/net/tl/tl_common.c
===================================================================
--- uspace/lib/net/tl/tl_common.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/tl/tl_common.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libnet 
+/** @addtogroup libnet
  * @{
  */
@@ -39,5 +39,5 @@
 #include <packet_client.h>
 #include <packet_remote.h>
-#include <icmp_interface.h>
+#include <icmp_remote.h>
 #include <ip_remote.h>
 #include <ip_interface.h>
Index: uspace/lib/net/tl/tl_skel.c
===================================================================
--- uspace/lib/net/tl/tl_skel.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/net/tl/tl_skel.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -54,5 +54,8 @@
 	 * the initial IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
+	
+	/* Per-connection initialization */
+	tl_connection();
 	
 	while (true) {
@@ -68,6 +71,5 @@
 		
 		/* Process the message */
-		int res = tl_module_message(callid, &call, &answer,
-		    &count);
+		int res = tl_message(callid, &call, &answer, &count);
 		
 		/*
@@ -115,6 +117,5 @@
 		goto out;
 	
-	sysarg_t phonehash;
-	rc = ipc_connect_to_me(PHONE_NS, service, 0, 0, &phonehash);
+	rc = async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
 	if (rc != EOK)
 		goto out;
Index: uspace/lib/packet/generic/packet_server.c
===================================================================
--- uspace/lib/packet/generic/packet_server.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/packet/generic/packet_server.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -44,9 +44,6 @@
 #include <unistd.h>
 #include <sys/mman.h>
-
-#include <ipc/ipc.h>
 #include <ipc/packet.h>
 #include <ipc/net.h>
-
 #include <net/packet.h>
 #include <net/packet_header.h>
@@ -292,10 +289,10 @@
 
 	if (!async_share_in_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);
+		async_answer_0(callid, EINVAL);
 		return EINVAL;
 	}
 
 	if (size != packet->length) {
-		ipc_answer_0(callid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
 		return ENOMEM;
 	}
Index: uspace/lib/packet/include/packet_server.h
===================================================================
--- uspace/lib/packet/include/packet_server.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/packet/include/packet_server.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,5 +45,5 @@
 #define LIBPACKET_PACKET_SERVER_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 
 extern int packet_server_message(ipc_callid_t, ipc_call_t *, ipc_call_t *,
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,16 +35,18 @@
 	src/addrkeep.c \
 	src/class.c \
+	src/ddfiface.c \
 	src/debug.c \
 	src/dp.c \
-	src/drvpsync.c \
-	src/hcdhubd.c \
-	src/hcdrv.c \
+	src/dump.c \
 	src/hidparser.c \
-	src/localdrv.c \
+	src/hub.c \
+	src/pipes.c \
+	src/pipesinit.c \
+	src/pipesio.c \
 	src/recognise.c \
-	src/remotedrv.c \
+	src/request.c \
 	src/usb.c \
-	src/usbdrvreq.c \
-	src/usbdrv.c
+	src/usbdevice.c \
+	src/usbmem.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usb/include/usb/addrkeep.h
===================================================================
--- uspace/lib/usb/include/usb/addrkeep.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/addrkeep.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB address keeping for host controller drivers.
+ */
+#ifndef LIBUSB_ADDRKEEP_H_
+#define LIBUSB_ADDRKEEP_H_
+
+#include <usb/usb.h>
+#include <fibril_synch.h>
+#include <devman.h>
+
+/** Info about used address. */
+typedef struct {
+	/** Linked list member. */
+	link_t link;
+	/** Address. */
+	usb_address_t address;
+	/** Corresponding devman handle. */
+	devman_handle_t devman_handle;
+} usb_address_keeping_used_t;
+
+/** Structure for keeping track of free and used USB addresses. */
+typedef struct {
+	/** Head of list of used addresses. */
+	link_t used_addresses;
+	/** Upper bound for USB addresses. */
+	usb_address_t max_address;
+	/** Mutex protecting used address. */
+	fibril_mutex_t used_addresses_guard;
+	/** Condition variable for used addresses. */
+	fibril_condvar_t used_addresses_condvar;
+
+	/** Condition variable mutex for default address. */
+	fibril_mutex_t default_condvar_guard;
+	/** Condition variable for default address. */
+	fibril_condvar_t default_condvar;
+	/** Whether is default address available. */
+	bool default_available;
+} usb_address_keeping_t;
+
+void usb_address_keeping_init(usb_address_keeping_t *, usb_address_t);
+
+void usb_address_keeping_reserve_default(usb_address_keeping_t *);
+void usb_address_keeping_release_default(usb_address_keeping_t *);
+
+usb_address_t usb_address_keeping_request(usb_address_keeping_t *);
+int usb_address_keeping_release(usb_address_keeping_t *, usb_address_t);
+void usb_address_keeping_devman_bind(usb_address_keeping_t *, usb_address_t,
+    devman_handle_t);
+usb_address_t usb_address_keeping_find(usb_address_keeping_t *,
+    devman_handle_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/classes/classes.h
===================================================================
--- uspace/lib/usb/include/usb/classes/classes.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/classes.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
Index: uspace/lib/usb/include/usb/classes/hid.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hid.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/hid.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -37,6 +37,6 @@
 
 #include <usb/usb.h>
-#include <driver.h>
 #include <usb/classes/hidparser.h>
+#include <usb/descriptor.h>
 
 /** USB/HID device requests. */
@@ -51,4 +51,21 @@
 } usb_hid_request_t;
 
+typedef enum {
+	USB_HID_REPORT_TYPE_INPUT = 1,
+	USB_HID_REPORT_TYPE_OUTPUT = 2,
+	USB_HID_REPORT_TYPE_FEATURE = 3
+} usb_hid_report_type_t;
+
+typedef enum {
+	USB_HID_PROTOCOL_BOOT = 0,
+	USB_HID_PROTOCOL_REPORT = 1
+} usb_hid_protocol_t;
+
+/** USB/HID subclass constants. */
+typedef enum {
+	USB_HID_SUBCLASS_NONE = 0,
+	USB_HID_SUBCLASS_BOOT = 1
+} usb_hid_subclass_t;
+
 /** USB/HID interface protocols. */
 typedef enum {
@@ -56,5 +73,5 @@
 	USB_HID_PROTOCOL_KEYBOARD = 1,
 	USB_HID_PROTOCOL_MOUSE = 2
-} usb_hid_protocol_t;
+} usb_hid_iface_protocol_t;
 
 /** Part of standard USB HID descriptor specifying one class descriptor.
@@ -63,9 +80,9 @@
  */
 typedef struct {
-	/** Type of class descriptor (Report or Physical). */
-	uint8_t class_descriptor_type;
-	/** Length of class descriptor. */
-	uint16_t class_descriptor_length;
-} __attribute__ ((packed)) usb_standard_hid_descriptor_class_item_t;
+	/** Type of class-specific descriptor (Report or Physical). */
+	uint8_t type;
+	/** Length of class-specific descriptor in bytes. */
+	uint16_t length;
+} __attribute__ ((packed)) usb_standard_hid_class_descriptor_info_t;
 
 /** Standard USB HID descriptor.
@@ -73,9 +90,14 @@
  * (See HID Specification, p.22)
  * 
- * It is actually only the "header" of the descriptor, as it may have arbitrary
- * length if more than one class descritor is provided.
+ * It is actually only the "header" of the descriptor, it does not contain
+ * the last two mandatory fields (type and length of the first class-specific
+ * descriptor).
  */
 typedef struct {
-	/** Size of this descriptor in bytes. */
+	/** Total size of this descriptor in bytes. 
+	 *
+	 * This includes all class-specific descriptor info - type + length 
+	 * for each descriptor.
+	 */
 	uint8_t length;
 	/** Descriptor type (USB_DESCTYPE_HID). */
@@ -85,22 +107,14 @@
 	/** Country code of localized hardware. */
 	uint8_t country_code;
-	/** Total number of class (i.e. Report and Physical) descriptors. */
-	uint8_t class_count;
-	/** First mandatory class descriptor info. */
-	usb_standard_hid_descriptor_class_item_t class_descriptor;
+	/** Total number of class-specific (i.e. Report and Physical) 
+	 * descriptors. 
+	 *
+	 * @note There is always only one Report descriptor.
+	 */
+	uint8_t class_desc_count;
+	/** First mandatory class descriptor (Report) info. */
+	usb_standard_hid_class_descriptor_info_t report_desc_info;
 } __attribute__ ((packed)) usb_standard_hid_descriptor_t;
 
-
-/**
- * @brief USB/HID keyboard device type.
- *
- * Quite dummy right now.
- */
-typedef struct {
-	device_t *device;
-	usb_address_t address;
-	usb_endpoint_t poll_endpoint;
-	usb_hid_report_parser_t *parser;
-} usb_hid_dev_kbd_t;
 
 #endif
Index: uspace/lib/usb/include/usb/classes/hidparser.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidparser.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/hidparser.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,10 +37,7 @@
 
 #include <stdint.h>
-#include <adt/list.h>
-
-#include <hid_report_items.h>
 
 /**
- * Items prefix
+ * Item prefix
  */
 #define USB_HID_ITEM_SIZE(data) 	((uint8_t)(data & 0x3))
@@ -62,24 +59,4 @@
 #define USB_HID_ITEM_FLAG_VOLATILE(flags)	(flags & 0x80)
 #define USB_HID_ITEM_FLAG_BUFFERED(flags)	(flags & 0x100)
-
-
-/**
- * Collection Item Types
- */
-#define USB_HID_COLLECTION_TYPE_PHYSICAL		0x00
-#define USB_HID_COLLECTION_TYPE_APPLICATION		0x01
-#define USB_HID_COLLECTION_TYPE_LOGICAL			0x02
-#define USB_HID_COLLECTION_TYPE_REPORT			0x03
-#define USB_HID_COLLECTION_TYPE_NAMED_ARRAY		0x04
-#define USB_HID_COLLECTION_TYPE_USAGE_SWITCH	0x05
-
-/*
- * modifiers definitions
- */
-#define USB_HID_BOOT_KEYBOARD_NUM_LOCK		0x01
-#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK		0x02
-#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK	0x04
-#define USB_HID_BOOT_KEYBOARD_COMPOSE		0x08
-#define USB_HID_BOOT_KEYBOARD_KANA			0x10
 
 
@@ -128,4 +105,5 @@
 
 
+
 /** HID parser callbacks for IN items. */
 typedef struct {
@@ -139,9 +117,60 @@
 } usb_hid_report_in_callbacks_t;
 
+
+typedef enum {
+	USB_HID_MOD_LCTRL = 0x01,
+	USB_HID_MOD_LSHIFT = 0x02,
+	USB_HID_MOD_LALT = 0x04,
+	USB_HID_MOD_LGUI = 0x08,
+	USB_HID_MOD_RCTRL = 0x10,
+	USB_HID_MOD_RSHIFT = 0x20,
+	USB_HID_MOD_RALT = 0x40,
+	USB_HID_MOD_RGUI = 0x80,
+	USB_HID_MOD_COUNT = 8
+} usb_hid_modifiers_t;
+
+typedef enum {
+	USB_HID_LED_NUM_LOCK = 0x1,
+	USB_HID_LED_CAPS_LOCK = 0x2,
+	USB_HID_LED_SCROLL_LOCK = 0x4,
+	USB_HID_LED_COMPOSE = 0x8,
+	USB_HID_LED_KANA = 0x10,
+	USB_HID_LED_COUNT = 5
+} usb_hid_led_t;
+
+static const usb_hid_modifiers_t 
+    usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = {
+	USB_HID_MOD_LCTRL,
+	USB_HID_MOD_LSHIFT,
+	USB_HID_MOD_LALT,
+	USB_HID_MOD_LGUI,
+	USB_HID_MOD_RCTRL,
+	USB_HID_MOD_RSHIFT,
+	USB_HID_MOD_RALT,
+	USB_HID_MOD_RGUI
+};
+
+//static const usb_hid_led_t usb_hid_led_consts[USB_HID_LED_COUNT] = {
+//	USB_HID_LED_NUM_LOCK,
+//	USB_HID_LED_CAPS_LOCK,
+//	USB_HID_LED_SCROLL_LOCK,
+//	USB_HID_LED_COMPOSE,
+//	USB_HID_LED_KANA
+//};
+
+//#define USB_HID_BOOT_KEYBOARD_NUM_LOCK		0x01
+//#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK		0x02
+//#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK	0x04
+//#define USB_HID_BOOT_KEYBOARD_COMPOSE		0x08
+//#define USB_HID_BOOT_KEYBOARD_KANA			0x10
+
+/*
+ * modifiers definitions
+ */
+
 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
 	const usb_hid_report_in_callbacks_t *callbacks, void *arg);
 
 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
-
 
 int usb_hid_parser_init(usb_hid_report_parser_t *parser);
@@ -157,4 +186,5 @@
 
 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
+
 #endif
 /**
Index: uspace/lib/usb/include/usb/classes/hidut.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidut.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/hidut.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
Index: uspace/lib/usb/include/usb/classes/hidutkbd.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidutkbd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/hidutkbd.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
Index: uspace/lib/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2010 Matus Dekanek
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -33,10 +33,8 @@
  * @brief USB hub related structures.
  */
-#ifndef LIBUSB_HUB_H_
-#define LIBUSB_HUB_H_
+#ifndef LIBUSB_CLASS_HUB_H_
+#define LIBUSB_CLASS_HUB_H_
 
 #include <sys/types.h>
-#include <usb/hcdhubd.h>
-
 
 /** Hub class feature selector.
@@ -68,5 +66,5 @@
  *	For more information see Universal Serial Bus Specification Revision 1.1 chapter 11.16.2
  */
-typedef struct hub_descriptor_type{
+typedef struct usb_hub_descriptor_type {
     /** Number of bytes in this descriptor, including this byte */
     //uint8_t bDescLength;
@@ -80,5 +78,5 @@
     /**
             D1...D0: Logical Power Switching Mode
-            00: Ganged power switching (all ports’ power at
+            00: Ganged power switching (all ports power at
             once)
             01: Individual port power switching
@@ -91,5 +89,5 @@
             00: Global Over-current Protection. The hub
             reports over-current as a summation of all
-            ports’ current draw, without a breakdown of
+            ports current draw, without a breakdown of
             individual port over-current status.
             01: Individual Port Over-current Protection. The
@@ -198,19 +196,4 @@
 extern size_t USB_HUB_MAX_DESCRIPTOR_SIZE;
 
-/**
- * @brief create uint8_t array with serialized descriptor
- *
- * @param descriptor
- */
-void * usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor);
-
-/**
- * @brief create deserialized desriptor structure out of serialized descriptor
- *
- * The serialized descriptor must be proper usb hub descriptor, otherwise an eerror might occur.
- *
- * @param sdescriptor serialized descriptor
- */
-usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * sdescriptor);
 
 
Index: uspace/lib/usb/include/usb/ddfiface.h
===================================================================
--- uspace/lib/usb/include/usb/ddfiface.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/ddfiface.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Implementations of DDF interfaces functions.
+ */
+#ifndef LIBUSB_DDFIFACE_H_
+#define LIBUSB_DDFIFACE_H_
+
+#include <sys/types.h>
+#include <usb/usbdevice.h>
+#include <usb_iface.h>
+
+int usb_iface_get_hc_handle_hub_impl(ddf_fun_t *, devman_handle_t *);
+int usb_iface_get_address_hub_impl(ddf_fun_t *, devman_handle_t,
+    usb_address_t *);
+extern usb_iface_t usb_iface_hub_impl;
+
+int usb_iface_get_hc_handle_hub_child_impl(ddf_fun_t *, devman_handle_t *);
+int usb_iface_get_address_hub_child_impl(ddf_fun_t *, devman_handle_t,
+    usb_address_t *);
+extern usb_iface_t usb_iface_hub_child_impl;
+
+int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *, devman_handle_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/debug.h
===================================================================
--- uspace/lib/usb/include/usb/debug.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/debug.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2010-2011 Vojtech Horky
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -35,8 +35,53 @@
 #ifndef LIBUSB_DEBUG_H_
 #define LIBUSB_DEBUG_H_
+#include <stdio.h>
+#include <usb/usb.h>
+#include <assert.h>
 
 void usb_dprintf(const char *tag, int level, const char *format, ...);
 void usb_dprintf_enable(const char *tag, int level);
 
+void usb_dump_standard_descriptor(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+
+/** Logging level. */
+typedef enum {
+	USB_LOG_LEVEL_FATAL,
+	USB_LOG_LEVEL_ERROR,
+	USB_LOG_LEVEL_WARNING,
+	USB_LOG_LEVEL_INFO,
+	USB_LOG_LEVEL_DEBUG,
+	USB_LOG_LEVEL_DEBUG2,
+	USB_LOG_LEVEL_MAX
+} usb_log_level_t;
+
+
+void usb_log_enable(usb_log_level_t, const char *);
+
+void usb_log_printf(usb_log_level_t, const char *, ...);
+
+#define usb_log_fatal(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_FATAL, format, ##__VA_ARGS__)
+
+#define usb_log_error(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_ERROR, format, ##__VA_ARGS__)
+
+#define usb_log_warning(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_WARNING, format, ##__VA_ARGS__)
+
+#define usb_log_info(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_INFO, format, ##__VA_ARGS__)
+
+#define usb_log_debug(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
+
+#define usb_log_debug2(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_DEBUG2, format, ##__VA_ARGS__)
+
+
 
 #endif
+/**
+ * @}
+ */
+
Index: uspace/lib/usb/include/usb/descriptor.h
===================================================================
--- uspace/lib/usb/include/usb/descriptor.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/descriptor.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -36,5 +36,4 @@
 #define LIBUSB_DESCRIPTOR_H_
 
-#include <ipc/ipc.h>
 #include <async.h>
 
Index: pace/lib/usb/include/usb/devreq.h
===================================================================
--- uspace/lib/usb/include/usb/devreq.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,113 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief Standard USB device requests.
- */
-#ifndef LIBUSB_DEVREQ_H_
-#define LIBUSB_DEVREQ_H_
-
-#include <ipc/ipc.h>
-#include <async.h>
-#include <usb/usb.h>
-#include <usb/descriptor.h>
-
-/** Standard device request. */
-typedef enum {
-	USB_DEVREQ_GET_STATUS = 0,
-	USB_DEVREQ_CLEAR_FEATURE = 1,
-	USB_DEVREQ_SET_FEATURE = 3,
-	USB_DEVREQ_SET_ADDRESS = 5,
-	USB_DEVREQ_GET_DESCRIPTOR = 6,
-	USB_DEVREQ_SET_DESCRIPTOR = 7,
-	USB_DEVREQ_GET_CONFIGURATION = 8,
-	USB_DEVREQ_SET_CONFIGURATION = 9,
-	USB_DEVREQ_GET_INTERFACE = 10,
-	USB_DEVREQ_SET_INTERFACE = 11,
-	USB_DEVREQ_SYNCH_FRAME = 12,
-	USB_DEVREQ_LAST_STD
-} usb_stddevreq_t;
-
-/** Device request setup packet.
- * The setup packet describes the request.
- */
-typedef struct {
-	/** Request type.
-	 * The type combines transfer direction, request type and
-	 * intended recipient.
-	 */
-	uint8_t request_type;
-	/** Request identification. */
-	uint8_t request;
-	/** Main parameter to the request. */
-	union {
-		/* FIXME: add #ifdefs according to host endianess */
-		struct {
-			uint8_t value_low;
-			uint8_t value_high;
-		};
-		uint16_t value;
-	};
-	/** Auxiliary parameter to the request.
-	 * Typically, it is offset to something.
-	 */
-	uint16_t index;
-	/** Length of extra data. */
-	uint16_t length;
-} __attribute__ ((packed)) usb_device_request_setup_packet_t;
-
-
-int usb_drv_req_get_status(int, usb_address_t, usb_request_recipient_t,
-    uint16_t, uint16_t *);
-int usb_drv_req_clear_feature(int, usb_address_t, usb_request_recipient_t,
-    uint16_t, uint16_t);
-int usb_drv_req_set_feature(int, usb_address_t, usb_request_recipient_t,
-    uint16_t, uint16_t);
-int usb_drv_req_set_address(int, usb_address_t, usb_address_t);
-int usb_drv_req_get_descriptor(int, usb_address_t, usb_request_type_t,
-    uint8_t, uint8_t, uint16_t, void *, size_t, size_t *);
-int usb_drv_req_get_device_descriptor(int, usb_address_t,
-    usb_standard_device_descriptor_t *);
-int usb_drv_req_get_bare_configuration_descriptor(int, usb_address_t, int,
-    usb_standard_configuration_descriptor_t *);
-int usb_drv_req_get_full_configuration_descriptor(int, usb_address_t, int,
-    void *, size_t, size_t *);
-int usb_drv_req_set_descriptor(int, usb_address_t, uint8_t, uint8_t, uint16_t,
-    void *, size_t);
-int usb_drv_req_get_configuration(int, usb_address_t, uint8_t *);
-int usb_drv_req_set_configuration(int, usb_address_t, uint8_t);
-int usb_drv_req_get_interface(int, usb_address_t, uint16_t, uint8_t *);
-int usb_drv_req_set_interface(int, usb_address_t, uint16_t, uint8_t);
-
-#endif
-/**
- * @}
- */
Index: uspace/lib/usb/include/usb/dp.h
===================================================================
--- uspace/lib/usb/include/usb/dp.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/dp.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,4 +45,6 @@
 } usb_dp_descriptor_nesting_t;
 
+extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
+
 typedef struct {
 	usb_dp_descriptor_nesting_t *nesting;
Index: pace/lib/usb/include/usb/hcd.h
===================================================================
--- uspace/lib/usb/include/usb/hcd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,84 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief HC driver.
- */
-#ifndef LIBUSB_HCD_H_
-#define LIBUSB_HCD_H_
-
-#include <usb/usb.h>
-#include <fibril_synch.h>
-#include <devman.h>
-
-/** Info about used address. */
-typedef struct {
-	/** Linked list member. */
-	link_t link;
-	/** Address. */
-	usb_address_t address;
-	/** Corresponding devman handle. */
-	devman_handle_t devman_handle;
-} usb_address_keeping_used_t;
-
-/** Structure for keeping track of free and used USB addresses. */
-typedef struct {
-	/** Head of list of used addresses. */
-	link_t used_addresses;
-	/** Upper bound for USB addresses. */
-	usb_address_t max_address;
-	/** Mutex protecting used address. */
-	fibril_mutex_t used_addresses_guard;
-	/** Condition variable for used addresses. */
-	fibril_condvar_t used_addresses_condvar;
-
-	/** Condition variable mutex for default address. */
-	fibril_mutex_t default_condvar_guard;
-	/** Condition variable for default address. */
-	fibril_condvar_t default_condvar;
-	/** Whether is default address available. */
-	bool default_available;
-} usb_address_keeping_t;
-
-void usb_address_keeping_init(usb_address_keeping_t *, usb_address_t);
-
-void usb_address_keeping_reserve_default(usb_address_keeping_t *);
-void usb_address_keeping_release_default(usb_address_keeping_t *);
-
-usb_address_t usb_address_keeping_request(usb_address_keeping_t *);
-int usb_address_keeping_release(usb_address_keeping_t *, usb_address_t);
-void usb_address_keeping_devman_bind(usb_address_keeping_t *, usb_address_t,
-    devman_handle_t);
-usb_address_t usb_address_keeping_find(usb_address_keeping_t *,
-    devman_handle_t);
-
-
-#endif
Index: pace/lib/usb/include/usb/hcdhubd.h
===================================================================
--- uspace/lib/usb/include/usb/hcdhubd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,214 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief HC driver and hub driver.
- */
-#ifndef LIBUSB_HCDHUBD_H_
-#define LIBUSB_HCDHUBD_H_
-
-#include <adt/list.h>
-#include <bool.h>
-#include <driver.h>
-#include <usb/usb.h>
-
-/** Endpoint properties. */
-typedef struct {
-	/** Endpoint number. */
-	usb_endpoint_t endpoint;
-	/** Transfer type. */
-	usb_transfer_type_t transfer_type;
-	/** Endpoint direction. */
-	usb_direction_t direction;
-	/** Data toggle bit. */
-	int data_toggle;
-} usb_hc_endpoint_info_t;
-
-/** Information about attached USB device. */
-typedef struct {
-	/** Assigned address. */
-	usb_address_t address;
-	/** Number of endpoints. */
-	size_t endpoint_count;
-	/** Endpoint properties. */
-	usb_hc_endpoint_info_t *endpoints;
-	/** Link to other attached devices of the same HC. */
-	link_t link;
-} usb_hcd_attached_device_info_t;
-
-
-/** Host controller device. */
-typedef struct usb_hc_device usb_hc_device_t;
-
-/** Callback for OUT transfers. */
-typedef void (*usb_hcd_transfer_callback_out_t)
-    (usb_hc_device_t *, usb_transaction_outcome_t, void *);
-
-/** Callback for IN transfers. */
-typedef void (*usb_hcd_transfer_callback_in_t)
-    (usb_hc_device_t *, size_t, usb_transaction_outcome_t, void *);
-
-
-/** Transfer functions provided by each USB host controller driver. */
-typedef struct {
-	/** OUT transfer.
-	 * @param hc Host controller that shall enqueue the transfer.
-	 * @param dev Target device.
-	 * @param ep Target endpoint.
-	 * @param buffer Buffer to be sent.
-	 * @param size Buffer size.
-	 * @param callback Callback after transfer was processed by hardware.
-	 * @param arg Callback argument.
-	 */
-	int (*transfer_out)(usb_hc_device_t *hc,
-	    usb_hcd_attached_device_info_t *dev, usb_hc_endpoint_info_t *ep,
-	    void *buffer, size_t size,
-	    usb_hcd_transfer_callback_out_t callback, void *arg);
-
-	/** SETUP transfer. */
-	int (*transfer_setup)(usb_hc_device_t *,
-	    usb_hcd_attached_device_info_t *, usb_hc_endpoint_info_t *,
-	    void *, size_t,
-	    usb_hcd_transfer_callback_out_t, void *);
-
-	/** IN transfer. */
-	int (*transfer_in)(usb_hc_device_t *,
-	    usb_hcd_attached_device_info_t *, usb_hc_endpoint_info_t *,
-	    void *, size_t,
-	    usb_hcd_transfer_callback_in_t, void *);
-} usb_hcd_transfer_ops_t;
-
-/**
- * @brief structure holding information about free and used addresses
- *
- * This structure should not be used outside usb hcd driver.
- * You better consider it to be 'private'.
- */
-typedef struct {
-	/** lower bound included in the interval */
-	usb_address_t lower_bound;
-
-	/** upper bound, excluded from the interval */
-	usb_address_t upper_bound;
-
-	/** */
-	link_t link;
-}usb_address_list_t;
-
-struct usb_hc_device {
-	/** Transfer operations. */
-	usb_hcd_transfer_ops_t *transfer_ops;
-
-	/** Custom HC data. */
-	void *data;
-
-	/** Generic device entry (read-only). */
-	device_t *generic;
-
-	/** List of attached devices. */
-	link_t attached_devices;
-
-	/** List of hubs operating from this HC. */
-	link_t hubs;
-
-	/** Structure with free and used addresses */
-	link_t addresses;
-
-	/** Link to other driven HCs. */
-	link_t link;
-};
-
-/** Host controller driver. */
-typedef struct {
-	/** Driver name. */
-	const char *name;
-	/** Callback when device (host controller) is added. */
-	int (*add_hc)(usb_hc_device_t *device);
-} usb_hc_driver_t;
-
-
-int usb_hcd_main(usb_hc_driver_t *);
-int usb_hcd_add_root_hub(device_t *dev);
-
-/**
- * find first not yet used address on this host controller and use it
- * @param this_hcd
- * @return number in the range of allowed usb addresses or
- *     a negative number if not succesful
- */
-usb_address_t usb_use_free_address(usb_hc_device_t * this_hcd);
-
-/**
- * @brief free the address in the address space of this hcd.
- *
- * if address is not used, nothing happens
- * @param this_hcd
- * @param addr
- */
-void usb_free_used_address(usb_hc_device_t * this_hcd, usb_address_t addr );
-
-
-/*
- * Functions to be used by drivers within same task as the HC driver.
- * This will probably include only hub drivers.
- */
-
-device_t *usb_hc_connect(device_t *);
-
-int usb_hc_async_interrupt_out(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_interrupt_in(usb_hc_device_t *, usb_target_t,
-    void *, size_t, size_t *, usb_handle_t *);
-
-int usb_hc_async_control_write_setup(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_control_write_data(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_control_write_status(usb_hc_device_t *, usb_target_t,
-    usb_handle_t *);
-
-int usb_hc_async_control_read_setup(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_control_read_data(usb_hc_device_t *, usb_target_t,
-    void *, size_t, size_t *, usb_handle_t *);
-int usb_hc_async_control_read_status(usb_hc_device_t *, usb_target_t,
-    usb_handle_t *);
-
-int usb_hc_async_wait_for(usb_handle_t);
-
-int usb_hc_add_child_device(device_t *, const char *, const char *, bool);
-
-
-/**
- * @}
- */
-
-#endif
Index: uspace/lib/usb/include/usb/hub.h
===================================================================
--- uspace/lib/usb/include/usb/hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Functions needed by hub drivers.
+ */
+#ifndef LIBUSB_HUB_H_
+#define LIBUSB_HUB_H_
+
+#include <sys/types.h>
+#include <usb/usbdevice.h>
+
+int usb_hc_new_device_wrapper(ddf_dev_t *, usb_hc_connection_t *, usb_speed_t,
+    int (*)(int, void *), int, void *,
+    usb_address_t *, devman_handle_t *,
+    ddf_dev_ops_t *, void *, ddf_fun_t **);
+
+/** Info about device attached to host controller.
+ *
+ * This structure exists only to keep the same signature of
+ * usb_hc_register_device() when more properties of the device
+ * would have to be passed to the host controller.
+ */
+typedef struct {
+	/** Device address. */
+	usb_address_t address;
+	/** Devman handle of the device. */
+	devman_handle_t handle;
+} usb_hc_attached_device_t;
+
+int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);
+int usb_hc_release_default_address(usb_hc_connection_t *);
+
+usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
+int usb_hc_register_device(usb_hc_connection_t *,
+    const usb_hc_attached_device_t *);
+int usb_hc_unregister_device(usb_hc_connection_t *, usb_address_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/pipes.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB pipes representation.
+ */
+#ifndef LIBUSB_PIPES_H_
+#define LIBUSB_PIPES_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/usbdevice.h>
+#include <usb/descriptor.h>
+#include <ipc/devman.h>
+#include <ddf/driver.h>
+
+/**
+ * Abstraction of a physical connection to the device.
+ * This type is an abstraction of the USB wire that connects the host and
+ * the function (device).
+ */
+typedef struct {
+	/** Handle of the host controller device is connected to. */
+	devman_handle_t hc_handle;
+	/** Address of the device. */
+	usb_address_t address;
+} usb_device_connection_t;
+
+/**
+ * Abstraction of a logical connection to USB device endpoint.
+ * It encapsulates endpoint attributes (transfer type etc.) as well
+ * as information about currently running sessions.
+ * This endpoint must be bound with existing usb_device_connection_t
+ * (i.e. the wire to send data over).
+ */
+typedef struct {
+	/** The connection used for sending the data. */
+	usb_device_connection_t *wire;
+
+	/** Endpoint number. */
+	usb_endpoint_t endpoint_no;
+
+	/** Endpoint transfer type. */
+	usb_transfer_type_t transfer_type;
+
+	/** Endpoint direction. */
+	usb_direction_t direction;
+
+	/** Maximum packet size for the endpoint. */
+	size_t max_packet_size;
+
+	/** Phone to the host controller.
+	 * Negative when no session is active.
+	 */
+	int hc_phone;
+} usb_endpoint_pipe_t;
+
+
+/** Description of endpoint characteristics. */
+typedef struct {
+	/** Transfer type (e.g. control or interrupt). */
+	usb_transfer_type_t transfer_type;
+	/** Transfer direction (to or from a device). */
+	usb_direction_t direction;
+	/** Interface class this endpoint belongs to (-1 for any). */
+	int interface_class;
+	/** Interface subclass this endpoint belongs to (-1 for any). */
+	int interface_subclass;
+	/** Interface protocol this endpoint belongs to (-1 for any). */
+	int interface_protocol;
+	/** Extra endpoint flags. */
+	unsigned int flags;
+} usb_endpoint_description_t;
+
+/** Mapping of endpoint pipes and endpoint descriptions. */
+typedef struct {
+	/** Endpoint pipe. */
+	usb_endpoint_pipe_t *pipe;
+	/** Endpoint description. */
+	const usb_endpoint_description_t *description;
+	/** Interface number the endpoint must belong to (-1 for any). */
+	const int interface_no;
+	/** Found descriptor fitting the description. */
+	usb_standard_endpoint_descriptor_t *descriptor;
+	/** Interface the endpoint belongs to. */
+	usb_standard_interface_descriptor_t *interface;
+	/** Whether the endpoint was actually found. */
+	bool present;
+} usb_endpoint_mapping_t;
+
+int usb_device_connection_initialize_on_default_address(
+    usb_device_connection_t *, usb_hc_connection_t *);
+int usb_device_connection_initialize_from_device(usb_device_connection_t *,
+    ddf_dev_t *);
+int usb_device_connection_initialize(usb_device_connection_t *,
+    devman_handle_t, usb_address_t);
+
+int usb_device_get_assigned_interface(ddf_dev_t *);
+
+int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *,
+    usb_device_connection_t *,
+    usb_endpoint_t, usb_transfer_type_t, size_t, usb_direction_t);
+int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *,
+    usb_device_connection_t *);
+int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
+    size_t, uint8_t *, size_t, usb_device_connection_t *);
+
+
+int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *);
+int usb_endpoint_pipe_end_session(usb_endpoint_pipe_t *);
+bool usb_endpoint_pipe_is_session_started(usb_endpoint_pipe_t *);
+
+int usb_endpoint_pipe_read(usb_endpoint_pipe_t *, void *, size_t, size_t *);
+int usb_endpoint_pipe_write(usb_endpoint_pipe_t *, void *, size_t);
+
+int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *, void *, size_t,
+    void *, size_t, size_t *);
+int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *, void *, size_t,
+    void *, size_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/recognise.h
===================================================================
--- uspace/lib/usb/include/usb/recognise.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/recognise.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB device recognition.
+ */
+#ifndef LIBUSB_RECOGNISE_H_
+#define LIBUSB_RECOGNISE_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <ipc/devman.h>
+
+int usb_device_create_match_ids_from_device_descriptor(
+    const usb_standard_device_descriptor_t *, match_id_list_t *);
+
+int usb_device_create_match_ids_from_interface(
+    const usb_standard_device_descriptor_t *,
+    const usb_standard_interface_descriptor_t *, match_id_list_t *);
+
+int usb_device_create_match_ids(usb_endpoint_pipe_t *, match_id_list_t *);
+
+int usb_device_register_child_in_devman(usb_address_t, devman_handle_t,
+    ddf_dev_t *, devman_handle_t *, ddf_dev_ops_t *, void *, ddf_fun_t **);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/request.h
===================================================================
--- uspace/lib/usb/include/usb/request.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/request.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Standard USB requests.
+ */
+#ifndef LIBUSB_REQUEST_H_
+#define LIBUSB_REQUEST_H_
+
+#include <sys/types.h>
+#include <l18n/langs.h>
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <usb/descriptor.h>
+
+/** Standard device request. */
+typedef enum {
+	USB_DEVREQ_GET_STATUS = 0,
+	USB_DEVREQ_CLEAR_FEATURE = 1,
+	USB_DEVREQ_SET_FEATURE = 3,
+	USB_DEVREQ_SET_ADDRESS = 5,
+	USB_DEVREQ_GET_DESCRIPTOR = 6,
+	USB_DEVREQ_SET_DESCRIPTOR = 7,
+	USB_DEVREQ_GET_CONFIGURATION = 8,
+	USB_DEVREQ_SET_CONFIGURATION = 9,
+	USB_DEVREQ_GET_INTERFACE = 10,
+	USB_DEVREQ_SET_INTERFACE = 11,
+	USB_DEVREQ_SYNCH_FRAME = 12,
+	USB_DEVREQ_LAST_STD
+} usb_stddevreq_t;
+
+/** Device request setup packet.
+ * The setup packet describes the request.
+ */
+typedef struct {
+	/** Request type.
+	 * The type combines transfer direction, request type and
+	 * intended recipient.
+	 */
+	uint8_t request_type;
+	/** Request identification. */
+	uint8_t request;
+	/** Main parameter to the request. */
+	union {
+		uint16_t value;
+		/* FIXME: add #ifdefs according to host endianess */
+		struct {
+			uint8_t value_low;
+			uint8_t value_high;
+		};
+	};
+	/** Auxiliary parameter to the request.
+	 * Typically, it is offset to something.
+	 */
+	uint16_t index;
+	/** Length of extra data. */
+	uint16_t length;
+} __attribute__ ((packed)) usb_device_request_setup_packet_t;
+
+int usb_control_request_set(usb_endpoint_pipe_t *,
+    usb_request_type_t, usb_request_recipient_t, uint8_t,
+    uint16_t, uint16_t, void *, size_t);
+
+int usb_control_request_get(usb_endpoint_pipe_t *,
+    usb_request_type_t, usb_request_recipient_t, uint8_t,
+    uint16_t, uint16_t, void *, size_t, size_t *);
+
+int usb_request_set_address(usb_endpoint_pipe_t *, usb_address_t);
+int usb_request_get_descriptor(usb_endpoint_pipe_t *, usb_request_type_t,
+    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t, 
+    size_t *);
+int usb_request_get_descriptor_alloc(usb_endpoint_pipe_t *, usb_request_type_t,
+    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void **, size_t *);
+int usb_request_get_device_descriptor(usb_endpoint_pipe_t *,
+    usb_standard_device_descriptor_t *);
+int usb_request_get_bare_configuration_descriptor(usb_endpoint_pipe_t *, int,
+    usb_standard_configuration_descriptor_t *);
+int usb_request_get_full_configuration_descriptor(usb_endpoint_pipe_t *, int,
+    void *, size_t, size_t *);
+int usb_request_set_configuration(usb_endpoint_pipe_t *, uint8_t);
+
+int usb_request_get_supported_languages(usb_endpoint_pipe_t *,
+    l18_win_locales_t **, size_t *);
+int usb_request_get_string(usb_endpoint_pipe_t *, size_t, l18_win_locales_t,
+    char **);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/usb.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -37,5 +37,18 @@
 
 #include <sys/types.h>
-#include <ipc/ipc.h>
+#include <byteorder.h>
+
+/** Convert 16bit value from native (host) endianness to USB endianness. */
+#define uint16_host2usb(n) host2uint16_t_le((n))
+
+/** Convert 32bit value from native (host) endianness to USB endianness. */
+#define uint32_host2usb(n) host2uint32_t_le((n))
+
+/** Convert 16bit value from USB endianness into native (host) one. */
+#define uint16_usb2host(n) uint16_t_le2host((n))
+
+/** Convert 32bit value from USB endianness into native (host) one. */
+#define uint32_usb2host(n) uint32_t_le2host((n))
+
 
 /** USB transfer type. */
@@ -52,6 +65,17 @@
 typedef enum {
 	USB_DIRECTION_IN,
-	USB_DIRECTION_OUT
+	USB_DIRECTION_OUT,
+	USB_DIRECTION_BOTH
 } usb_direction_t;
+
+/** USB speeds. */
+typedef enum {
+	/** USB 1.1 low speed (1.5Mbits/s). */
+	USB_SPEED_LOW,
+	/** USB 1.1 full speed (12Mbits/s). */
+	USB_SPEED_FULL,
+	/** USB 2.0 high speed (480Mbits/s). */
+	USB_SPEED_HIGH
+} usb_speed_t;
 
 /** USB request type target. */
@@ -68,13 +92,4 @@
 	USB_REQUEST_RECIPIENT_ENDPOINT = 2
 } usb_request_recipient_t;
-
-/** USB transaction outcome. */
-typedef enum {
-	USB_OUTCOME_OK,
-	USB_OUTCOME_CRCERROR,
-	USB_OUTCOME_BABBLE
-} usb_transaction_outcome_t;
-
-const char * usb_str_transaction_outcome(usb_transaction_outcome_t o);
 
 /** USB address type.
Index: uspace/lib/usb/include/usb/usbdevice.h
===================================================================
--- uspace/lib/usb/include/usb/usbdevice.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/usbdevice.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * General communication between device drivers and host controller driver.
+ */
+#ifndef LIBUSB_USBDEVICE_H_
+#define LIBUSB_USBDEVICE_H_
+
+#include <sys/types.h>
+#include <ipc/devman.h>
+#include <ddf/driver.h>
+#include <bool.h>
+#include <usb/usb.h>
+
+/** Connection to the host controller driver. */
+typedef struct {
+	/** Devman handle of the host controller. */
+	devman_handle_t hc_handle;
+	/** Phone to the host controller. */
+	int hc_phone;
+} usb_hc_connection_t;
+
+int usb_hc_find(devman_handle_t, devman_handle_t *);
+
+int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
+    ddf_dev_t *);
+int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t);
+
+int usb_hc_connection_open(usb_hc_connection_t *);
+bool usb_hc_connection_is_opened(const usb_hc_connection_t *);
+int usb_hc_connection_close(usb_hc_connection_t *);
+
+
+
+#endif
+/**
+ * @}
+ */
Index: pace/lib/usb/include/usb/usbdrv.h
===================================================================
--- uspace/lib/usb/include/usb/usbdrv.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,111 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief USB driver.
- */
-#ifndef LIBUSB_USBDRV_H_
-#define LIBUSB_USBDRV_H_
-
-#include <usb/usb.h>
-#include <driver.h>
-#include <usb/devreq.h>
-#include <usb/descriptor.h>
-
-int usb_drv_find_hc(device_t *, devman_handle_t *);
-int usb_drv_hc_connect(device_t *, devman_handle_t, unsigned int);
-int usb_drv_hc_connect_auto(device_t *, unsigned int);
-
-int usb_drv_reserve_default_address(int);
-int usb_drv_release_default_address(int);
-usb_address_t usb_drv_request_address(int);
-int usb_drv_bind_address(int, usb_address_t, devman_handle_t);
-int usb_drv_release_address(int, usb_address_t);
-
-usb_address_t usb_drv_get_my_address(int, device_t *);
-
-int usb_drv_async_interrupt_out(int, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_drv_async_interrupt_in(int, usb_target_t,
-    void *, size_t, size_t *, usb_handle_t *);
-
-int usb_drv_psync_interrupt_out(int, usb_target_t, void *, size_t);
-int usb_drv_psync_interrupt_in(int, usb_target_t, void *, size_t, size_t *);
-
-
-
-int usb_drv_async_control_write_setup(int, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_drv_async_control_write_data(int, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_drv_async_control_write_status(int, usb_target_t,
-    usb_handle_t *);
-
-int usb_drv_psync_control_write_setup(int, usb_target_t, void *, size_t);
-int usb_drv_psync_control_write_data(int, usb_target_t, void *, size_t);
-int usb_drv_psync_control_write_status(int, usb_target_t);
-
-int usb_drv_psync_control_write(int, usb_target_t,
-    void *, size_t, void *, size_t);
-
-
-int usb_drv_async_control_read_setup(int, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_drv_async_control_read_data(int, usb_target_t,
-    void *, size_t, size_t *, usb_handle_t *);
-int usb_drv_async_control_read_status(int, usb_target_t,
-    usb_handle_t *);
-
-int usb_drv_psync_control_read_setup(int, usb_target_t, void *, size_t);
-int usb_drv_psync_control_read_data(int, usb_target_t, void *, size_t, size_t *);
-int usb_drv_psync_control_read_status(int, usb_target_t);
-
-int usb_drv_psync_control_read(int, usb_target_t,
-    void *, size_t, void *, size_t, size_t *);
-
-
-
-int usb_drv_async_wait_for(usb_handle_t);
-
-int usb_drv_create_match_ids_from_device_descriptor(match_id_list_t *,
-    const usb_standard_device_descriptor_t *);
-int usb_drv_create_match_ids_from_configuration_descriptor(match_id_list_t *,
-    const void *, size_t);
-
-int usb_drv_create_device_match_ids(int, match_id_list_t *, usb_address_t);
-int usb_drv_register_child_in_devman(int, device_t *, usb_address_t,
-    devman_handle_t *);
-
-
-#endif
-/**
- * @}
- */
Index: uspace/lib/usb/include/usb/usbmem.h
===================================================================
--- uspace/lib/usb/include/usb/usbmem.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/usbmem.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 Matus Dekanek
+ * 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.
+ */
+
+#ifndef USBMEM_H
+#define	USBMEM_H
+
+
+// group should be changed - this is not usb specific
+/** @addtogroup usb
+ * @{
+ */
+/** @file definitions of memory management with address translation, used mostly in usb stack
+ *
+ * USB HCD needs traslation between physical and virtual addresses. These
+ * functions implement such functionality. For each allocated virtual address
+ * the memory manager gets also it`s physical translation and remembers it.
+ * Addresses allocated byt this manager can be therefore translated from and to
+ * physical addresses.
+ * Typical use:
+ * void * address = mman_malloc(some_size);
+ * void * physical_address = mman_getPA(address);
+ * void * the_same_address = mman_getVA(physical_address);
+ * void * null_address = mman_getPA(non_existing_address);
+ * mman_free(address);
+ * // physical_address, adress and the_same_address are no longer valid here
+ *
+ *
+ * @note Addresses allocated by this memory manager should be as well
+ * deallocated byt it.
+ *
+ */
+
+#include <sys/types.h>
+
+extern void * mman_malloc(
+    size_t size,
+    size_t alignment,
+    unsigned long max_physical_address);
+
+extern void * mman_getVA(void * addr);
+
+extern void * mman_getPA(void * addr);
+
+extern void mman_free(void * addr);
+
+
+
+
+
+
+/** @}
+ */
+
+
+#endif	/* USBMEM_H */
+
Index: uspace/lib/usb/src/addrkeep.c
===================================================================
--- uspace/lib/usb/src/addrkeep.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/addrkeep.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -33,5 +33,5 @@
  * @brief Address keeping.
  */
-#include <usb/hcd.h>
+#include <usb/addrkeep.h>
 #include <errno.h>
 #include <assert.h>
@@ -149,4 +149,5 @@
 			&addresses->default_condvar_guard);
 	}
+	addresses->default_available = false;
 	fibril_mutex_unlock(&addresses->default_condvar_guard);
 }
Index: uspace/lib/usb/src/class.c
===================================================================
--- uspace/lib/usb/src/class.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/class.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
Index: uspace/lib/usb/src/ddfiface.c
===================================================================
--- uspace/lib/usb/src/ddfiface.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/ddfiface.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Implementations of DDF interfaces functions (actual implementation).
+ */
+#include <ipc/devman.h>
+#include <devman.h>
+#include <async.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <assert.h>
+
+/** DDF interface for USB device, implementation for typical hub. */
+usb_iface_t  usb_iface_hub_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_impl,
+	.get_address = usb_iface_get_address_hub_impl
+};
+
+/** DDF interface for USB device, implementation for child of a typical hub. */
+usb_iface_t  usb_iface_hub_child_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
+	.get_address = usb_iface_get_address_hub_child_impl
+};
+
+
+/** Get host controller handle, interface implementation for hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Error code.
+ */
+int usb_iface_get_hc_handle_hub_impl(ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+	return usb_hc_find(fun->handle, handle);
+}
+
+/** Get host controller handle, interface implementation for child of
+ * a hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Error code.
+ */
+int usb_iface_get_hc_handle_hub_child_impl(ddf_fun_t *fun,
+    devman_handle_t *handle)
+{
+	assert(fun != NULL);
+
+	int parent_phone = devman_parent_device_connect(fun->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	sysarg_t hc_handle;
+	int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &hc_handle);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	*handle = hc_handle;
+
+	return EOK;
+}
+
+/** Get host controller handle, interface implementation for HC driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Always EOK.
+ */
+int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+
+	if (handle != NULL) {
+		*handle = fun->handle;
+	}
+
+	return EOK;
+}
+
+/** Get USB device address, interface implementation for hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[in] handle Devman handle of USB device we want address of.
+ * @param[out] address Storage for USB address of device with handle @p handle.
+ * @return Error code.
+ */
+int usb_iface_get_address_hub_impl(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	assert(fun);
+	int parent_phone = devman_parent_device_connect(fun->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	sysarg_t addr;
+	int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_ADDRESS, handle, &addr);
+
+	async_hangup(parent_phone);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (address != NULL) {
+		*address = (usb_address_t) addr;
+	}
+
+	return EOK;
+}
+
+/** Get USB device address, interface implementation for child of
+ * a hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[in] handle Devman handle of USB device we want address of.
+ * @param[out] address Storage for USB address of device with handle @p handle.
+ * @return Error code.
+ */
+int usb_iface_get_address_hub_child_impl(ddf_fun_t *fun,
+    devman_handle_t handle, usb_address_t *address)
+{
+	if (handle == 0) {
+		handle = fun->handle;
+	}
+	return usb_iface_get_address_hub_impl(fun, handle, address);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/debug.c
===================================================================
--- uspace/lib/usb/src/debug.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/debug.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2010-2011 Vojtech Horky
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -60,4 +60,12 @@
 /** Mutex guard for the list of all tags. */
 static FIBRIL_MUTEX_INITIALIZE(tag_list_guard);
+
+/** Level of logging messages. */
+static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
+/** Prefix for logging messages. */
+static const char *log_prefix = "usb";
+/** Serialization mutex for logging functions. */
+static FIBRIL_MUTEX_INITIALIZE(log_serializer);
+static FILE *log_stream = NULL;
 
 /** Find or create new tag with given name.
@@ -155,4 +163,92 @@
 }
 
+/** Enable logging.
+ *
+ * @param level Maximal enabled level (including this one).
+ * @param message_prefix Prefix for each printed message.
+ */
+void usb_log_enable(usb_log_level_t level, const char *message_prefix)
+{
+	log_prefix = message_prefix;
+	log_level = level;
+	if (log_stream == NULL) {
+		char *fname;
+		int rc = asprintf(&fname, "/log/%s", message_prefix);
+		if (rc > 0) {
+			log_stream = fopen(fname, "w");
+			free(fname);
+		}
+	}
+}
+
+
+static const char *log_level_name(usb_log_level_t level)
+{
+	switch (level) {
+		case USB_LOG_LEVEL_FATAL:
+			return " FATAL";
+		case USB_LOG_LEVEL_ERROR:
+			return " ERROR";
+		case USB_LOG_LEVEL_WARNING:
+			return " WARN";
+		case USB_LOG_LEVEL_INFO:
+			return " info";
+		default:
+			return "";
+	}
+}
+
+/** Print logging message.
+ *
+ * @param level Verbosity level of the message.
+ * @param format Formatting directive.
+ */
+void usb_log_printf(usb_log_level_t level, const char *format, ...)
+{
+	FILE *screen_stream = NULL;
+	switch (level) {
+		case USB_LOG_LEVEL_FATAL:
+		case USB_LOG_LEVEL_ERROR:
+			screen_stream = stderr;
+			break;
+		default:
+			screen_stream = stdout;
+			break;
+	}
+	assert(screen_stream != NULL);
+
+	va_list args;
+
+	/*
+	 * Serialize access to log files.
+	 * Always print to log file, to screen print only when the enabled
+	 * log level is high enough.
+	 */
+	fibril_mutex_lock(&log_serializer);
+
+	const char *level_name = log_level_name(level);
+
+	if (log_stream != NULL) {
+		va_start(args, format);
+
+		fprintf(log_stream, "[%s]%s: ", log_prefix, level_name);
+		vfprintf(log_stream, format, args);
+		fflush(log_stream);
+
+		va_end(args);
+	}
+
+	if (level <= log_level) {
+		va_start(args, format);
+
+		fprintf(screen_stream, "[%s]%s: ", log_prefix, level_name);
+		vfprintf(screen_stream, format, args);
+		fflush(screen_stream);
+
+		va_end(args);
+	}
+
+	fibril_mutex_unlock(&log_serializer);
+}
 
 /**
Index: uspace/lib/usb/src/dp.c
===================================================================
--- uspace/lib/usb/src/dp.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/dp.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,7 +37,28 @@
 #include <str_error.h>
 #include <errno.h>
-#include <usb/usbdrv.h>
+#include <assert.h>
 #include <bool.h>
 #include <usb/dp.h>
+#include <usb/descriptor.h>
+
+#define NESTING(parentname, childname) \
+	{ \
+		.child = USB_DESCTYPE_##childname, \
+		.parent = USB_DESCTYPE_##parentname, \
+	}
+#define LAST_NESTING { -1, -1 }
+
+/** Nesting of standard USB descriptors. */
+usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
+	NESTING(CONFIGURATION, INTERFACE),
+	NESTING(INTERFACE, ENDPOINT),
+	NESTING(INTERFACE, HUB),
+	NESTING(INTERFACE, HID),
+	NESTING(HID, HID_REPORT),
+	LAST_NESTING
+};
+
+#undef NESTING
+#undef LAST_NESTING
 
 /** Tells whether pointer points inside descriptor data.
@@ -45,5 +66,5 @@
  * @param data Parser data.
  * @param ptr Pointer to be verified.
- * @return Whether @ptr points inside <code>data->data</code> field.
+ * @return Whether @p ptr points inside <code>data->data</code> field.
  */
 static bool is_valid_descriptor_pointer(usb_dp_parser_data_t *data,
Index: pace/lib/usb/src/drvpsync.c
===================================================================
--- uspace/lib/usb/src/drvpsync.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,218 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief Implementation of pseudo-synchronous transfers.
- */
-#include <usb/usbdrv.h>
-#include <usbhc_iface.h>
-#include <errno.h>
-
-int usb_drv_psync_interrupt_out(int phone, usb_target_t target,
-    void *buffer, size_t size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_interrupt_out(phone, target, buffer, size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-int usb_drv_psync_interrupt_in(int phone, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_interrupt_in(phone, target, buffer, size,
-	    actual_size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-
-
-int usb_drv_psync_control_write_setup(int phone, usb_target_t target,
-    void *buffer, size_t size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_write_setup(phone, target, buffer, size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-int usb_drv_psync_control_write_data(int phone, usb_target_t target,
-    void *buffer, size_t size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_write_data(phone, target, buffer, size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-int usb_drv_psync_control_write_status(int phone, usb_target_t target)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_write_status(phone, target, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-
-/** Perform complete control write transaction over USB.
- *
- * The DATA stage is performed only when @p data is not NULL and
- * @p data_size is greater than zero.
- *
- * @param phone Open phone to host controller.
- * @param target Target device and endpoint.
- * @param setup_packet Setup packet data.
- * @param setup_packet_size Size of the setup packet.
- * @param data Data to be sent.
- * @param data_size Size of the @p data buffer.
- * @return Error code.
- */
-int usb_drv_psync_control_write(int phone, usb_target_t target,
-    void *setup_packet, size_t setup_packet_size,
-    void *data, size_t data_size)
-{
-	int rc;
-	
-	rc = usb_drv_psync_control_write_setup(phone, target,
-	    setup_packet, setup_packet_size);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if ((data != NULL) && (data_size > 0)) {
-		rc = usb_drv_psync_control_write_data(phone, target,
-		    data, data_size);
-		if (rc != EOK) {
-			return rc;
-		}
-	}
-
-	rc = usb_drv_psync_control_write_status(phone, target);
-
-	return rc;
-}
-
-
-int usb_drv_psync_control_read_setup(int phone, usb_target_t target,
-    void *buffer, size_t size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_read_setup(phone, target, buffer, size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-int usb_drv_psync_control_read_data(int phone, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_read_data(phone, target, buffer, size,
-	    actual_size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-int usb_drv_psync_control_read_status(int phone, usb_target_t target)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_read_status(phone, target, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-
-/** Perform complete control read transaction over USB.
- *
- * @param phone Open phone to host controller.
- * @param target Target device and endpoint.
- * @param setup_packet Setup packet data.
- * @param setup_packet_size Size of the setup packet.
- * @param data Storage for read data.
- * @param data_size Size of the @p data buffer.
- * @param actual_data_size Storage for number of actually transferred data from
- *        device.
- * @return Error code.
- */
-int usb_drv_psync_control_read(int phone, usb_target_t target,
-    void *setup_packet, size_t setup_packet_size,
-    void *data, size_t data_size, size_t *actual_data_size)
-{
-	int rc;
-	
-	rc = usb_drv_psync_control_read_setup(phone, target,
-	    setup_packet, setup_packet_size);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	rc = usb_drv_psync_control_read_data(phone, target,
-	    data, data_size, actual_data_size);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	rc = usb_drv_psync_control_read_status(phone, target);
-
-	return rc;
-}
-
-
-
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/dump.c
===================================================================
--- uspace/lib/usb/src/dump.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/dump.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * @brief Descriptor dumping.
+ */
+#include <adt/list.h>
+#include <fibril_synch.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <usb/debug.h>
+#include <usb/descriptor.h>
+#include <usb/classes/classes.h>
+#include <usb/classes/hid.h>
+
+typedef struct {
+	int id;
+	void (*dump)(FILE *, const char *, const char *,
+	    const uint8_t *, size_t);
+} descriptor_dump_t;
+
+static void usb_dump_descriptor_device(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_configuration(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_interface(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_string(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_endpoint(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_hid(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_hub(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_generic(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+
+static descriptor_dump_t descriptor_dumpers[] = {
+	{ USB_DESCTYPE_DEVICE, usb_dump_descriptor_device },
+	{ USB_DESCTYPE_CONFIGURATION, usb_dump_descriptor_configuration },
+	{ USB_DESCTYPE_STRING, usb_dump_descriptor_string },
+	{ USB_DESCTYPE_INTERFACE, usb_dump_descriptor_interface },
+	{ USB_DESCTYPE_ENDPOINT, usb_dump_descriptor_endpoint },
+	{ USB_DESCTYPE_HID, usb_dump_descriptor_hid },
+	{ USB_DESCTYPE_HUB, usb_dump_descriptor_hub },
+	{ -1, usb_dump_descriptor_generic },
+	{ -1, NULL }
+};
+
+/** Dumps standard USB descriptor.
+ * The @p line_suffix must contain the newline <code>\\n</code> character.
+ * When @p line_suffix or @p line_prefix is NULL, they are substitued with
+ * default values
+ * (<code> - </code> for prefix and line termination for suffix).
+ *
+ * @param output Output file stream to dump descriptor to.
+ * @param line_prefix Prefix for each line of output.
+ * @param line_suffix Suffix of each line of output.
+ * @param descriptor Actual descriptor.
+ * @param descriptor_length Descriptor size.
+ */
+void usb_dump_standard_descriptor(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	if (descriptor_length < 2) {
+		return;
+	}
+	int type = descriptor[1];
+
+	descriptor_dump_t *dumper = descriptor_dumpers;
+	while (dumper->dump != NULL) {
+		if ((dumper->id == type) || (dumper->id < 0)) {
+			dumper->dump(output, line_prefix, line_suffix,
+			    descriptor, descriptor_length);
+			return;
+		}
+		dumper++;
+	}
+}
+
+/** Prints single line of USB descriptor dump.
+ * @warning This macro abuses heavily the naming conventions used
+ * by all dumping functions (i.e. names for output file stream (@c output) and
+ * line prefix and suffix (@c line_prefix and @c line_suffix respectively))-
+ *
+ * @param fmt Formatting string.
+ */
+#define PRINTLINE(fmt, ...) \
+	fprintf(output, "%s" fmt "%s", \
+	    line_prefix ? line_prefix : " - ", \
+	    __VA_ARGS__, \
+	    line_suffix ? line_suffix : "\n")
+
+#define BCD_INT(a) (((unsigned int)(a)) / 256)
+#define BCD_FRAC(a) (((unsigned int)(a)) % 256)
+
+#define BCD_FMT "%x.%x"
+#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
+
+static void usb_dump_descriptor_device(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_device_descriptor_t *d
+	    = (usb_standard_device_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("bcdUSB = %d (" BCD_FMT ")", d->usb_spec_version,
+	    BCD_ARGS(d->usb_spec_version));
+	PRINTLINE("bDeviceClass = 0x%02x", d->device_class);
+	PRINTLINE("bDeviceSubClass = 0x%02x", d->device_subclass);
+	PRINTLINE("bDeviceProtocol = 0x%02x", d->device_protocol);
+	PRINTLINE("bMaxPacketSize0 = %d", d->max_packet_size);
+	PRINTLINE("idVendor = 0x%04x", d->vendor_id);
+	PRINTLINE("idProduct = 0x%04x", d->product_id);
+	PRINTLINE("bcdDevice = %d", d->device_version);
+	PRINTLINE("iManufacturer = %d", d->str_manufacturer);
+	PRINTLINE("iProduct = %d", d->str_product);
+	PRINTLINE("iSerialNumber = %d", d->str_serial_number);
+	PRINTLINE("bNumConfigurations = %d", d->configuration_count);
+}
+
+static void usb_dump_descriptor_configuration(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_configuration_descriptor_t *d
+	    = (usb_standard_configuration_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	bool self_powered = d->attributes & 64;
+	bool remote_wakeup = d->attributes & 32;
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("wTotalLength = %d", d->total_length);
+	PRINTLINE("bNumInterfaces = %d", d->interface_count);
+	PRINTLINE("bConfigurationValue = %d", d->configuration_number);
+	PRINTLINE("iConfiguration = %d", d->str_configuration);
+	PRINTLINE("bmAttributes = %d [%s%s%s]", d->attributes,
+	    self_powered ? "self-powered" : "",
+	    (self_powered & remote_wakeup) ? ", " : "",
+	    remote_wakeup ? "remote-wakeup" : "");
+	PRINTLINE("MaxPower = %d (%dmA)", d->max_power,
+	    2 * d->max_power);
+}
+
+static void usb_dump_descriptor_interface(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_interface_descriptor_t *d
+	    = (usb_standard_interface_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("bInterfaceNumber = %d", d->interface_number);
+	PRINTLINE("bAlternateSetting = %d", d->alternate_setting);
+	PRINTLINE("bNumEndpoints = %d", d->endpoint_count);
+	PRINTLINE("bInterfaceClass = %s", d->interface_class == 0
+	    ? "reserved (0)" : usb_str_class(d->interface_class));
+	PRINTLINE("bInterfaceSubClass = %d", d->interface_subclass);
+	PRINTLINE("bInterfaceProtocol = %d", d->interface_protocol);
+	PRINTLINE("iInterface = %d", d->str_interface);
+}
+
+static void usb_dump_descriptor_string(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+}
+
+static void usb_dump_descriptor_endpoint(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_endpoint_descriptor_t *d
+	   = (usb_standard_endpoint_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	int endpoint = d->endpoint_address & 15;
+	usb_direction_t direction = d->endpoint_address & 128
+	    ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
+	usb_transfer_type_t transfer_type = d->attributes & 3;
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02X", d->descriptor_type);
+	PRINTLINE("bEndpointAddress = 0x%02X [%d, %s]",
+	    d->endpoint_address, endpoint,
+	    direction == USB_DIRECTION_IN ? "in" : "out");
+	PRINTLINE("bmAttributes = %d [%s]", d->attributes,
+	    usb_str_transfer_type(transfer_type));
+	PRINTLINE("wMaxPacketSize = %d", d->max_packet_size);
+	PRINTLINE("bInterval = %dms", d->poll_interval);
+}
+
+static void usb_dump_descriptor_hid(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_hid_descriptor_t *d
+	    = (usb_standard_hid_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("bcdHID = %d (" BCD_FMT ")", d->spec_release,
+	    BCD_ARGS(d->spec_release));
+	PRINTLINE("bCountryCode = %d", d->country_code);
+	PRINTLINE("bNumDescriptors = %d", d->class_desc_count);
+	PRINTLINE("bDescriptorType = %d", d->report_desc_info.type);
+	PRINTLINE("wDescriptorLength = %d", d->report_desc_info.length);
+
+	/* Print info about report descriptors. */
+	size_t i;
+	size_t count = (descriptor_length - sizeof(*d))
+	    / sizeof(usb_standard_hid_class_descriptor_info_t);
+	usb_standard_hid_class_descriptor_info_t *d2
+	    = (usb_standard_hid_class_descriptor_info_t *)
+	    (descriptor + sizeof(*d));
+	for (i = 0; i < count; i++, d2++) {
+		PRINTLINE("bDescriptorType = %d", d2->type);
+		PRINTLINE("wDescriptorLength = %d", d2->length);
+	}
+}
+
+static void usb_dump_descriptor_hub(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+}
+
+static void usb_dump_descriptor_generic(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+}
+
+
+/**
+ * @}
+ */
Index: pace/lib/usb/src/hcdhubd.c
===================================================================
--- uspace/lib/usb/src/hcdhubd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,341 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief Common stuff for both HC driver and hub driver.
- */
-#include <usb/hcdhubd.h>
-#include <usb/devreq.h>
-#include <usbhc_iface.h>
-#include <usb_iface.h>
-#include <usb/descriptor.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-#include <str_error.h>
-#include <usb/classes/hub.h>
-
-#include "hcdhubd_private.h"
-
-
-static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
-{
-	assert(dev);
-	assert(dev->parent != NULL);
-
-	device_t *parent = dev->parent;
-
-	if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
-		usb_iface_t *usb_iface
-		    = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
-		assert(usb_iface != NULL);
-		if (usb_iface->get_hc_handle) {
-			int rc = usb_iface->get_hc_handle(parent, handle);
-			return rc;
-		}
-	}
-
-	return ENOTSUP;
-}
-
-static usb_iface_t usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle
-};
-
-static device_ops_t child_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface
-};
-
-/** Callback when new device is detected and must be handled by this driver.
- *
- * @param dev New device.
- * @return Error code.
- */
-static int add_device(device_t *dev) {
-	return ENOTSUP;
-}
-
-/** Operations for combined HC and HUB driver. */
-static driver_ops_t hc_driver_generic_ops = {
-	.add_device = add_device
-};
-
-/** Combined HC and HUB driver. */
-static driver_t hc_driver_generic = {
-	.driver_ops = &hc_driver_generic_ops
-};
-
-/** Main USB host controller driver routine.
- *
- * @see driver_main
- *
- * @param hc Host controller driver.
- * @return Error code.
- */
-int usb_hcd_main(usb_hc_driver_t *hc) {
-	hc_driver = hc;
-	hc_driver_generic.name = hc->name;
-
-	/*
-	 * Run the device driver framework.
-	 */
-	return driver_main(&hc_driver_generic);
-}
-
-/** Add a root hub for given host controller.
- * This function shall be called only once for each host controller driven
- * by this driver.
- * It takes care of creating child device - hub - that will be driven by
- * this task.
- *
- * @param dev Host controller device.
- * @return Error code.
- */
-int usb_hcd_add_root_hub(device_t *dev)
-{
-	char *id;
-	int rc = asprintf(&id, "usb&hub");
-	if (rc <= 0) {
-		return rc;
-	}
-
-	rc = usb_hc_add_child_device(dev, USB_HUB_DEVICE_NAME, id, true);
-	if (rc != EOK) {
-		free(id);
-	}
-
-	return rc;
-}
-
-/** Info about child device. */
-struct child_device_info {
-	device_t *parent;
-	const char *name;
-	const char *match_id;
-};
-
-/** Adds a child device fibril worker. */
-static int fibril_add_child_device(void *arg) {
-	struct child_device_info *child_info
-			= (struct child_device_info *) arg;
-	int rc;
-
-	async_usleep(1000);
-
-	device_t *child = create_device();
-	match_id_t *match_id = NULL;
-
-	if (child == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-	child->name = child_info->name;
-	child->parent = child_info->parent;
-	child->ops = &child_ops;
-
-	match_id = create_match_id();
-	if (match_id == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-	match_id->id = child_info->match_id;
-	match_id->score = 10;
-	add_match_id(&child->match_ids, match_id);
-
-	printf("%s: adding child device `%s' with match \"%s\"\n",
-			hc_driver->name, child->name, match_id->id);
-	rc = child_device_register(child, child_info->parent);
-	printf("%s: child device `%s' registration: %s\n",
-			hc_driver->name, child->name, str_error(rc));
-
-	if (rc != EOK) {
-		goto failure;
-	}
-
-	goto leave;
-
-failure:
-	if (child != NULL) {
-		child->name = NULL;
-		delete_device(child);
-	}
-
-	if (match_id != NULL) {
-		match_id->id = NULL;
-		delete_match_id(match_id);
-	}
-
-leave:
-	free(arg);
-	return EOK;
-}
-
-/** Adds a child.
- * Due to deadlock in devman when parent registers child that oughts to be
- * driven by the same task, the child adding is done in separate fibril.
- * Not optimal, but it works.
- * Update: not under all circumstances the new fibril is successful either.
- * Thus the last parameter to let the caller choose.
- *
- * @param parent Parent device.
- * @param name Device name.
- * @param match_id Match id.
- * @param create_fibril Whether to run the addition in new fibril.
- * @return Error code.
- */
-int usb_hc_add_child_device(device_t *parent, const char *name,
-		const char *match_id, bool create_fibril) {
-	printf("%s: about to add child device `%s' (%s)\n", hc_driver->name,
-			name, match_id);
-
-	/*
-	 * Seems that creating fibril which postpones the action
-	 * is the best solution.
-	 */
-	create_fibril = true;
-
-	struct child_device_info *child_info
-			= malloc(sizeof (struct child_device_info));
-
-	child_info->parent = parent;
-	child_info->name = name;
-	child_info->match_id = match_id;
-
-	if (create_fibril) {
-		fid_t fibril = fibril_create(fibril_add_child_device, child_info);
-		if (!fibril) {
-			return ENOMEM;
-		}
-		fibril_add_ready(fibril);
-	} else {
-		fibril_add_child_device(child_info);
-	}
-
-	return EOK;
-}
-
-/** Tell USB address of given device.
- *
- * @param handle Devman handle of the device.
- * @return USB device address or error code.
- */
-usb_address_t usb_get_address_by_handle(devman_handle_t handle) {
-	/* TODO: search list of attached devices. */
-	return ENOENT;
-}
-
-usb_address_t usb_use_free_address(usb_hc_device_t * this_hcd) {
-	//is there free address?
-	link_t * addresses = &this_hcd->addresses;
-	if (list_empty(addresses)) return -1;
-	link_t * link_addr = addresses;
-	bool found = false;
-	usb_address_list_t * range = NULL;
-	while (!found) {
-		link_addr = link_addr->next;
-		if (link_addr == addresses) return -2;
-		range = list_get_instance(link_addr,
-				usb_address_list_t, link);
-		if (range->upper_bound - range->lower_bound > 0) {
-			found = true;
-		}
-	}
-	//now we have interval
-	int result = range->lower_bound;
-	++(range->lower_bound);
-	if (range->upper_bound - range->lower_bound == 0) {
-		list_remove(&range->link);
-		free(range);
-	}
-	return result;
-}
-
-void usb_free_used_address(usb_hc_device_t * this_hcd, usb_address_t addr) {
-	//check range
-	if (addr < usb_lowest_address || addr > usb_highest_address)
-		return;
-	link_t * addresses = &this_hcd->addresses;
-	link_t * link_addr = addresses;
-	//find 'good' interval
-	usb_address_list_t * found_range = NULL;
-	bool found = false;
-	while (!found) {
-		link_addr = link_addr->next;
-		if (link_addr == addresses) {
-			found = true;
-		} else {
-			usb_address_list_t * range = list_get_instance(link_addr,
-					usb_address_list_t, link);
-			if (	(range->lower_bound - 1 == addr) ||
-					(range->upper_bound == addr)) {
-				found = true;
-				found_range = range;
-			}
-			if (range->lower_bound - 1 > addr) {
-				found = true;
-			}
-
-		}
-	}
-	if (found_range == NULL) {
-		//no suitable range found
-		usb_address_list_t * result_range =
-				(usb_address_list_t*) malloc(sizeof (usb_address_list_t));
-		result_range->lower_bound = addr;
-		result_range->upper_bound = addr + 1;
-		list_insert_before(&result_range->link, link_addr);
-	} else {
-		//we have good range
-		if (found_range->lower_bound - 1 == addr) {
-			--found_range->lower_bound;
-		} else {
-			//only one possible case
-			++found_range->upper_bound;
-			if (found_range->link.next != addresses) {
-				usb_address_list_t * next_range =
-						list_get_instance( &found_range->link.next,
-						usb_address_list_t, link);
-				//check neighbour range
-				if (next_range->lower_bound == addr + 1) {
-					//join ranges
-					found_range->upper_bound = next_range->upper_bound;
-					list_remove(&next_range->link);
-					free(next_range);
-				}
-			}
-		}
-	}
-
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/hcdhubd_private.h
===================================================================
--- uspace/lib/usb/src/hcdhubd_private.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/hcdhubd_private.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
Index: pace/lib/usb/src/hcdrv.c
===================================================================
--- uspace/lib/usb/src/hcdrv.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,127 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief HC driver.
- */
-#include <usb/hcdhubd.h>
-#include <usb/devreq.h>
-#include <usbhc_iface.h>
-#include <usb/descriptor.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-#include <usb/classes/hub.h>
-
-#include "hcdhubd_private.h"
-
-/** List of handled host controllers. */
-LIST_INITIALIZE(hc_list);
-
-/* Fake driver to have the name item initialized. */
-static usb_hc_driver_t hc_driver_fake = {
-	.name = "HCD",
-};
-
-/** Our HC driver. */
-usb_hc_driver_t *hc_driver = &hc_driver_fake;
-
-int usb_lowest_address = 1;
-
-int usb_highest_address = 255;
-
-static device_ops_t usb_device_ops = {
-	.interfaces[USBHC_DEV_IFACE] = &usbhc_interface
-};
-
-
-void usb_create_address_list(usb_hc_device_t * hcd){
-	list_initialize(&hcd->addresses);
-	usb_address_list_t * range =
-			(usb_address_list_t*)malloc(sizeof(usb_address_list_t));
-	range->lower_bound = usb_lowest_address;
-	range->upper_bound = usb_highest_address + 1;
-	list_append(&range->link, &hcd->addresses);
-}
-
-static usb_hc_device_t *usb_hc_device_create(device_t *dev) {
-	usb_hc_device_t *hc_dev = malloc(sizeof (usb_hc_device_t));
-
-	list_initialize(&hc_dev->link);
-	list_initialize(&hc_dev->hubs);
-	usb_create_address_list(hc_dev);
-	list_initialize(&hc_dev->attached_devices);
-	hc_dev->transfer_ops = NULL;
-
-	hc_dev->generic = dev;
-	dev->ops = &usb_device_ops;
-	hc_dev->generic->driver_data = hc_dev;
-
-	return hc_dev;
-}
-
-int usb_add_hc_device(device_t *dev)
-{
-	return ENOTSUP;
-	usb_hc_device_t *hc_dev = usb_hc_device_create(dev);
-
-	int rc = hc_driver->add_hc(hc_dev);
-	if (rc != EOK) {
-		free(hc_dev);
-		return rc;
-	}
-
-	/*
-	 * FIXME: The following line causes devman to hang.
-	 * Will investigate later why.
-	 */
-	// add_device_to_class(dev, "usbhc");
-
-	list_append(&hc_dev->link, &hc_list);
-
-	/*
-	 * FIXME: the following is a workaround to force loading of USB
-	 * keyboard driver.
-	 * Will be removed as soon as the hub driver is completed and
-	 * can detect connected devices.
-	 */
-	printf("%s: trying to add USB HID child device...\n", hc_driver->name);
-	rc = usb_hc_add_child_device(dev, USB_KBD_DEVICE_NAME, "usb&hid", false);
-	if (rc != EOK) {
-		printf("%s: adding USB HID child failed...\n", hc_driver->name);
-	}
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/hidparser.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -196,15 +196,4 @@
 }
 
-/** Free the HID report parser structure 
- *
- * @param parser Opaque HID report parser structure
- * @return Error code
- */
-int usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
-{
-
-	return EOK;
-}
-
 
 /**
@@ -237,5 +226,5 @@
 
 	if (size != 8) {
-		return -1;//ERANGE;
+		return ERANGE;
 	}
 
@@ -540,8 +529,7 @@
 }
 
-/**
- * Frees complete structure of report parser
- * 
- * @param Parser to free
+/** Free the HID report parser structure 
+ *
+ * @param parser Opaque HID report parser structure
  * @return Error code
  */
@@ -561,7 +549,2 @@
  * @}
  */
-
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/hub.c
===================================================================
--- uspace/lib/usb/src/hub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/hub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Functions needed by hub drivers.
+ */
+#include <usb/hub.h>
+#include <usb/pipes.h>
+#include <usb/request.h>
+#include <usb/recognise.h>
+#include <usbhc_iface.h>
+#include <errno.h>
+#include <assert.h>
+
+/** Check that HC connection is alright.
+ *
+ * @param conn Connection to be checked.
+ */
+#define CHECK_CONNECTION(conn) \
+	do { \
+		assert((conn)); \
+		if (!usb_hc_connection_is_opened((conn))) { \
+			return ENOENT; \
+		} \
+	} while (false)
+
+
+/** Tell host controller to reserve default address.
+ *
+ * @param connection Opened connection to host controller.
+ * @return Error code.
+ */
+int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
+    usb_speed_t speed)
+{
+	CHECK_CONNECTION(connection);
+
+	return async_req_2_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);
+}
+
+/** Tell host controller to release default address.
+ *
+ * @param connection Opened connection to host controller.
+ * @return Error code.
+ */
+int usb_hc_release_default_address(usb_hc_connection_t *connection)
+{
+	CHECK_CONNECTION(connection);
+
+	return async_req_1_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
+}
+
+/** Ask host controller for free address assignment.
+ *
+ * @param connection Opened connection to host controller.
+ * @return Assigned USB address or negative error code.
+ */
+usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
+    usb_speed_t speed)
+{
+	CHECK_CONNECTION(connection);
+
+	sysarg_t address;
+	int rc = async_req_2_1(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_REQUEST_ADDRESS, speed,
+	    &address);
+	if (rc != EOK) {
+		return (usb_address_t) rc;
+	} else {
+		return (usb_address_t) address;
+	}
+}
+
+/** Inform host controller about new device.
+ *
+ * @param connection Opened connection to host controller.
+ * @param attached_device Information about the new device.
+ * @return Error code.
+ */
+int usb_hc_register_device(usb_hc_connection_t * connection,
+    const usb_hc_attached_device_t *attached_device)
+{
+	CHECK_CONNECTION(connection);
+	if (attached_device == NULL) {
+		return EBADMEM;
+	}
+
+	return async_req_3_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_BIND_ADDRESS,
+	    attached_device->address, attached_device->handle);
+}
+
+/** Inform host controller about device removal.
+ *
+ * @param connection Opened connection to host controller.
+ * @param address Address of the device that is being removed.
+ * @return Error code.
+ */
+int usb_hc_unregister_device(usb_hc_connection_t *connection,
+    usb_address_t address)
+{
+	CHECK_CONNECTION(connection);
+
+	return async_req_2_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RELEASE_ADDRESS, address);
+}
+
+
+/** Wrapper for registering attached device to the hub.
+ *
+ * The @p enable_port function is expected to enable singalling on given
+ * port.
+ * The two arguments to it can have arbitrary meaning
+ * (the @p port_no is only a suggestion)
+ * and are not touched at all by this function
+ * (they are passed as is to the @p enable_port function).
+ *
+ * If the @p enable_port fails (i.e. does not return EOK), the device
+ * addition is cancelled.
+ * The return value is then returned (it is good idea to use different
+ * error codes than those listed as return codes by this function itself).
+ *
+ * @param parent Parent device (i.e. the hub device).
+ * @param connection Opened connection to host controller.
+ * @param dev_speed New device speed.
+ * @param enable_port Function for enabling signalling through the port the
+ *	device is attached to.
+ * @param port_no Port number (passed through to @p enable_port).
+ * @param arg Any data argument to @p enable_port.
+ * @param[out] assigned_address USB address of the device.
+ * @param[out] assigned_handle Devman handle of the new device.
+ * @return Error code.
+ * @retval ENOENT Connection to HC not opened.
+ * @retval EADDRNOTAVAIL Failed retrieving free address from host controller.
+ * @retval EBUSY Failed reserving default USB address.
+ * @retval ENOTCONN Problem connecting to the host controller via USB pipe.
+ * @retval ESTALL Problem communication with device (either SET_ADDRESS
+ *	request or requests for descriptors when creating match ids).
+ */
+int usb_hc_new_device_wrapper(ddf_dev_t *parent, usb_hc_connection_t *connection,
+    usb_speed_t dev_speed,
+    int (*enable_port)(int port_no, void *arg), int port_no, void *arg,
+    usb_address_t *assigned_address, devman_handle_t *assigned_handle,
+    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
+{
+	CHECK_CONNECTION(connection);
+
+	/*
+	 * Request new address.
+	 */
+	usb_address_t dev_addr = usb_hc_request_address(connection, dev_speed);
+	if (dev_addr < 0) {
+		return EADDRNOTAVAIL;
+	}
+
+	int rc;
+
+	/*
+	 * Reserve the default address.
+	 */
+	rc = usb_hc_reserve_default_address(connection, dev_speed);
+	if (rc != EOK) {
+		rc = EBUSY;
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * Enable the port (i.e. allow signalling through this port).
+	 */
+	rc = enable_port(port_no, arg);
+	if (rc != EOK) {
+		goto leave_release_default_address;
+	}
+
+	/*
+	 * Change the address from default to the free one.
+	 * We need to create a new control pipe for that.
+	 */
+	usb_device_connection_t dev_conn;
+	rc = usb_device_connection_initialize_on_default_address(&dev_conn,
+	    connection);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_default_address;
+	}
+
+	usb_endpoint_pipe_t ctrl_pipe;
+	rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe,
+	    &dev_conn);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_default_address;
+	}
+
+	rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_default_address;
+	}
+
+	rc = usb_request_set_address(&ctrl_pipe, dev_addr);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_stop_session;
+	}
+
+	usb_endpoint_pipe_end_session(&ctrl_pipe);
+
+	/*
+	 * Once the address is changed, we can return the default address.
+	 */
+	usb_hc_release_default_address(connection);
+
+	/*
+	 * It is time to register the device with devman.
+	 */
+	/* FIXME: create device_register that will get opened ctrl pipe. */
+	devman_handle_t child_handle;
+	rc = usb_device_register_child_in_devman(dev_addr, dev_conn.hc_handle,
+	    parent, &child_handle,
+	    dev_ops, new_dev_data, new_fun);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * And now inform the host controller about the handle.
+	 */
+	usb_hc_attached_device_t new_device = {
+		.address = dev_addr,
+		.handle = child_handle
+	};
+	rc = usb_hc_register_device(connection, &new_device);
+	if (rc != EOK) {
+		rc = EDESTADDRREQ;
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * And we are done.
+	 */
+	if (assigned_address != NULL) {
+		*assigned_address = dev_addr;
+	}
+	if (assigned_handle != NULL) {
+		*assigned_handle = child_handle;
+	}
+
+	return EOK;
+
+
+
+	/*
+	 * Error handling (like nested exceptions) starts here.
+	 * Completely ignoring errors here.
+	 */
+
+leave_stop_session:
+	usb_endpoint_pipe_end_session(&ctrl_pipe);
+
+leave_release_default_address:
+	usb_hc_release_default_address(connection);
+
+leave_release_free_address:
+	usb_hc_unregister_device(connection, dev_addr);
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: pace/lib/usb/src/localdrv.c
===================================================================
--- uspace/lib/usb/src/localdrv.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,414 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief Driver communication for local drivers (hubs).
- */
-#include <usb/hcdhubd.h>
-#include <usbhc_iface.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-
-/** Find host controller when handled by current task.
- *
- * @param dev Device asking for connection.
- * @return Device structure corresponding to parent host controller.
- * @retval NULL Corresponding host controller not found.
- */
-device_t *usb_hc_connect(device_t *dev)
-{
-	/*
-	 * FIXME: this will not work when some hub on the path is
-	 * not driven by the same task.
-	 */
-	device_t *parent = dev;
-	while (parent->parent != NULL) {
-		parent = parent->parent;
-	}
-	
-	if (dev == parent) {
-		printf("FIXME in %s:%d encountered!\n", __FILE__, __LINE__);
-		parent = NULL;
-	}
-
-	return parent;
-}
-
-/** Information about pending transaction on HC. */
-typedef struct {
-	/** Storage for actual number of bytes transferred. */
-	size_t *size_transferred;
-
-	/** Target device. */
-	usb_hcd_attached_device_info_t *device;
-	/** Target endpoint. */
-	usb_hc_endpoint_info_t *endpoint;
-
-	/** Guard for the condition variable. */
-	fibril_mutex_t condvar_guard;
-	/** Condition variable for waiting for done. */
-	fibril_condvar_t condvar;
-
-	/** Flag whether the transfer is done. */
-	bool done;
-} transfer_info_t;
-
-/** Create new transfer info.
- *
- * @param device Attached device.
- * @param endpoint Endpoint.
- * @return Transfer info with pre-filled values.
- */
-static transfer_info_t *transfer_info_create(
-    usb_hcd_attached_device_info_t *device, usb_hc_endpoint_info_t *endpoint)
-{
-	transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
-
-	transfer->size_transferred = NULL;
-	fibril_condvar_initialize(&transfer->condvar);
-	fibril_mutex_initialize(&transfer->condvar_guard);
-	transfer->done = false;
-
-	transfer->device = device;
-	transfer->endpoint = endpoint;
-
-	return transfer;
-}
-
-/** Destroy transfer info.
- *
- * @param transfer Transfer to be destroyed.
- */
-static void transfer_info_destroy(transfer_info_t *transfer)
-{
-	free(transfer->device);
-	free(transfer->endpoint);
-	free(transfer);
-}
-
-/** Create info about attached device.
- *
- * @param address Device address.
- * @return Device info structure.
- */
-static usb_hcd_attached_device_info_t *create_attached_device_info(
-    usb_address_t address)
-{
-	usb_hcd_attached_device_info_t *dev
-	    = malloc(sizeof(usb_hcd_attached_device_info_t));
-
-	dev->address = address;
-	dev->endpoint_count = 0;
-	dev->endpoints = NULL;
-	list_initialize(&dev->link);
-
-	return dev;
-}
-
-/** Create info about device endpoint.
- *
- * @param endpoint Endpoint number.
- * @param direction Endpoint data direction.
- * @param transfer_type Transfer type of the endpoint.
- * @return Endpoint info structure.
- */
-static usb_hc_endpoint_info_t *create_endpoint_info(usb_endpoint_t endpoint,
-    usb_direction_t direction, usb_transfer_type_t transfer_type)
-{
-	usb_hc_endpoint_info_t *ep = malloc(sizeof(usb_hc_endpoint_info_t));
-	ep->data_toggle = 0;
-	ep->direction = direction;
-	ep->transfer_type = transfer_type;
-	ep->endpoint = endpoint;
-
-	return ep;
-}
-
-/** Marks given transfer as done.
- *
- * @param transfer Transfer to be completed.
- */
-static void transfer_mark_complete(transfer_info_t *transfer)
-{
-	fibril_mutex_lock(&transfer->condvar_guard);
-	transfer->done = true;
-	fibril_condvar_signal(&transfer->condvar);
-	fibril_mutex_unlock(&transfer->condvar_guard);
-}
-
-/** Callback for OUT transfers.
- *
- * @param hc Host controller that processed the transfer.
- * @param outcome Transfer outcome.
- * @param arg Custom argument.
- */
-static void callback_out(usb_hc_device_t *hc,
-    usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-
-	/*
-	 * For out transfers, marking them complete is enough.
-	 * No other processing is necessary.
-	 */
-	transfer_mark_complete(transfer);
-}
-
-/** Callback for IN transfers.
- *
- * @param hc Host controller that processed the transfer.
- * @param actual_size Number of actually transferred bytes.
- * @param outcome Transfer outcome.
- * @param arg Custom argument.
- */
-static void callback_in(usb_hc_device_t *hc,
-    size_t actual_size, usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-
-	/*
-	 * Set the number of actually transferred bytes and
-	 * mark the transfer as complete.
-	 */
-	if (transfer->size_transferred != NULL) {
-		*transfer->size_transferred = actual_size;
-	}
-
-	transfer_mark_complete(transfer);
-}
-
-static int async_transfer_out(usb_hc_device_t *hc,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *data, size_t size,
-    usb_handle_t *handle)
-{
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_out == NULL)) {
-		return ENOTSUP;
-	}
-
-	/* This creation of the device on the fly is just a workaround. */
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type));
-
-	int rc = hc->transfer_ops->transfer_out(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    callback_out, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	*handle = (usb_handle_t)transfer;
-
-	return EOK;
-}
-
-static int async_transfer_setup(usb_hc_device_t *hc,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *data, size_t size,
-    usb_handle_t *handle)
-{
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_setup == NULL)) {
-		return ENOTSUP;
-	}
-
-	/* This creation of the device on the fly is just a workaround. */
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type));
-
-	int rc = hc->transfer_ops->transfer_setup(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    callback_out, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	*handle = (usb_handle_t)transfer;
-
-	return EOK;
-}
-
-static int async_transfer_in(usb_hc_device_t *hc, usb_target_t target,
-    usb_transfer_type_t transfer_type,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_in == NULL)) {
-		return ENOTSUP;
-	}
-
-	/* This creation of the device on the fly is just a workaround. */
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_IN, transfer_type));
-	transfer->size_transferred = actual_size;
-
-	int rc = hc->transfer_ops->transfer_in(hc,
-	    transfer->device, transfer->endpoint,
-	    buffer, size,
-	    callback_in, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	*handle = (usb_handle_t)transfer;
-
-	return EOK;
-}
-
-
-/** Issue interrupt OUT transfer to HC driven by current task.
- *
- * @param hc Host controller to handle the transfer.
- * @param target Target device address.
- * @param buffer Data buffer.
- * @param size Buffer size.
- * @param handle Transfer handle.
- * @return Error code.
- */
-int usb_hc_async_interrupt_out(usb_hc_device_t *hc, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_transfer_out(hc, target,
-	    USB_TRANSFER_INTERRUPT, buffer, size, handle);
-}
-
-
-/** Issue interrupt IN transfer to HC driven by current task.
- *
- * @warning The @p buffer and @p actual_size parameters shall not be
- * touched until this transfer is waited for by usb_hc_async_wait_for().
- *
- * @param hc Host controller to handle the transfer.
- * @param target Target device address.
- * @param buffer Data buffer.
- * @param size Buffer size.
- * @param actual_size Size of actually transferred data.
- * @param handle Transfer handle.
- * @return Error code.
- */
-int usb_hc_async_interrupt_in(usb_hc_device_t *hc, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_transfer_in(hc, target,
-	    USB_TRANSFER_INTERRUPT, buffer, size, actual_size, handle);
-}
-
-int usb_hc_async_control_write_setup(usb_hc_device_t *hc, usb_target_t target,
-    void *data, size_t size, usb_handle_t *handle)
-{
-	return async_transfer_setup(hc, target,
-	    USB_TRANSFER_CONTROL, data, size, handle);
-}
-
-int usb_hc_async_control_write_data(usb_hc_device_t *hc, usb_target_t target,
-    void *data, size_t size, usb_handle_t *handle)
-{
-	return async_transfer_out(hc, target,
-	    USB_TRANSFER_CONTROL, data, size, handle);
-}
-
-int usb_hc_async_control_write_status(usb_hc_device_t *hc, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_transfer_in(hc, target,
-	    USB_TRANSFER_CONTROL, NULL, 0, NULL, handle);
-}
-
-int usb_hc_async_control_read_setup(usb_hc_device_t *hc, usb_target_t target,
-    void *data, size_t size, usb_handle_t *handle)
-{
-	return async_transfer_setup(hc, target,
-	    USB_TRANSFER_CONTROL, data, size, handle);
-}
-
-int usb_hc_async_control_read_data(usb_hc_device_t *hc, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_transfer_in(hc, target,
-	    USB_TRANSFER_CONTROL, buffer, size, actual_size, handle);
-}
-
-int usb_hc_async_control_read_status(usb_hc_device_t *hc, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_transfer_out(hc, target,
-	    USB_TRANSFER_CONTROL, NULL, 0, handle);
-}
-
-/** Wait for transfer to complete.
- *
- * @param handle Transfer handle.
- * @return Error code.
- */
-int usb_hc_async_wait_for(usb_handle_t handle)
-{
-	transfer_info_t *transfer = (transfer_info_t *) handle;
-	if (transfer == NULL) {
-		return ENOENT;
-	}
-
-	fibril_mutex_lock(&transfer->condvar_guard);
-	while (!transfer->done) {
-		fibril_condvar_wait(&transfer->condvar, &transfer->condvar_guard);
-	}
-	fibril_mutex_unlock(&transfer->condvar_guard);
-
-	transfer_info_destroy(transfer);
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/pipes.c
===================================================================
--- uspace/lib/usb/src/pipes.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/pipes.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB endpoint pipes miscellaneous functions.
+ */
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <usb/debug.h>
+#include <usbhc_iface.h>
+#include <usb_iface.h>
+#include <devman.h>
+#include <errno.h>
+#include <assert.h>
+
+/** Tell USB address assigned to given device.
+ *
+ * @param phone Phone to parent device.
+ * @param dev Device in question.
+ * @return USB address or error code.
+ */
+static usb_address_t get_my_address(int phone, ddf_dev_t *dev)
+{
+	sysarg_t address;
+
+
+	/*
+	 * We are sending special value as a handle - zero - to get
+	 * handle of the parent function (that handle was used
+	 * when registering our device @p dev.
+	 */
+	int rc = async_req_2_1(phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_ADDRESS,
+	    0, &address);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	return (usb_address_t) address;
+}
+
+/** Tell USB interface assigned to given device.
+ *
+ * @param device Device in question.
+ * @return Interface number (negative code means any).
+ */
+int usb_device_get_assigned_interface(ddf_dev_t *device)
+{
+	int parent_phone = devman_parent_device_connect(device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return -1;
+	}
+
+	sysarg_t iface_no;
+	int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_INTERFACE,
+	    device->handle, &iface_no);
+
+	async_hangup(parent_phone);
+
+	if (rc != EOK) {
+		return -1;
+	}
+
+	return (int) iface_no;
+}
+
+/** Initialize connection to USB device.
+ *
+ * @param connection Connection structure to be initialized.
+ * @param device Generic device backing the USB device.
+ * @return Error code.
+ */
+int usb_device_connection_initialize_from_device(
+    usb_device_connection_t *connection, ddf_dev_t *dev)
+{
+	assert(connection);
+	assert(dev);
+
+	int rc;
+	devman_handle_t hc_handle;
+	usb_address_t my_address;
+
+	rc = usb_hc_find(dev->handle, &hc_handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	int parent_phone = devman_parent_device_connect(dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	my_address = get_my_address(parent_phone, dev);
+	if (my_address < 0) {
+		rc = my_address;
+		goto leave;
+	}
+
+	rc = usb_device_connection_initialize(connection,
+	    hc_handle, my_address);
+
+leave:
+	async_hangup(parent_phone);
+	return rc;
+}
+
+/** Initialize connection to USB device.
+ *
+ * @param connection Connection structure to be initialized.
+ * @param host_controller_handle Devman handle of host controller device is
+ * 	connected to.
+ * @param device_address Device USB address.
+ * @return Error code.
+ */
+int usb_device_connection_initialize(usb_device_connection_t *connection,
+    devman_handle_t host_controller_handle, usb_address_t device_address)
+{
+	assert(connection);
+
+	if ((device_address < 0) || (device_address >= USB11_ADDRESS_MAX)) {
+		return EINVAL;
+	}
+
+	connection->hc_handle = host_controller_handle;
+	connection->address = device_address;
+
+	return EOK;
+}
+
+/** Initialize connection to USB device on default address.
+ *
+ * @param dev_connection Device connection structure to be initialized.
+ * @param hc_connection Initialized connection to host controller.
+ * @return Error code.
+ */
+int usb_device_connection_initialize_on_default_address(
+    usb_device_connection_t *dev_connection,
+    usb_hc_connection_t *hc_connection)
+{
+	assert(dev_connection);
+
+	if (hc_connection == NULL) {
+		return EBADMEM;
+	}
+
+	return usb_device_connection_initialize(dev_connection,
+	    hc_connection->hc_handle, (usb_address_t) 0);
+}
+
+
+/** Start a session on the endpoint pipe.
+ *
+ * A session is something inside what any communication occurs.
+ * It is expected that sessions would be started right before the transfer
+ * and ended - see usb_endpoint_pipe_end_session() - after the last
+ * transfer.
+ * The reason for this is that session actually opens some communication
+ * channel to the host controller (or to the physical hardware if you
+ * wish) and thus it involves acquiring kernel resources.
+ * Since they are limited, sessions shall not be longer than strictly
+ * necessary.
+ *
+ * @param pipe Endpoint pipe to start the session on.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *pipe)
+{
+	assert(pipe);
+
+	if (usb_endpoint_pipe_is_session_started(pipe)) {
+		return EBUSY;
+	}
+
+	int phone = devman_device_connect(pipe->wire->hc_handle, 0);
+	if (phone < 0) {
+		return phone;
+	}
+
+	pipe->hc_phone = phone;
+
+	return EOK;
+}
+
+
+/** Ends a session on the endpoint pipe.
+ *
+ * @see usb_endpoint_pipe_start_session
+ *
+ * @param pipe Endpoint pipe to end the session on.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_end_session(usb_endpoint_pipe_t *pipe)
+{
+	assert(pipe);
+
+	if (!usb_endpoint_pipe_is_session_started(pipe)) {
+		return ENOENT;
+	}
+
+	int rc = async_hangup(pipe->hc_phone);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	pipe->hc_phone = -1;
+
+	return EOK;
+}
+
+/** Tell whether a session is started (open) on the endpoint pipe.
+ *
+ * The expected usage of this function is in assertions for some
+ * nested functions.
+ *
+ * @param pipe Endpoint pipe in question.
+ * @return Whether @p pipe has opened a session.
+ */
+bool usb_endpoint_pipe_is_session_started(usb_endpoint_pipe_t *pipe)
+{
+	return (pipe->hc_phone >= 0);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/pipesinit.c
===================================================================
--- uspace/lib/usb/src/pipesinit.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/pipesinit.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Initialization of endpoint pipes.
+ *
+ */
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <usb/dp.h>
+#include <errno.h>
+#include <assert.h>
+
+
+#define NESTING(parentname, childname) \
+	{ \
+		.child = USB_DESCTYPE_##childname, \
+		.parent = USB_DESCTYPE_##parentname, \
+	}
+#define LAST_NESTING { -1, -1 }
+
+/** Nesting pairs of standard descriptors. */
+static usb_dp_descriptor_nesting_t descriptor_nesting[] = {
+	NESTING(CONFIGURATION, INTERFACE),
+	NESTING(INTERFACE, ENDPOINT),
+	NESTING(INTERFACE, HUB),
+	NESTING(INTERFACE, HID),
+	NESTING(HID, HID_REPORT),
+	LAST_NESTING
+};
+
+/** Tells whether given descriptor is of endpoint type.
+ *
+ * @param descriptor Descriptor in question.
+ * @return Whether the given descriptor is endpoint descriptor.
+ */
+static inline bool is_endpoint_descriptor(uint8_t *descriptor)
+{
+	return descriptor[1] == USB_DESCTYPE_ENDPOINT;
+}
+
+/** Tells whether found endpoint corresponds to endpoint described by user.
+ *
+ * @param wanted Endpoint description as entered by driver author.
+ * @param found Endpoint description obtained from endpoint descriptor.
+ * @return Whether the @p found descriptor fits the @p wanted descriptor.
+ */
+static bool endpoint_fits_description(const usb_endpoint_description_t *wanted,
+    usb_endpoint_description_t *found)
+{
+#define _SAME(fieldname) ((wanted->fieldname) == (found->fieldname))
+
+	if (!_SAME(direction)) {
+		return false;
+	}
+
+	if (!_SAME(transfer_type)) {
+		return false;
+	}
+
+	if ((wanted->interface_class >= 0) && !_SAME(interface_class)) {
+		return false;
+	}
+
+	if ((wanted->interface_subclass >= 0) && !_SAME(interface_subclass)) {
+		return false;
+	}
+
+	if ((wanted->interface_protocol >= 0) && !_SAME(interface_protocol)) {
+		return false;
+	}
+
+#undef _SAME
+
+	return true;
+}
+
+/** Find endpoint mapping for a found endpoint.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param found_endpoint Description of found endpoint.
+ * @param interface_number Number of currently processed interface.
+ * @return Endpoint mapping corresponding to @p found_endpoint.
+ * @retval NULL No corresponding endpoint found.
+ */
+static usb_endpoint_mapping_t *find_endpoint_mapping(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_endpoint_description_t *found_endpoint,
+    int interface_number)
+{
+	while (mapping_count > 0) {
+		bool interface_number_fits = (mapping->interface_no < 0)
+		    || (mapping->interface_no == interface_number);
+
+		bool endpoint_descriptions_fits = endpoint_fits_description(
+		    mapping->description, found_endpoint);
+
+		if (interface_number_fits && endpoint_descriptions_fits) {
+			return mapping;
+		}
+
+		mapping++;
+		mapping_count--;
+	}
+	return NULL;
+}
+
+/** Process endpoint descriptor.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param interface Interface descriptor under which belongs the @p endpoint.
+ * @param endpoint Endpoint descriptor.
+ * @param wire Connection backing the endpoint pipes.
+ * @return Error code.
+ */
+static int process_endpoint(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_standard_interface_descriptor_t *interface,
+    usb_standard_endpoint_descriptor_t *endpoint,
+    usb_device_connection_t *wire)
+{
+	usb_endpoint_description_t description;
+
+	/*
+	 * Get endpoint characteristics.
+	 */
+
+	/* Actual endpoint number is in bits 0..3 */
+	usb_endpoint_t ep_no = endpoint->endpoint_address & 0x0F;
+
+	/* Endpoint direction is set by bit 7 */
+	description.direction = (endpoint->endpoint_address & 128)
+	    ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
+	/* Transfer type is in bits 0..2 and the enum values corresponds 1:1 */
+	description.transfer_type = endpoint->attributes & 3;
+
+	/*
+	 * Get interface characteristics.
+	 */
+	description.interface_class = interface->interface_class;
+	description.interface_subclass = interface->interface_subclass;
+	description.interface_protocol = interface->interface_protocol;
+
+	/*
+	 * Find the most fitting mapping and initialize the pipe.
+	 */
+	usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping,
+	    mapping_count, &description, interface->interface_number);
+	if (ep_mapping == NULL) {
+		return ENOENT;
+	}
+
+	if (ep_mapping->pipe == NULL) {
+		return EBADMEM;
+	}
+	if (ep_mapping->present) {
+		return EEXISTS;
+	}
+
+	int rc = usb_endpoint_pipe_initialize(ep_mapping->pipe, wire,
+	    ep_no, description.transfer_type, endpoint->max_packet_size,
+	    description.direction);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	ep_mapping->present = true;
+	ep_mapping->descriptor = endpoint;
+	ep_mapping->interface = interface;
+
+	return EOK;
+}
+
+/** Process whole USB interface.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param parser Descriptor parser.
+ * @param parser_data Descriptor parser data.
+ * @param interface_descriptor Interface descriptor.
+ * @return Error code.
+ */
+static int process_interface(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_dp_parser_t *parser, usb_dp_parser_data_t *parser_data,
+    uint8_t *interface_descriptor)
+{
+	uint8_t *descriptor = usb_dp_get_nested_descriptor(parser,
+	    parser_data, interface_descriptor);
+
+	if (descriptor == NULL) {
+		return ENOENT;
+	}
+
+	do {
+		if (is_endpoint_descriptor(descriptor)) {
+			(void) process_endpoint(mapping, mapping_count,
+			    (usb_standard_interface_descriptor_t *)
+			        interface_descriptor,
+			    (usb_standard_endpoint_descriptor_t *)
+			        descriptor,
+			    (usb_device_connection_t *) parser_data->arg);
+		}
+
+		descriptor = usb_dp_get_sibling_descriptor(parser, parser_data,
+		    interface_descriptor, descriptor);
+	} while (descriptor != NULL);
+
+	return EOK;
+}
+
+/** Initialize endpoint pipes from configuration descriptor.
+ *
+ * The mapping array is expected to conform to following rules:
+ * - @c pipe must point to already allocated structure with uninitialized pipe
+ * - @c description must point to prepared endpoint description
+ * - @c descriptor does not need to be initialized (will be overwritten)
+ * - @c interface does not need to be initialized (will be overwritten)
+ * - @c present does not need to be initialized (will be overwritten)
+ *
+ * After processing the configuration descriptor, the mapping is updated
+ * in the following fashion:
+ * - @c present will be set to @c true when the endpoint was found in the
+ *   configuration
+ * - @c descriptor will point inside the configuration descriptor to endpoint
+ *   corresponding to given description (or NULL for not found descriptor)
+ * - @c interface will point inside the configuration descriptor to interface
+ *   descriptor the endpoint @c descriptor belongs to (or NULL for not found
+ *   descriptor)
+ * - @c pipe will be initialized when found, otherwise left untouched
+ * - @c description will be untouched under all circumstances
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param configuration_descriptor Full configuration descriptor (is expected
+ *	to be in USB endianness: i.e. as-is after being retrieved from
+ *	the device).
+ * @param configuration_descriptor_size Size of @p configuration_descriptor
+ *	in bytes.
+ * @param connection Connection backing the endpoint pipes.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_initialize_from_configuration(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    uint8_t *configuration_descriptor, size_t configuration_descriptor_size,
+    usb_device_connection_t *connection)
+{
+	assert(connection);
+
+	if (configuration_descriptor == NULL) {
+		return EBADMEM;
+	}
+	if (configuration_descriptor_size
+	    < sizeof(usb_standard_configuration_descriptor_t)) {
+		return ERANGE;
+	}
+
+	/*
+	 * Go through the mapping and set all endpoints to not present.
+	 */
+	size_t i;
+	for (i = 0; i < mapping_count; i++) {
+		mapping[i].present = false;
+		mapping[i].descriptor = NULL;
+		mapping[i].interface = NULL;
+	}
+
+	/*
+	 * Prepare the descriptor parser.
+	 */
+	usb_dp_parser_t dp_parser = {
+		.nesting = descriptor_nesting
+	};
+	usb_dp_parser_data_t dp_data = {
+		.data = configuration_descriptor,
+		.size = configuration_descriptor_size,
+		.arg = connection
+	};
+
+	/*
+	 * Iterate through all interfaces.
+	 */
+	uint8_t *interface = usb_dp_get_nested_descriptor(&dp_parser,
+	    &dp_data, configuration_descriptor);
+	if (interface == NULL) {
+		return ENOENT;
+	}
+	do {
+		(void) process_interface(mapping, mapping_count,
+		    &dp_parser, &dp_data,
+		    interface);
+		interface = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
+		    configuration_descriptor, interface);
+	} while (interface != NULL);
+
+	return EOK;
+}
+
+/** Initialize USB endpoint pipe.
+ *
+ * @param pipe Endpoint pipe to be initialized.
+ * @param connection Connection to the USB device backing this pipe (the wire).
+ * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
+ * @param transfer_type Transfer type (e.g. interrupt or bulk).
+ * @param max_packet_size Maximum packet size in bytes.
+ * @param direction Endpoint direction (in/out).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *pipe,
+    usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
+    usb_transfer_type_t transfer_type, size_t max_packet_size,
+    usb_direction_t direction)
+{
+	assert(pipe);
+	assert(connection);
+
+	pipe->wire = connection;
+	pipe->hc_phone = -1;
+	pipe->endpoint_no = endpoint_no;
+	pipe->transfer_type = transfer_type;
+	pipe->max_packet_size = max_packet_size;
+	pipe->direction = direction;
+
+	return EOK;
+}
+
+
+/** Initialize USB endpoint pipe as the default zero control pipe.
+ *
+ * @param pipe Endpoint pipe to be initialized.
+ * @param connection Connection to the USB device backing this pipe (the wire).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *pipe,
+    usb_device_connection_t *connection)
+{
+	assert(pipe);
+	assert(connection);
+
+	int rc = usb_endpoint_pipe_initialize(pipe, connection,
+	    0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH);
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/pipesio.c
===================================================================
--- uspace/lib/usb/src/pipesio.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/pipesio.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,501 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Input and output functions (reads and writes) on endpoint pipes.
+ *
+ * Note on synchronousness of the operations: there is ABSOLUTELY NO
+ * guarantee that a call to particular function will not trigger a fibril
+ * switch.
+ *
+ * Note about the implementation: the transfer requests are always divided
+ * into two functions.
+ * The outer one does checking of input parameters (e.g. that session was
+ * already started, buffers are not NULL etc), while the inner one
+ * (with _no_checks suffix) does the actual IPC (it checks for IPC errors,
+ * obviously).
+ */
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <errno.h>
+#include <assert.h>
+#include <usbhc_iface.h>
+
+/** Request an in transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[out] buffer Buffer where to store the data.
+ * @param[in] size Size of the buffer (in bytes).
+ * @param[out] size_transfered Number of bytes that were actually transfered.
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_read_no_checks(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size, size_t *size_transfered)
+{
+	/*
+	 * Get corresponding IPC method.
+	 * In future, replace with static array of mappings
+	 * transfer type -> method.
+	 */
+	usbhc_iface_funcs_t ipc_method;
+	switch (pipe->transfer_type) {
+		case USB_TRANSFER_INTERRUPT:
+			ipc_method = IPC_M_USBHC_INTERRUPT_IN;
+			break;
+		case USB_TRANSFER_BULK:
+			ipc_method = IPC_M_USBHC_BULK_IN;
+			break;
+		default:
+			return ENOTSUP;
+	}
+
+	/*
+	 * Make call identifying target USB device and type of transfer.
+	 */
+	aid_t opening_request = async_send_4(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
+	    pipe->wire->address, pipe->endpoint_no,
+	    pipe->max_packet_size,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Retrieve the data.
+	 */
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
+	    &data_request_call);
+
+	if (data_request == 0) {
+		/*
+		 * FIXME:
+		 * How to let the other side know that we want to abort?
+		 */
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+
+	if (data_request_rc != EOK) {
+		return (int) data_request_rc;
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	*size_transfered = IPC_GET_ARG2(data_request_call);
+
+	return EOK;
+}
+
+
+/** Request a read (in) transfer on an endpoint pipe.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[out] buffer Buffer where to store the data.
+ * @param[in] size Size of the buffer (in bytes).
+ * @param[out] size_transfered Number of bytes that were actually transfered.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_read(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size, size_t *size_transfered)
+{
+	assert(pipe);
+
+	if (buffer == NULL) {
+			return EINVAL;
+	}
+
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	if (!usb_endpoint_pipe_is_session_started(pipe)) {
+		return EBADF;
+	}
+
+	if (pipe->direction != USB_DIRECTION_IN) {
+		return EBADF;
+	}
+
+	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
+		return EBADF;
+	}
+
+	size_t act_size = 0;
+	int rc;
+
+	rc = usb_endpoint_pipe_read_no_checks(pipe, buffer, size, &act_size);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (size_transfered != NULL) {
+		*size_transfered = act_size;
+	}
+
+	return EOK;
+}
+
+
+
+
+/** Request an out transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] buffer Buffer with data to transfer.
+ * @param[in] size Size of the buffer (in bytes).
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_write_no_check(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size)
+{
+	/*
+	 * Get corresponding IPC method.
+	 * In future, replace with static array of mappings
+	 * transfer type -> method.
+	 */
+	usbhc_iface_funcs_t ipc_method;
+	switch (pipe->transfer_type) {
+		case USB_TRANSFER_INTERRUPT:
+			ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
+			break;
+		case USB_TRANSFER_BULK:
+			ipc_method = IPC_M_USBHC_BULK_OUT;
+			break;
+		default:
+			return ENOTSUP;
+	}
+
+	/*
+	 * Make call identifying target USB device and type of transfer.
+	 */
+	aid_t opening_request = async_send_4(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
+	    pipe->wire->address, pipe->endpoint_no,
+	    pipe->max_packet_size,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Send the data.
+	 */
+	int rc = async_data_write_start(pipe->hc_phone, buffer, size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+
+	return (int) opening_request_rc;
+}
+
+/** Request a write (out) transfer on an endpoint pipe.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] buffer Buffer with data to transfer.
+ * @param[in] size Size of the buffer (in bytes).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_write(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size)
+{
+	assert(pipe);
+
+	if (buffer == NULL) {
+		return EINVAL;
+	}
+
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	if (!usb_endpoint_pipe_is_session_started(pipe)) {
+		return EBADF;
+	}
+
+	if (pipe->direction != USB_DIRECTION_OUT) {
+		return EBADF;
+	}
+
+	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
+		return EBADF;
+	}
+
+	int rc = usb_endpoint_pipe_write_no_check(pipe, buffer, size);
+
+	return rc;
+}
+
+
+/** Request a control read transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[out] data_buffer Buffer for incoming data.
+ * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
+ * @param[out] data_transfered_size Number of bytes that were actually
+ *                                  transfered during the DATA stage.
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_control_read_no_check(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
+{
+	/*
+	 * Make call identifying target USB device and control transfer type.
+	 */
+	aid_t opening_request = async_send_4(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
+	    pipe->wire->address, pipe->endpoint_no,
+	    pipe->max_packet_size,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Send the setup packet.
+	 */
+	int rc = async_data_write_start(pipe->hc_phone,
+	    setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	/*
+	 * Retrieve the data.
+	 */
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(pipe->hc_phone,
+	    data_buffer, data_buffer_size,
+	    &data_request_call);
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+
+	if (data_request_rc != EOK) {
+		return (int) data_request_rc;
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	*data_transfered_size = IPC_GET_ARG2(data_request_call);
+
+	return EOK;
+}
+
+/** Request a control read transfer on an endpoint pipe.
+ *
+ * This function encapsulates all three stages of a control transfer.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[out] data_buffer Buffer for incoming data.
+ * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
+ * @param[out] data_transfered_size Number of bytes that were actually
+ *                                  transfered during the DATA stage.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
+{
+	assert(pipe);
+
+	if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer == NULL) || (data_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if (!usb_endpoint_pipe_is_session_started(pipe)) {
+		return EBADF;
+	}
+
+	if ((pipe->direction != USB_DIRECTION_BOTH)
+	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
+		return EBADF;
+	}
+
+	size_t act_size = 0;
+	int rc = usb_endpoint_pipe_control_read_no_check(pipe,
+	    setup_buffer, setup_buffer_size,
+	    data_buffer, data_buffer_size, &act_size);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (data_transfered_size != NULL) {
+		*data_transfered_size = act_size;
+	}
+
+	return EOK;
+}
+
+
+/** Request a control write transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[in] data_buffer Buffer with data to be sent.
+ * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_control_write_no_check(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size)
+{
+	/*
+	 * Make call identifying target USB device and control transfer type.
+	 */
+	aid_t opening_request = async_send_5(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
+	    pipe->wire->address, pipe->endpoint_no,
+	    data_buffer_size,
+	    pipe->max_packet_size,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Send the setup packet.
+	 */
+	int rc = async_data_write_start(pipe->hc_phone,
+	    setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	/*
+	 * Send the data (if any).
+	 */
+	if (data_buffer_size > 0) {
+		rc = async_data_write_start(pipe->hc_phone,
+		    data_buffer, data_buffer_size);
+		if (rc != EOK) {
+			async_wait_for(opening_request, NULL);
+			return rc;
+		}
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+
+	return (int) opening_request_rc;
+}
+
+/** Request a control write transfer on an endpoint pipe.
+ *
+ * This function encapsulates all three stages of a control transfer.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[in] data_buffer Buffer with data to be sent.
+ * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size)
+{
+	assert(pipe);
+
+	if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer == NULL) && (data_buffer_size > 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer != NULL) && (data_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if (!usb_endpoint_pipe_is_session_started(pipe)) {
+		return EBADF;
+	}
+
+	if ((pipe->direction != USB_DIRECTION_BOTH)
+	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
+		return EBADF;
+	}
+
+	int rc = usb_endpoint_pipe_control_write_no_check(pipe,
+	    setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
+
+	return rc;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/recognise.c
===================================================================
--- uspace/lib/usb/src/recognise.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/recognise.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -33,36 +33,20 @@
  * @brief Functions for recognising kind of attached devices.
  */
-#include <usb_iface.h>
-#include <usb/usbdrv.h>
+#include <sys/types.h>
+#include <fibril_synch.h>
+#include <usb/pipes.h>
+#include <usb/recognise.h>
+#include <usb/ddfiface.h>
+#include <usb/request.h>
 #include <usb/classes/classes.h>
 #include <stdio.h>
 #include <errno.h>
-
-static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
-{
-	assert(dev);
-	assert(dev->parent != NULL);
-
-	device_t *parent = dev->parent;
-
-	if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
-		usb_iface_t *usb_iface
-		    = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
-		assert(usb_iface != NULL);
-		if (usb_iface->get_hc_handle) {
-			int rc = usb_iface->get_hc_handle(parent, handle);
-			return rc;
-		}
-	}
-
-	return ENOTSUP;
-}
-
-static usb_iface_t usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle
-};
-
-static device_ops_t child_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface
+#include <assert.h>
+
+static size_t device_name_index = 0;
+static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
+
+ddf_dev_ops_t child_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
 };
 
@@ -129,4 +113,127 @@
 }
 
+#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
+	do { \
+		int __rc = usb_add_match_id((match_ids), (score), \
+		    format, ##__VA_ARGS__); \
+		if (__rc != EOK) { \
+			return __rc; \
+		} \
+	} while (0)
+
+/** Create device match ids based on its interface.
+ *
+ * @param[in] descriptor Interface descriptor.
+ * @param[out] matches Initialized list of match ids.
+ * @return Error code (the two mentioned are not the only ones).
+ * @retval EINVAL Invalid input parameters (expects non NULL pointers).
+ * @retval ENOENT Interface does not specify class.
+ */
+int usb_device_create_match_ids_from_interface(
+    const usb_standard_device_descriptor_t *desc_device,
+    const usb_standard_interface_descriptor_t *desc_interface,
+    match_id_list_t *matches)
+{
+	if (desc_interface == NULL) {
+		return EINVAL;
+	}
+	if (matches == NULL) {
+		return EINVAL;
+	}
+
+	if (desc_interface->interface_class == USB_CLASS_USE_INTERFACE) {
+		return ENOENT;
+	}
+
+	const char *classname = usb_str_class(desc_interface->interface_class);
+	assert(classname != NULL);
+
+#define IFACE_PROTOCOL_FMT "interface&class=%s&subclass=0x%02x&protocol=0x%02x"
+#define IFACE_PROTOCOL_ARGS classname, desc_interface->interface_subclass, \
+    desc_interface->interface_protocol
+
+#define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x"
+#define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass
+
+#define IFACE_CLASS_FMT "interface&class=%s"
+#define IFACE_CLASS_ARGS classname
+
+#define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT
+#define VENDOR_RELEASE_ARGS desc_device->vendor_id, desc_device->product_id, \
+    BCD_ARGS(desc_device->device_version)
+
+#define VENDOR_PRODUCT_FMT "vendor=0x%04x&product=0x%04x"
+#define VENDOR_PRODUCT_ARGS desc_device->vendor_id, desc_device->product_id
+
+#define VENDOR_ONLY_FMT "vendor=0x%04x"
+#define VENDOR_ONLY_ARGS desc_device->vendor_id
+
+	/*
+	 * If the vendor is specified, create match ids with vendor with
+	 * higher score.
+	 * Then the same ones without the vendor part.
+	 */
+	if ((desc_device != NULL) && (desc_device->vendor_id != 0)) {
+		/* First, interface matches with device release number. */
+		ADD_MATCHID_OR_RETURN(matches, 250,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 240,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 230,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_CLASS_ARGS);
+
+		/* Next, interface matches without release number. */
+		ADD_MATCHID_OR_RETURN(matches, 220,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 210,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 200,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_CLASS_ARGS);
+
+		/* Finally, interface matches with only vendor. */
+		ADD_MATCHID_OR_RETURN(matches, 190,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 180,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 170,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_CLASS_ARGS);
+	}
+
+	/* Now, the same but without any vendor specification. */
+	ADD_MATCHID_OR_RETURN(matches, 160,
+	    "usb&" IFACE_PROTOCOL_FMT,
+	    IFACE_PROTOCOL_ARGS);
+	ADD_MATCHID_OR_RETURN(matches, 150,
+	    "usb&" IFACE_SUBCLASS_FMT,
+	    IFACE_SUBCLASS_ARGS);
+	ADD_MATCHID_OR_RETURN(matches, 140,
+	    "usb&" IFACE_CLASS_FMT,
+	    IFACE_CLASS_ARGS);
+
+#undef IFACE_PROTOCOL_FMT
+#undef IFACE_PROTOCOL_ARGS
+#undef IFACE_SUBCLASS_FMT
+#undef IFACE_SUBCLASS_ARGS
+#undef IFACE_CLASS_FMT
+#undef IFACE_CLASS_ARGS
+#undef VENDOR_RELEASE_FMT
+#undef VENDOR_RELEASE_ARGS
+#undef VENDOR_PRODUCT_FMT
+#undef VENDOR_PRODUCT_ARGS
+#undef VENDOR_ONLY_FMT
+#undef VENDOR_ONLY_ARGS
+
+	return EOK;
+}
+
 /** Create DDF match ids from USB device descriptor.
  *
@@ -135,10 +242,8 @@
  * @return Error code.
  */
-int usb_drv_create_match_ids_from_device_descriptor(
-    match_id_list_t *matches,
-    const usb_standard_device_descriptor_t *device_descriptor)
+int usb_device_create_match_ids_from_device_descriptor(
+    const usb_standard_device_descriptor_t *device_descriptor,
+    match_id_list_t *matches)
 {
-	int rc;
-	
 	/*
 	 * Unless the vendor id is 0, the pair idVendor-idProduct
@@ -147,32 +252,26 @@
 	if (device_descriptor->vendor_id != 0) {
 		/* First, with release number. */
-		rc = usb_add_match_id(matches, 100,
-		    "usb&vendor=%d&product=%d&release=" BCD_FMT,
+		ADD_MATCHID_OR_RETURN(matches, 100,
+		    "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT,
 		    (int) device_descriptor->vendor_id,
 		    (int) device_descriptor->product_id,
 		    BCD_ARGS(device_descriptor->device_version));
-		if (rc != EOK) {
-			return rc;
-		}
 		
 		/* Next, without release number. */
-		rc = usb_add_match_id(matches, 90, "usb&vendor=%d&product=%d",
+		ADD_MATCHID_OR_RETURN(matches, 90,
+		    "usb&vendor=0x%04x&product=0x%04x",
 		    (int) device_descriptor->vendor_id,
 		    (int) device_descriptor->product_id);
-		if (rc != EOK) {
-			return rc;
-		}
 	}	
 
 	/*
 	 * If the device class points to interface we skip adding
-	 * class directly.
+	 * class directly but we add a multi interface device.
 	 */
 	if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) {
-		rc = usb_add_match_id(matches, 50, "usb&class=%s",
+		ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
 		    usb_str_class(device_descriptor->device_class));
-		if (rc != EOK) {
-			return rc;
-		}
+	} else {
+		ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid");
 	}
 	
@@ -180,177 +279,85 @@
 }
 
-/** Create DDF match ids from USB configuration descriptor.
- * The configuration descriptor is expected to be in the complete form,
- * i.e. including interface, endpoint etc. descriptors.
- *
- * @param matches List of match ids to extend.
- * @param config_descriptor Configuration descriptor returned by given device.
- * @param total_size Size of the @p config_descriptor.
+
+/** Create match ids describing attached device.
+ *
+ * @warning The list of match ids @p matches may change even when
+ * function exits with error.
+ *
+ * @param ctrl_pipe Control pipe to given device (session must be already
+ *	started).
+ * @param matches Initialized list of match ids.
  * @return Error code.
  */
-int usb_drv_create_match_ids_from_configuration_descriptor(
-    match_id_list_t *matches,
-    const void *config_descriptor, size_t total_size)
+int usb_device_create_match_ids(usb_endpoint_pipe_t *ctrl_pipe,
+    match_id_list_t *matches)
 {
-	/*
-	 * Iterate through config descriptor to find the interface
-	 * descriptors.
-	 */
-	size_t position = sizeof(usb_standard_configuration_descriptor_t);
-	while (position + 1 < total_size) {
-		uint8_t *current_descriptor
-		    = ((uint8_t *) config_descriptor) + position;
-		uint8_t cur_descr_len = current_descriptor[0];
-		uint8_t cur_descr_type = current_descriptor[1];
-		
-		position += cur_descr_len;
-		
-		if (cur_descr_type != USB_DESCTYPE_INTERFACE) {
-			continue;
-		}
-		
-		/*
-		 * Finally, we found an interface descriptor.
-		 */
-		usb_standard_interface_descriptor_t *interface
-		    = (usb_standard_interface_descriptor_t *)
-		    current_descriptor;
-		
-		int rc = usb_add_match_id(matches, 50,
-		    "usb&interface&class=%s",
-		    usb_str_class(interface->interface_class));
-		if (rc != EOK) {
-			return rc;
-		}
-	}
-	
+	int rc;
+	/*
+	 * Retrieve device descriptor and add matches from it.
+	 */
+	usb_standard_device_descriptor_t device_descriptor;
+
+	rc = usb_request_get_device_descriptor(ctrl_pipe, &device_descriptor);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_device_create_match_ids_from_device_descriptor(
+	    &device_descriptor, matches);
+	if (rc != EOK) {
+		return rc;
+	}
+
 	return EOK;
 }
 
-/** Add match ids based on configuration descriptor.
- *
- * @param hc Open phone to host controller.
- * @param matches Match ids list to add matches to.
- * @param address USB address of the attached device.
+/** Probe for device kind and register it in devman.
+ *
+ * @param[in] address Address of the (unknown) attached device.
+ * @param[in] hc_handle Handle of the host controller.
+ * @param[in] parent Parent device.
+ * @param[out] child_handle Handle of the child device.
  * @return Error code.
  */
-static int usb_add_config_descriptor_match_ids(int hc,
-    match_id_list_t *matches, usb_address_t address,
-    int config_count)
+int usb_device_register_child_in_devman(usb_address_t address,
+    devman_handle_t hc_handle,
+    ddf_dev_t *parent, devman_handle_t *child_handle,
+    ddf_dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)
 {
-	int final_rc = EOK;
-	
-	int config_index;
-	for (config_index = 0; config_index < config_count; config_index++) {
-		int rc;
-		usb_standard_configuration_descriptor_t config_descriptor;
-		rc = usb_drv_req_get_bare_configuration_descriptor(hc,
-		    address,  config_index, &config_descriptor);
-		if (rc != EOK) {
-			final_rc = rc;
-			continue;
-		}
-
-		size_t full_config_descriptor_size;
-		void *full_config_descriptor
-		    = malloc(config_descriptor.total_length);
-		rc = usb_drv_req_get_full_configuration_descriptor(hc,
-		    address, config_index,
-		    full_config_descriptor, config_descriptor.total_length,
-		    &full_config_descriptor_size);
-		if (rc != EOK) {
-			final_rc = rc;
-			continue;
-		}
-		if (full_config_descriptor_size
-		    != config_descriptor.total_length) {
-			final_rc = ERANGE;
-			continue;
-		}
-		
-		rc = usb_drv_create_match_ids_from_configuration_descriptor(
-		    matches,
-		    full_config_descriptor, full_config_descriptor_size);
-		if (rc != EOK) {
-			final_rc = rc;
-			continue;
-		}
-		
-	}
-	
-	return final_rc;
-}
-
-/** Create match ids describing attached device.
- *
- * @warning The list of match ids @p matches may change even when
- * function exits with error.
- *
- * @param hc Open phone to host controller.
- * @param matches Initialized list of match ids.
- * @param address USB address of the attached device.
- * @return Error code.
- */
-int usb_drv_create_device_match_ids(int hc, match_id_list_t *matches,
-    usb_address_t address)
-{
-	int rc;
-	
-	/*
-	 * Retrieve device descriptor and add matches from it.
-	 */
-	usb_standard_device_descriptor_t device_descriptor;
-
-	rc = usb_drv_req_get_device_descriptor(hc, address,
-	    &device_descriptor);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	rc = usb_drv_create_match_ids_from_device_descriptor(matches,
-	    &device_descriptor);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	/*
-	 * Go through all configurations and add matches
-	 * based on interface class.
-	 */
-	rc = usb_add_config_descriptor_match_ids(hc, matches,
-	    address, device_descriptor.configuration_count);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/*
-	 * As a fallback, provide the simplest match id possible.
-	 */
-	rc = usb_add_match_id(matches, 1, "usb&fallback");
-	if (rc != EOK) {
-		return rc;
-	}
-
-	return EOK;
-}
-
-
-/** Probe for device kind and register it in devman.
- *
- * @param hc Open phone to the host controller.
- * @param parent Parent device.
- * @param address Address of the (unknown) attached device.
- * @return Error code.
- */
-int usb_drv_register_child_in_devman(int hc, device_t *parent,
-    usb_address_t address, devman_handle_t *child_handle)
-{
-	static size_t device_name_index = 0;
-
-	device_t *child = NULL;
+	size_t this_device_name_index;
+
+	fibril_mutex_lock(&device_name_index_mutex);
+	this_device_name_index = device_name_index;
+	device_name_index++;
+	fibril_mutex_unlock(&device_name_index_mutex);
+
+	ddf_fun_t *child = NULL;
 	char *child_name = NULL;
 	int rc;
-
-	child = create_device();
+	usb_device_connection_t dev_connection;
+	usb_endpoint_pipe_t ctrl_pipe;
+
+	rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe,
+	    &dev_connection);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	/*
+	 * TODO: Once the device driver framework support persistent
+	 * naming etc., something more descriptive could be created.
+	 */
+	rc = asprintf(&child_name, "usbdev%02zu", this_device_name_index);
+	if (rc < 0) {
+		goto failure;
+	}
+
+	child = ddf_fun_create(parent, fun_inner, child_name);
 	if (child == NULL) {
 		rc = ENOMEM;
@@ -358,22 +365,28 @@
 	}
 
-	/*
-	 * TODO: Once the device driver framework support persistent
-	 * naming etc., something more descriptive could be created.
-	 */
-	rc = asprintf(&child_name, "usbdev%02zu", device_name_index);
-	if (rc < 0) {
-		goto failure;
-	}
-	child->parent = parent;
-	child->name = child_name;
-	child->ops = &child_ops;
-	
-	rc = usb_drv_create_device_match_ids(hc, &child->match_ids, address);
-	if (rc != EOK) {
-		goto failure;
-	}
-
-	rc = child_device_register(child, parent);
+	if (dev_ops != NULL) {
+		child->ops = dev_ops;
+	} else {
+		child->ops = &child_ops;
+	}
+
+	child->driver_data = dev_data;
+
+	rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = usb_endpoint_pipe_end_session(&ctrl_pipe);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = ddf_fun_bind(child);
 	if (rc != EOK) {
 		goto failure;
@@ -383,6 +396,8 @@
 		*child_handle = child->handle;
 	}
-	
-	device_name_index++;
+
+	if (child_fun != NULL) {
+		*child_fun = child;
+	}
 
 	return EOK;
@@ -392,5 +407,5 @@
 		child->name = NULL;
 		/* This takes care of match_id deallocation as well. */
-		delete_device(child);
+		ddf_fun_destroy(child);
 	}
 	if (child_name != NULL) {
@@ -399,5 +414,4 @@
 
 	return rc;
-
 }
 
Index: pace/lib/usb/src/remotedrv.c
===================================================================
--- uspace/lib/usb/src/remotedrv.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,437 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief Driver communication for remote drivers (interface implementation).
- */
-#include <usb/hcdhubd.h>
-#include <usbhc_iface.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-
-#include "hcdhubd_private.h"
-
-static int remote_get_address(device_t *, devman_handle_t, usb_address_t *);
-
-static int remote_interrupt_out(device_t *, usb_target_t, void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_interrupt_in(device_t *, usb_target_t, void *, size_t,
-    usbhc_iface_transfer_in_callback_t, void *);
-
-static int remote_control_write_setup(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_control_write_data(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_control_write_status(device_t *, usb_target_t,
-    usbhc_iface_transfer_in_callback_t, void *);
-
-static int remote_control_read_setup(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_control_read_data(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_in_callback_t, void *);
-static int remote_control_read_status(device_t *, usb_target_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-
-/** Implementation of USB HC interface. */
-usbhc_iface_t usbhc_interface = {
-	.tell_address = remote_get_address,
-	.interrupt_out = remote_interrupt_out,
-	.interrupt_in = remote_interrupt_in,
-	.control_write_setup = remote_control_write_setup,
-	.control_write_data = remote_control_write_data,
-	.control_write_status = remote_control_write_status,
-	.control_read_setup = remote_control_read_setup,
-	.control_read_data = remote_control_read_data,
-	.control_read_status = remote_control_read_status
-};
-
-/** Get USB address for remote USBHC interface.
- *
- * @param dev Device asked for the information.
- * @param handle Devman handle of the USB device.
- * @param address Storage for obtained address.
- * @return Error code.
- */
-int remote_get_address(device_t *dev, devman_handle_t handle,
-    usb_address_t *address)
-{
-	usb_address_t addr = usb_get_address_by_handle(handle);
-	if (addr < 0) {
-		return addr;
-	}
-
-	*address = addr;
-
-	return EOK;
-}
-
-/** Information about pending transaction on HC. */
-typedef struct {
-	/** Target device. */
-	usb_hcd_attached_device_info_t *device;
-	/** Target endpoint. */
-	usb_hc_endpoint_info_t *endpoint;
-
-	/** Callbacks. */
-	union {
-		/** Callback for outgoing transfers. */
-		usbhc_iface_transfer_out_callback_t out_callback;
-		/** Callback for incoming transfers. */
-		usbhc_iface_transfer_in_callback_t in_callback;
-	};
-
-	/** Custom argument for the callback. */
-	void *arg;
-} transfer_info_t;
-
-/** Create new transfer info.
- *
- * @param device Attached device.
- * @param endpoint Endpoint.
- * @param custom_arg Custom argument.
- * @return Transfer info with pre-filled values.
- */
-static transfer_info_t *transfer_info_create(
-    usb_hcd_attached_device_info_t *device, usb_hc_endpoint_info_t *endpoint,
-    void *custom_arg)
-{
-	transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
-
-	transfer->device = device;
-	transfer->endpoint = endpoint;
-	transfer->arg = custom_arg;
-	transfer->out_callback = NULL;
-	transfer->in_callback = NULL;
-
-	return transfer;
-}
-
-/** Destroy transfer info.
- *
- * @param transfer Transfer to be destroyed.
- */
-static void transfer_info_destroy(transfer_info_t *transfer)
-{
-	free(transfer->device);
-	free(transfer->endpoint);
-	free(transfer);
-}
-
-/** Create info about attached device.
- *
- * @param address Device address.
- * @return Device info structure.
- */
-static usb_hcd_attached_device_info_t *create_attached_device_info(
-    usb_address_t address)
-{
-	usb_hcd_attached_device_info_t *dev
-	    = malloc(sizeof(usb_hcd_attached_device_info_t));
-
-	dev->address = address;
-	dev->endpoint_count = 0;
-	dev->endpoints = NULL;
-	list_initialize(&dev->link);
-
-	return dev;
-}
-
-/** Create info about device endpoint.
- *
- * @param endpoint Endpoint number.
- * @param direction Endpoint data direction.
- * @param transfer_type Transfer type of the endpoint.
- * @return Endpoint info structure.
- */
-static usb_hc_endpoint_info_t *create_endpoint_info(usb_endpoint_t endpoint,
-    usb_direction_t direction, usb_transfer_type_t transfer_type)
-{
-	usb_hc_endpoint_info_t *ep = malloc(sizeof(usb_hc_endpoint_info_t));
-	ep->data_toggle = 0;
-	ep->direction = direction;
-	ep->transfer_type = transfer_type;
-	ep->endpoint = endpoint;
-
-	return ep;
-}
-
-
-
-/** Callback for OUT transfers.
- * This callback is called by implementation of HC operations.
- *
- * @param hc Host controller that processed the transfer.
- * @param outcome Transfer outcome.
- * @param arg Custom argument.
- */
-static void remote_out_callback(usb_hc_device_t *hc,
-    usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-	transfer->out_callback(hc->generic, outcome, transfer->arg);
-
-	transfer_info_destroy(transfer);
-}
-
-/** Start an OUT transfer.
- *
- * @param dev Device that shall process the transfer.
- * @param target Target device for the data.
- * @param transfer_type Transfer type.
- * @param data Data buffer.
- * @param size Size of data buffer.
- * @param callback Callback after transfer is complete.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-static int remote_out_transfer(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
-
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_out == NULL)) {
-		return ENOTSUP;
-	}
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type),
-	    arg);
-	transfer->out_callback = callback;
-
-	int rc = hc->transfer_ops->transfer_out(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    remote_out_callback, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Start a SETUP transfer.
- *
- * @param dev Device that shall process the transfer.
- * @param target Target device for the data.
- * @param transfer_type Transfer type.
- * @param data Data buffer.
- * @param size Size of data buffer.
- * @param callback Callback after transfer is complete.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-static int remote_setup_transfer(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
-
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_setup == NULL)) {
-		return ENOTSUP;
-	}
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type),
-	    arg);
-	transfer->out_callback = callback;
-
-	int rc = hc->transfer_ops->transfer_setup(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    remote_out_callback, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Callback for IN transfers.
- * This callback is called by implementation of HC operations.
- *
- * @param hc Host controller that processed the transfer.
- * @param outcome Transfer outcome.
- * @param actual_size Size of actually received data.
- * @param arg Custom argument.
- */
-static void remote_in_callback(usb_hc_device_t *hc,
-    size_t actual_size, usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-	transfer->in_callback(hc->generic, outcome, actual_size, transfer->arg);
-
-	transfer_info_destroy(transfer);
-}
-
-/** Start an IN transfer.
- *
- * @param dev Device that shall process the transfer.
- * @param target Target device for the data.
- * @param transfer_type Transfer type.
- * @param data Data buffer.
- * @param size Size of data buffer.
- * @param callback Callback after transfer is complete.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-static int remote_in_transfer(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
-
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_in == NULL)) {
-		return ENOTSUP;
-	}
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type),
-	    arg);
-	transfer->in_callback = callback;
-
-	int rc = hc->transfer_ops->transfer_in(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    remote_in_callback, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Start outgoing interrupt transfer (USBHC remote interface).
- *
- * @param dev Host controller device processing the transfer.
- * @param target Target USB device.
- * @param buffer Data buffer.
- * @param size Data buffer size.
- * @param callback Callback after the transfer is completed.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-int remote_interrupt_out(device_t *dev, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_out_transfer(dev, target, USB_TRANSFER_INTERRUPT,
-	    buffer, size, callback, arg);
-}
-
-/** Start incoming interrupt transfer (USBHC remote interface).
- *
- * @param dev Host controller device processing the transfer.
- * @param target Target USB device.
- * @param buffer Data buffer.
- * @param size Data buffer size.
- * @param callback Callback after the transfer is completed.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-int remote_interrupt_in(device_t *dev, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return remote_in_transfer(dev, target, USB_TRANSFER_INTERRUPT,
-	    buffer, size, callback, arg);
-}
-
-
-int remote_control_write_setup(device_t *device, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_setup_transfer(device, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_write_data(device_t *device, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_out_transfer(device, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_write_status(device_t *device, usb_target_t target,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return remote_in_transfer(device, target, USB_TRANSFER_CONTROL,
-	    NULL, 0, callback, arg);
-}
-
-int remote_control_read_setup(device_t *device, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_setup_transfer(device, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_read_data(device_t *dev, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return remote_in_transfer(dev, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_read_status(device_t *device, usb_target_t target,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_out_transfer(device, target, USB_TRANSFER_CONTROL,
-	    NULL, 0, callback, arg);
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/request.c
===================================================================
--- uspace/lib/usb/src/request.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/request.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,600 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Standard USB requests (implementation).
+ */
+#include <usb/request.h>
+#include <errno.h>
+#include <assert.h>
+#include <usb/debug.h>
+
+#define MAX_DATA_LENGTH ((size_t)(0xFFFF))
+
+/** Generic wrapper for SET requests using standard control request format.
+ *
+ * @see usb_endpoint_pipe_control_write
+ *
+ * @param pipe Pipe used for the communication.
+ * @param request_type Request type (standard/class/vendor).
+ * @param recipient Request recipient (e.g. device or endpoint).
+ * @param request Actual request (e.g. GET_DESCRIPTOR).
+ * @param value Value of @c wValue field of setup packet
+ * 	(must be in USB endianness).
+ * @param index Value of @c wIndex field of setup packet
+ * 	(must be in USB endianness).
+ * @param data Data to be sent during DATA stage
+ * 	(expected to be in USB endianness).
+ * @param data_size Size of the @p data buffer (in native endianness).
+ * @return Error code.
+ * @retval EBADMEM @p pipe is NULL.
+ * @retval EBADMEM @p data is NULL and @p data_size is not zero.
+ * @retval ERANGE Data buffer too large.
+ */
+int usb_control_request_set(usb_endpoint_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t request,
+    uint16_t value, uint16_t index,
+    void *data, size_t data_size)
+{
+	if (pipe == NULL) {
+		return EBADMEM;
+	}
+
+	if (data_size > MAX_DATA_LENGTH) {
+		return ERANGE;
+	}
+
+	if ((data_size > 0) && (data == NULL)) {
+		return EBADMEM;
+	}
+
+	/*
+	 * TODO: check that @p request_type and @p recipient are
+	 * within ranges.
+	 */
+
+	usb_device_request_setup_packet_t setup_packet;
+	setup_packet.request_type = (request_type << 5) | recipient;
+	setup_packet.request = request;
+	setup_packet.value = value;
+	setup_packet.index = index;
+	setup_packet.length = (uint16_t) data_size;
+
+	int rc = usb_endpoint_pipe_control_write(pipe,
+	    &setup_packet, sizeof(setup_packet),
+	    data, data_size);
+
+	return rc;
+}
+
+ /** Generic wrapper for GET requests using standard control request format.
+  *
+  * @see usb_endpoint_pipe_control_read
+  *
+  * @param pipe Pipe used for the communication.
+  * @param request_type Request type (standard/class/vendor).
+  * @param recipient Request recipient (e.g. device or endpoint).
+  * @param request Actual request (e.g. GET_DESCRIPTOR).
+  * @param value Value of @c wValue field of setup packet
+  * 	(must be in USB endianness).
+  * @param index Value of @c wIndex field of setup packet
+  *	(must be in USB endianness).
+  * @param data Buffer where to store data accepted during the DATA stage.
+  *	(they will come in USB endianess).
+  * @param data_size Size of the @p data buffer
+  * 	(in native endianness).
+  * @param actual_data_size Actual size of transfered data
+  * 	(in native endianness).
+  * @return Error code.
+  * @retval EBADMEM @p pipe is NULL.
+  * @retval EBADMEM @p data is NULL and @p data_size is not zero.
+  * @retval ERANGE Data buffer too large.
+  */
+int usb_control_request_get(usb_endpoint_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t request,
+    uint16_t value, uint16_t index,
+    void *data, size_t data_size, size_t *actual_data_size)
+{
+	if (pipe == NULL) {
+		return EBADMEM;
+	}
+
+	if (data_size > MAX_DATA_LENGTH) {
+		return ERANGE;
+	}
+
+	if ((data_size > 0) && (data == NULL)) {
+		return EBADMEM;
+	}
+
+	/*
+	 * TODO: check that @p request_type and @p recipient are
+	 * within ranges.
+	 */
+
+	usb_device_request_setup_packet_t setup_packet;
+	setup_packet.request_type = 128 | (request_type << 5) | recipient;
+	setup_packet.request = request;
+	setup_packet.value = value;
+	setup_packet.index = index;
+	setup_packet.length = (uint16_t) data_size;
+
+	int rc = usb_endpoint_pipe_control_read(pipe,
+	    &setup_packet, sizeof(setup_packet),
+	    data, data_size, actual_data_size);
+
+	return rc;
+}
+
+/** Change address of connected device.
+ * This function automatically updates the backing connection to point to
+ * the new address.
+ *
+ * @see usb_drv_reserve_default_address
+ * @see usb_drv_release_default_address
+ * @see usb_drv_request_address
+ * @see usb_drv_release_address
+ * @see usb_drv_bind_address
+ *
+ * @param pipe Control endpoint pipe (session must be already started).
+ * @param new_address New USB address to be set (in native endianness).
+ * @return Error code.
+ */
+int usb_request_set_address(usb_endpoint_pipe_t *pipe,
+    usb_address_t new_address)
+{
+	if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
+		return EINVAL;
+	}
+
+	uint16_t addr = uint16_host2usb((uint16_t)new_address);
+
+	int rc = usb_control_request_set(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_SET_ADDRESS,
+	    addr, 0,
+	    NULL, 0);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	assert(pipe->wire != NULL);
+	/* TODO: prevent other from accessing wire now. */
+	pipe->wire->address = new_address;
+
+	return EOK;
+}
+
+/** Retrieve USB descriptor of a USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
+ * @param[in] descriptor_index Descriptor index.
+ * @param[in] language Language index.
+ * @param[out] buffer Buffer where to store the retrieved descriptor.
+ * @param[in] size Size of the @p buffer.
+ * @param[out] actual_size Number of bytes actually transferred.
+ * @return Error code.
+ */
+int usb_request_get_descriptor(usb_endpoint_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t descriptor_type, uint8_t descriptor_index,
+    uint16_t language,
+    void *buffer, size_t size, size_t *actual_size)
+{
+	if (buffer == NULL) {
+		return EBADMEM;
+	}
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	uint16_t wValue = descriptor_index | (descriptor_type << 8);
+
+	return usb_control_request_get(pipe,
+	    request_type, recipient,
+	    USB_DEVREQ_GET_DESCRIPTOR,
+	    wValue, language,
+	    buffer, size, actual_size);
+}
+
+/** Retrieve USB descriptor, allocate space for it.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
+ * @param[in] descriptor_index Descriptor index.
+ * @param[in] language Language index.
+ * @param[out] buffer_ptr Where to store pointer to allocated buffer.
+ * @param[out] buffer_size Where to store the size of the descriptor.
+ * @return
+ */
+int usb_request_get_descriptor_alloc(usb_endpoint_pipe_t * pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t descriptor_type, uint8_t descriptor_index,
+    uint16_t language,
+    void **buffer_ptr, size_t *buffer_size)
+{
+	if (buffer_ptr == NULL) {
+		return EBADMEM;
+	}
+
+	int rc;
+
+	/*
+	 * Get only first byte to retrieve descriptor length.
+	 */
+	uint8_t tmp_buffer[1];
+	size_t bytes_transfered;
+	rc = usb_request_get_descriptor(pipe, request_type, recipient,
+	    descriptor_type, descriptor_index, language,
+	    &tmp_buffer, 1, &bytes_transfered);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (bytes_transfered != 1) {
+		/* FIXME: some better error code? */
+		return ESTALL;
+	}
+
+	size_t size = tmp_buffer[0];
+	if (size == 0) {
+		/* FIXME: some better error code? */
+		return ESTALL;
+	}
+
+	/*
+	 * Allocate buffer and get the descriptor again.
+	 */
+	void *buffer = malloc(size);
+	if (buffer == NULL) {
+		return ENOMEM;
+	}
+
+	rc = usb_request_get_descriptor(pipe, request_type, recipient,
+	    descriptor_type, descriptor_index, language,
+	    buffer, size, &bytes_transfered);
+	if (rc != EOK) {
+		free(buffer);
+		return rc;
+	}
+	if (bytes_transfered != size) {
+		free(buffer);
+		/* FIXME: some better error code? */
+		return ESTALL;
+	}
+
+	*buffer_ptr = buffer;
+	if (buffer_size != NULL) {
+		*buffer_size = size;
+	}
+
+	return EOK;
+}
+
+/** Retrieve standard device descriptor of a USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[out] descriptor Storage for the device descriptor.
+ * @return Error code.
+ */
+int usb_request_get_device_descriptor(usb_endpoint_pipe_t *pipe,
+    usb_standard_device_descriptor_t *descriptor)
+{
+	if (descriptor == NULL) {
+		return EBADMEM;
+	}
+
+	size_t actually_transferred = 0;
+	usb_standard_device_descriptor_t descriptor_tmp;
+	int rc = usb_request_get_descriptor(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE, 
+	    USB_DESCTYPE_DEVICE, 0, 0,
+	    &descriptor_tmp, sizeof(descriptor_tmp),
+	    &actually_transferred);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Verify that all data has been transferred. */
+	if (actually_transferred < sizeof(descriptor_tmp)) {
+		return ELIMIT;
+	}
+
+	/* Everything is okay, copy the descriptor. */
+	memcpy(descriptor, &descriptor_tmp,
+	    sizeof(descriptor_tmp));
+
+	return EOK;
+}
+
+/** Retrieve configuration descriptor of a USB device.
+ *
+ * The function does not retrieve additional data binded with configuration
+ * descriptor (such as its interface and endpoint descriptors) - use
+ * usb_request_get_full_configuration_descriptor() instead.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index Descriptor index.
+ * @param[out] descriptor Storage for the device descriptor.
+ * @return Error code.
+ */
+int usb_request_get_bare_configuration_descriptor(usb_endpoint_pipe_t *pipe,
+    int index, usb_standard_configuration_descriptor_t *descriptor)
+{
+	if (descriptor == NULL) {
+		return EBADMEM;
+	}
+
+	if ((index < 0) || (index > 0xFF)) {
+		return ERANGE;
+	}
+
+	size_t actually_transferred = 0;
+	usb_standard_configuration_descriptor_t descriptor_tmp;
+	int rc = usb_request_get_descriptor(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_CONFIGURATION, index, 0,
+	    &descriptor_tmp, sizeof(descriptor_tmp),
+	    &actually_transferred);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Verify that all data has been transferred. */
+	if (actually_transferred < sizeof(descriptor_tmp)) {
+		return ELIMIT;
+	}
+
+	/* Everything is okay, copy the descriptor. */
+	memcpy(descriptor, &descriptor_tmp,
+	    sizeof(descriptor_tmp));
+
+	return EOK;
+}
+
+/** Retrieve full configuration descriptor of a USB device.
+ *
+ * @warning The @p buffer might be touched (i.e. its contents changed)
+ * even when error occurs.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index Descriptor index.
+ * @param[out] descriptor Storage for the device descriptor.
+ * @param[in] descriptor_size Size of @p descriptor buffer.
+ * @param[out] actual_size Number of bytes actually transferred.
+ * @return Error code.
+ */
+int usb_request_get_full_configuration_descriptor(usb_endpoint_pipe_t *pipe,
+    int index, void *descriptor, size_t descriptor_size, size_t *actual_size)
+{
+	if ((index < 0) || (index > 0xFF)) {
+		return ERANGE;
+	}
+
+	return usb_request_get_descriptor(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_CONFIGURATION, index, 0,
+	    descriptor, descriptor_size, actual_size);
+}
+
+/** Set configuration of USB device.
+ *
+ * @param pipe Control endpoint pipe (session must be already started).
+ * @param configuration_value New configuration value.
+ * @return Error code.
+ */
+int usb_request_set_configuration(usb_endpoint_pipe_t *pipe,
+    uint8_t configuration_value)
+{
+	uint16_t config_value
+	    = uint16_host2usb((uint16_t) configuration_value);
+
+	return usb_control_request_set(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_SET_CONFIGURATION, config_value, 0,
+	    NULL, 0);
+}
+
+/** Get list of supported languages by USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[out] languages_ptr Where to store pointer to allocated array of
+ *	supported languages.
+ * @param[out] languages_count Number of supported languages.
+ * @return Error code.
+ */
+int usb_request_get_supported_languages(usb_endpoint_pipe_t *pipe,
+    l18_win_locales_t **languages_ptr, size_t *languages_count)
+{
+	int rc;
+
+	if (languages_ptr == NULL) {
+		return EBADMEM;
+	}
+	if (languages_count == NULL) {
+		return EBADMEM;
+	}
+
+	uint8_t *string_descriptor = NULL;
+	size_t string_descriptor_size = 0;
+	rc = usb_request_get_descriptor_alloc(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_STRING, 0, 0,
+	    (void **) &string_descriptor, &string_descriptor_size);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (string_descriptor_size <= 2) {
+		free(string_descriptor);
+		return EEMPTY;
+	}
+	/* Substract first 2 bytes (length and descriptor type). */
+	string_descriptor_size -= 2;
+
+	/* Odd number of bytes - descriptor is broken? */
+	if ((string_descriptor_size % 2) != 0) {
+		/* FIXME: shall we return with error or silently ignore? */
+		free(string_descriptor);
+		return ESTALL;
+	}
+
+	size_t langs_count = string_descriptor_size / 2;
+	l18_win_locales_t *langs
+	    = malloc(sizeof(l18_win_locales_t) * langs_count);
+	if (langs == NULL) {
+		free(string_descriptor);
+		return ENOMEM;
+	}
+
+	size_t i;
+	for (i = 0; i < langs_count; i++) {
+		/* Language code from the descriptor is in USB endianess. */
+		/* FIXME: is this really correct? */
+		uint16_t lang_code = (string_descriptor[2 + 2 * i + 1] << 8)
+		    + string_descriptor[2 + 2 * i];
+		langs[i] = uint16_usb2host(lang_code);
+	}
+
+	free(string_descriptor);
+
+	*languages_ptr = langs;
+	*languages_count =langs_count;
+
+	return EOK;
+}
+
+/** Get string (descriptor) from USB device.
+ *
+ * The string is returned in native encoding of the operating system.
+ * For HelenOS, that is UTF-8.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index String index (in native endianess).
+ * @param[in] lang String language (in native endianess).
+ * @param[out] string_ptr Where to store allocated string in native encoding.
+ * @return Error code.
+ */
+int usb_request_get_string(usb_endpoint_pipe_t *pipe,
+    size_t index, l18_win_locales_t lang, char **string_ptr)
+{
+	if (string_ptr == NULL) {
+		return EBADMEM;
+	}
+	/* Index is actually one byte value. */
+	if (index > 0xFF) {
+		return ERANGE;
+	}
+	/* Language is actually two byte value. */
+	if (lang > 0xFFFF) {
+		return ERANGE;
+	}
+
+	int rc;
+
+	/* Prepare dynamically allocated variables. */
+	uint8_t *string = NULL;
+	wchar_t *string_chars = NULL;
+
+	/* Get the actual descriptor. */
+	size_t string_size;
+	rc = usb_request_get_descriptor_alloc(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_STRING, index, uint16_host2usb(lang),
+	    (void **) &string, &string_size);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	if (string_size <= 2) {
+		rc =  EEMPTY;
+		goto leave;
+	}
+	/* Substract first 2 bytes (length and descriptor type). */
+	string_size -= 2;
+
+	/* Odd number of bytes - descriptor is broken? */
+	if ((string_size % 2) != 0) {
+		/* FIXME: shall we return with error or silently ignore? */
+		rc = ESTALL;
+		goto leave;
+	}
+
+	size_t string_char_count = string_size / 2;
+	string_chars = malloc(sizeof(wchar_t) * (string_char_count + 1));
+	if (string_chars == NULL) {
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	/*
+	 * Build a wide string.
+	 * And do not forget to set NULL terminator (string descriptors
+	 * do not have them).
+	 */
+	size_t i;
+	for (i = 0; i < string_char_count; i++) {
+		uint16_t uni_char = (string[2 + 2 * i + 1] << 8)
+		    + string[2 + 2 * i];
+		string_chars[i] = uni_char;
+	}
+	string_chars[string_char_count] = 0;
+
+
+	/* Convert to normal string. */
+	char *str = wstr_to_astr(string_chars);
+	if (str == NULL) {
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	*string_ptr = str;
+	rc = EOK;
+
+leave:
+	if (string != NULL) {
+		free(string);
+	}
+	if (string_chars != NULL) {
+		free(string_chars);
+	}
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/usb.c
===================================================================
--- uspace/lib/usb/src/usb.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/usb.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -54,20 +54,4 @@
 }
 
-/** String representation of USB transaction outcome. */
-const char * usb_str_transaction_outcome(usb_transaction_outcome_t o)
-{
-	switch (o) {
-		case USB_OUTCOME_OK:
-			return "ok";
-		case USB_OUTCOME_CRCERROR:
-			return "CRC error";
-		case USB_OUTCOME_BABBLE:
-			return "babble";
-		default:
-			return "unknown";
-	}
-}
-
-
 /**
  * @}
Index: uspace/lib/usb/src/usbdevice.c
===================================================================
--- uspace/lib/usb/src/usbdevice.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/usbdevice.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * General communication between device drivers and host controller driver.
+ */
+#include <devman.h>
+#include <async.h>
+#include <usb_iface.h>
+#include <usb/usbdevice.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <assert.h>
+
+/** Find host controller handle that is ancestor of given device.
+ *
+ * @param[in] device_handle Device devman handle.
+ * @param[out] hc_handle Where to store handle of host controller
+ *	controlling device with @p device_handle handle.
+ * @return Error code.
+ */
+int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)
+{
+	int parent_phone = devman_parent_device_connect(device_handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	devman_handle_t h;
+	usb_log_debug("asking for HC handle (my handle is %zu).\n", device_handle);
+	int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
+
+	async_hangup(parent_phone);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (hc_handle != NULL) {
+		*hc_handle = h;
+	}
+
+	return EOK;
+}
+
+/** Initialize connection to USB host controller.
+ *
+ * @param connection Connection to be initialized.
+ * @param device Device connecting to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_initialize_from_device(usb_hc_connection_t *connection,
+    ddf_dev_t *device)
+{
+	assert(connection);
+
+	if (device == NULL) {
+		return EBADMEM;
+	}
+
+	devman_handle_t hc_handle;
+	int rc = usb_hc_find(device->handle, &hc_handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_hc_connection_initialize(connection, hc_handle);
+
+	return rc;
+}
+
+/** Manually initialize connection to USB host controller.
+ *
+ * @param connection Connection to be initialized.
+ * @param hc_handle Devman handle of the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_initialize(usb_hc_connection_t *connection,
+    devman_handle_t hc_handle)
+{
+	assert(connection);
+
+	connection->hc_handle = hc_handle;
+	connection->hc_phone = -1;
+
+	return EOK;
+}
+
+/** Open connection to host controller.
+ *
+ * @param connection Connection to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_open(usb_hc_connection_t *connection)
+{
+	assert(connection);
+
+	if (usb_hc_connection_is_opened(connection)) {
+		return EBUSY;
+	}
+
+	int phone = devman_device_connect(connection->hc_handle, 0);
+	if (phone < 0) {
+		return phone;
+	}
+
+	connection->hc_phone = phone;
+
+	return EOK;
+}
+
+/** Tells whether connection to host controller is opened.
+ *
+ * @param connection Connection to the host controller.
+ * @return Whether connection is opened.
+ */
+bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection)
+{
+	assert(connection);
+
+	return (connection->hc_phone >= 0);
+}
+
+/** Close connection to the host controller.
+ *
+ * @param connection Connection to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_close(usb_hc_connection_t *connection)
+{
+	assert(connection);
+
+	if (!usb_hc_connection_is_opened(connection)) {
+		return ENOENT;
+	}
+
+	int rc = async_hangup(connection->hc_phone);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	connection->hc_phone = -1;
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: pace/lib/usb/src/usbdrv.c
===================================================================
--- uspace/lib/usb/src/usbdrv.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,534 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief USB driver (implementation).
- */
-#include <usb/usbdrv.h>
-#include <usbhc_iface.h>
-#include <usb_iface.h>
-#include <errno.h>
-#include <str_error.h>
-
-/** Information about pending transaction on HC. */
-typedef struct {
-	/** Phone to host controller driver. */
-	int phone;
-	/** Data buffer. */
-	void *buffer;
-	/** Buffer size. */
-	size_t size;
-	/** Storage for actual number of bytes transferred. */
-	size_t *size_transferred;
-	/** Initial call replay data. */
-	ipc_call_t reply;
-	/** Initial call identifier. */
-	aid_t request;
-} transfer_info_t;
-
-/** Find handle of host controller the device is physically attached to.
- *
- * @param[in] dev Device looking for its host controller.
- * @param[out] handle Host controller devman handle.
- * @return Error code.
- */
-int usb_drv_find_hc(device_t *dev, devman_handle_t *handle)
-{
-	if (dev == NULL) {
-		return EBADMEM;
-	}
-	if (handle == NULL) {
-		return EBADMEM;
-	}
-
-	int parent_phone = devman_parent_device_connect(dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (parent_phone < 0) {
-		return parent_phone;
-	}
-
-	devman_handle_t h;
-	int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
-	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
-
-	ipc_hangup(parent_phone);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	*handle = h;
-
-	return EOK;
-}
-
-/** Connect to host controller the device is physically attached to.
- *
- * @param dev Device asking for connection.
- * @param hc_handle Devman handle of the host controller.
- * @param flags Connection flags (blocking connection).
- * @return Phone to the HC or error code.
- */
-int usb_drv_hc_connect(device_t *dev, devman_handle_t hc_handle,
-    unsigned int flags)
-{
-	return devman_device_connect(hc_handle, flags);
-}
-
-/** Connect to host controller the device is physically attached to.
- *
- * @param dev Device asking for connection.
- * @param flags Connection flags (blocking connection).
- * @return Phone to corresponding HC or error code.
- */
-int usb_drv_hc_connect_auto(device_t *dev, unsigned int flags)
-{
-	int rc;
-	devman_handle_t hc_handle;
-
-	/*
-	 * Call parent hub to obtain device handle of respective HC.
-	 */
-	rc = usb_drv_find_hc(dev, &hc_handle);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	return usb_drv_hc_connect(dev, hc_handle, flags);
-}
-
-/** Tell USB address assigned to given device.
- *
- * @param phone Phone to my HC.
- * @param dev Device in question.
- * @return USB address or error code.
- */
-usb_address_t usb_drv_get_my_address(int phone, device_t *dev)
-{
-	sysarg_t address;
-	int rc = async_req_2_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_GET_ADDRESS,
-	    dev->handle, &address);
-
-	if (rc != EOK) {
-		printf("usb_drv_get_my_address over %d failed: %s\n", phone, str_error(rc));
-		return rc;
-	}
-
-	return (usb_address_t) address;
-}
-
-/** Tell HC to reserve default address.
- *
- * @param phone Open phone to host controller driver.
- * @return Error code.
- */
-int usb_drv_reserve_default_address(int phone)
-{
-	return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS);
-}
-
-/** Tell HC to release default address.
- *
- * @param phone Open phone to host controller driver.
- * @return Error code.
- */
-int usb_drv_release_default_address(int phone)
-{
-	return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
-}
-
-/** Ask HC for free address assignment.
- *
- * @param phone Open phone to host controller driver.
- * @return Assigned USB address or negative error code.
- */
-usb_address_t usb_drv_request_address(int phone)
-{
-	sysarg_t address;
-	int rc = async_req_1_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_REQUEST_ADDRESS, &address);
-	if (rc != EOK) {
-		return rc;
-	} else {
-		return (usb_address_t) address;
-	}
-}
-
-/** Inform HC about binding address with devman handle.
- *
- * @param phone Open phone to host controller driver.
- * @param address Address to be binded.
- * @param handle Devman handle of the device.
- * @return Error code.
- */
-int usb_drv_bind_address(int phone, usb_address_t address,
-    devman_handle_t handle)
-{
-	int rc = async_req_3_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_BIND_ADDRESS,
-	    address, handle);
-
-	return rc;
-}
-
-/** Inform HC about address release.
- *
- * @param phone Open phone to host controller driver.
- * @param address Address to be released.
- * @return Error code.
- */
-int usb_drv_release_address(int phone, usb_address_t address)
-{
-	return async_req_2_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RELEASE_ADDRESS, address);
-}
-
-/** Send data to HCD.
- *
- * @param phone Phone to HC.
- * @param method Method used for calling.
- * @param target Targeted device.
- * @param buffer Data buffer (NULL to skip data transfer phase).
- * @param size Buffer size (must be zero when @p buffer is NULL).
- * @param handle Storage for transaction handle (cannot be NULL).
- * @return Error status.
- * @retval EINVAL Invalid parameter.
- * @retval ENOMEM Not enough memory to complete the operation.
- */
-static int async_send_buffer(int phone, int method,
-    usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	if (phone < 0) {
-		return EINVAL;
-	}
-
-	if ((buffer == NULL) && (size > 0)) {
-		return EINVAL;
-	}
-
-	if (handle == NULL) {
-		return EINVAL;
-	}
-
-	transfer_info_t *transfer
-	    = (transfer_info_t *) malloc(sizeof(transfer_info_t));
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->size_transferred = NULL;
-	transfer->buffer = NULL;
-	transfer->size = 0;
-	transfer->phone = phone;
-
-	int rc;
-
-	transfer->request = async_send_4(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    method,
-	    target.address, target.endpoint,
-	    size,
-	    &transfer->reply);
-
-	if (size > 0) {
-		rc = async_data_write_start(phone, buffer, size);
-		if (rc != EOK) {
-			async_wait_for(transfer->request, NULL);
-			return rc;
-		}
-	}
-
-	*handle = (usb_handle_t) transfer;
-
-	return EOK;
-}
-
-/** Prepare data retrieval.
- *
- * @param phone Opened phone to HCD.
- * @param method Method used for calling.
- * @param target Targeted device.
- * @param buffer Buffer where to store retrieved data
- * 	(NULL to skip data transfer phase).
- * @param size Buffer size (must be zero when @p buffer is NULL).
- * @param actual_size Storage where actual number of bytes transferred will
- * 	be stored.
- * @param handle Storage for transaction handle (cannot be NULL).
- * @return Error status.
- * @retval EINVAL Invalid parameter.
- * @retval ENOMEM Not enough memory to complete the operation.
- */
-static int async_recv_buffer(int phone, int method,
-    usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	if (phone < 0) {
-		return EINVAL;
-	}
-
-	if ((buffer == NULL) && (size > 0)) {
-		return EINVAL;
-	}
-
-	if (handle == NULL) {
-		return EINVAL;
-	}
-
-	transfer_info_t *transfer
-	    = (transfer_info_t *) malloc(sizeof(transfer_info_t));
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->size_transferred = actual_size;
-	transfer->buffer = buffer;
-	transfer->size = size;
-	transfer->phone = phone;
-
-	transfer->request = async_send_4(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    method,
-	    target.address, target.endpoint,
-	    size,
-	    &transfer->reply);
-
-	*handle = (usb_handle_t) transfer;
-
-	return EOK;
-}
-
-/** Read buffer from HCD.
- *
- * @param phone Opened phone to HCD.
- * @param hash Buffer hash (obtained after completing IN transaction).
- * @param buffer Buffer where to store data data.
- * @param size Buffer size.
- * @param actual_size Storage where actual number of bytes transferred will
- * 	be stored.
- * @return Error status.
- */
-static int read_buffer_in(int phone, sysarg_t hash,
-    void *buffer, size_t size, size_t *actual_size)
-{
-	ipc_call_t answer_data;
-	sysarg_t answer_rc;
-	aid_t req;
-	int rc;
-
-	req = async_send_2(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_GET_BUFFER,
-	    hash,
-	    &answer_data);
-
-	rc = async_data_read_start(phone, buffer, size);
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return EINVAL;
-	}
-
-	async_wait_for(req, &answer_rc);
-	rc = (int)answer_rc;
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	*actual_size = IPC_GET_ARG1(answer_data);
-
-	return EOK;
-}
-
-/** Blocks caller until given USB transaction is finished.
- * After the transaction is finished, the user can access all output data
- * given to initial call function.
- *
- * @param handle Transaction handle.
- * @return Error status.
- * @retval EOK No error.
- * @retval EBADMEM Invalid handle.
- * @retval ENOENT Data buffer associated with transaction does not exist.
- */
-int usb_drv_async_wait_for(usb_handle_t handle)
-{
-	if (handle == 0) {
-		return EBADMEM;
-	}
-
-	int rc = EOK;
-
-	transfer_info_t *transfer = (transfer_info_t *) handle;
-
-	sysarg_t answer_rc;
-	async_wait_for(transfer->request, &answer_rc);
-
-	if (answer_rc != EOK) {
-		rc = (int) answer_rc;
-		goto leave;
-	}
-
-	/*
-	 * If the buffer is not NULL, we must accept some data.
-	 */
-	if ((transfer->buffer != NULL) && (transfer->size > 0)) {
-		/*
-		 * The buffer hash identifies the data on the server
-		 * side.
-		 * We will use it when actually reading-in the data.
-		 */
-		sysarg_t buffer_hash = IPC_GET_ARG1(transfer->reply);
-		if (buffer_hash == 0) {
-			rc = ENOENT;
-			goto leave;
-		}
-
-		size_t actual_size;
-		rc = read_buffer_in(transfer->phone, buffer_hash,
-		    transfer->buffer, transfer->size, &actual_size);
-
-		if (rc != EOK) {
-			goto leave;
-		}
-
-		if (transfer->size_transferred) {
-			*(transfer->size_transferred) = actual_size;
-		}
-	}
-
-leave:
-	free(transfer);
-
-	return rc;
-}
-
-/** Send interrupt data to device. */
-int usb_drv_async_interrupt_out(int phone, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_INTERRUPT_OUT,
-	    target,
-	    buffer, size,
-	    handle);
-}
-
-/** Request interrupt data from device. */
-int usb_drv_async_interrupt_in(int phone, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_recv_buffer(phone,
-	    IPC_M_USBHC_INTERRUPT_IN,
-	    target,
-	    buffer, size, actual_size,
-	    handle);
-}
-
-/** Start control write transfer. */
-int usb_drv_async_control_write_setup(int phone, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_WRITE_SETUP,
-	    target,
-	    buffer, size,
-	    handle);
-}
-
-/** Send data during control write transfer. */
-int usb_drv_async_control_write_data(int phone, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_WRITE_DATA,
-	    target,
-	    buffer, size,
-	    handle);
-}
-
-/** Finalize control write transfer. */
-int usb_drv_async_control_write_status(int phone, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_recv_buffer(phone,
-	    IPC_M_USBHC_CONTROL_WRITE_STATUS,
-	    target,
-	    NULL, 0, NULL,
-	    handle);
-}
-
-/** Start control read transfer. */
-int usb_drv_async_control_read_setup(int phone, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_SETUP,
-	    target,
-	    buffer, size,
-	    handle);
-}
-
-/** Read data during control read transfer. */
-int usb_drv_async_control_read_data(int phone, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_recv_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_DATA,
-	    target,
-	    buffer, size, actual_size,
-	    handle);
-}
-
-/** Finalize control read transfer. */
-int usb_drv_async_control_read_status(int phone, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_STATUS,
-	    target,
-	    NULL, 0,
-	    handle);
-}
-
-/**
- * @}
- */
Index: pace/lib/usb/src/usbdrvreq.c
===================================================================
--- uspace/lib/usb/src/usbdrvreq.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,523 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief USB driver - standard USB requests (implementation).
- */
-#include <usb/usbdrv.h>
-#include <errno.h>
-
-/**  Prepare USB target for control endpoint.
- *
- * @param name Variable name with the USB target.
- * @param target_address Target USB address.
- */
-#define PREPARE_TARGET(name, target_address) \
-	usb_target_t name = { \
-		.address = target_address, \
-		.endpoint = 0 \
-	}
-
-/** Prepare setup packet.
- *
- * @param name Variable name with the setup packet.
- * @param p_direction Data transfer direction.
- * @param p_type Request type (standard/class/vendor)
- * @param p_recipient Recipient of the request.
- * @param p_request Request.
- * @param p_value wValue field of setup packet.
- * @param p_index wIndex field of setup packet.
- * @param p_length Length of extra data.
- */
-#define PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
-    p_request, p_value, p_index, p_length) \
-	usb_device_request_setup_packet_t name = { \
-		.request_type = \
-			((p_direction) == USB_DIRECTION_IN ? 128 : 0) \
-			| ((p_type) << 5) \
-			| (p_recipient), \
-		.request = (p_request), \
-		{ .value = (p_value) }, \
-		.index = (p_index), \
-		.length = (p_length) \
-	}
-
-/** Prepare setup packet.
- *
- * @param name Variable name with the setup packet.
- * @param p_direction Data transfer direction.
- * @param p_type Request type (standard/class/vendor)
- * @param p_recipient Recipient of the request.
- * @param p_request Request.
- * @param p_value_low wValue field of setup packet (low byte).
- * @param p_value_high wValue field of setup packet (high byte).
- * @param p_index wIndex field of setup packet.
- * @param p_length Length of extra data.
- */
-#define PREPARE_SETUP_PACKET_LOHI(name, p_direction, p_type, p_recipient, \
-    p_request, p_value_low, p_value_high, p_index, p_length) \
-	PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
-	    p_request, (p_value_low) | ((p_value_high) << 8), \
-	    p_index, p_length)
-
-/** Retrieve status of a USB device.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] recipient Recipient of the request.
- * @param[in] recipient_index Index of @p recipient.
- * @param[out] status Status (see figure 9-4 in USB 1.1 specification).
- * @return Error code.
- */
-int usb_drv_req_get_status(int hc_phone, usb_address_t address,
-    usb_request_recipient_t recipient, uint16_t recipient_index,
-    uint16_t *status)
-{
-	if (status == NULL) {
-		return EBADMEM;
-	}
-
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET(setup_packet,
-	    USB_DIRECTION_IN, USB_REQUEST_TYPE_STANDARD,
-	    recipient, USB_DEVREQ_GET_STATUS, 0, recipient_index, 2);
-
-	size_t transfered;
-	uint16_t tmp_status;
-	int rc = usb_drv_psync_control_read(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), &tmp_status, 2, &transfered);
-	if (rc != EOK) {
-		return rc;
-	}
-	if (transfered != 2) {
-		return ERANGE;
-	}
-
-	*status = tmp_status;
-
-	return EOK;
-}
-
-/** Clear or disable USB device feature.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] recipient Recipient of the request.
- * @param[in] selector Feature selector.
- * @param[in] index Index of @p recipient.
- * @return Error code.
- */
-int usb_drv_req_clear_feature(int hc_phone, usb_address_t address,
-    usb_request_recipient_t recipient,
-    uint16_t selector, uint16_t index)
-{
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET(setup_packet,
-	    USB_DIRECTION_OUT, USB_REQUEST_TYPE_STANDARD,
-	    recipient, USB_DEVREQ_CLEAR_FEATURE, selector, index, 0);
-
-	int rc = usb_drv_psync_control_write(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), NULL, 0);
-
-	return rc;
-}
-
-/** Set or enable USB device feature.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] recipient Recipient of the request.
- * @param[in] selector Feature selector.
- * @param[in] index Index of @p recipient.
- * @return Error code.
- */
-int usb_drv_req_set_feature(int hc_phone, usb_address_t address,
-    usb_request_recipient_t recipient,
-    uint16_t selector, uint16_t index)
-{
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET(setup_packet,
-	    USB_DIRECTION_OUT, USB_REQUEST_TYPE_STANDARD,
-	    recipient, USB_DEVREQ_SET_FEATURE, selector, index, 0);
-
-	int rc = usb_drv_psync_control_write(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), NULL, 0);
-
-	return rc;
-}
-
-/** Change address of connected device.
- *
- * @see usb_drv_reserve_default_address
- * @see usb_drv_release_default_address
- * @see usb_drv_request_address
- * @see usb_drv_release_address
- * @see usb_drv_bind_address
- *
- * @param[in] phone Open phone to HC driver.
- * @param[in] old_address Current address.
- * @param[in] address Address to be set.
- * @return Error code.
- */
-int usb_drv_req_set_address(int phone, usb_address_t old_address,
-    usb_address_t new_address)
-{
-	PREPARE_TARGET(target, old_address);
-
-	PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_OUT,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_SET_ADDRESS, new_address, 0, 0);
-
-	int rc = usb_drv_psync_control_write(phone, target,
-	    &setup_packet, sizeof(setup_packet), NULL, 0);
-
-	return rc;
-}
-
-/** Retrieve USB descriptor of connected USB device.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] request_type Request type (standard/class/vendor).
- * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
- * @param[in] descriptor_index Descriptor index.
- * @param[in] language Language index.
- * @param[out] buffer Buffer where to store the retrieved descriptor.
- * @param[in] size Size of the @p buffer.
- * @param[out] actual_size Number of bytes actually transferred.
- * @return Error code.
- */
-int usb_drv_req_get_descriptor(int hc_phone, usb_address_t address,
-    usb_request_type_t request_type,
-    uint8_t descriptor_type, uint8_t descriptor_index,
-    uint16_t language,
-    void *buffer, size_t size, size_t *actual_size)
-{
-	if (buffer == NULL) {
-		return EBADMEM;
-	}
-	if (size == 0) {
-		return EINVAL;
-	}
-
-	// FIXME: check that size is not too big
-
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_IN,
-	    request_type, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_GET_DESCRIPTOR, descriptor_index, descriptor_type,
-	    language, size);
-
-	int rc = usb_drv_psync_control_read(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet),
-	    buffer, size, actual_size);
-	
-	return rc;
-}
-
-/** Retrieve device descriptor of connected USB device.
- *
- * @param[in] phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[out] descriptor Storage for the device descriptor.
- * @return Error code.
- * @retval EBADMEM @p descriptor is NULL.
- */
-int usb_drv_req_get_device_descriptor(int phone, usb_address_t address,
-    usb_standard_device_descriptor_t *descriptor)
-{
-	if (descriptor == NULL) {
-		return EBADMEM;
-	}
-	
-	size_t actually_transferred = 0;
-	usb_standard_device_descriptor_t descriptor_tmp;
-	int rc = usb_drv_req_get_descriptor(phone, address,
-	    USB_REQUEST_TYPE_STANDARD,
-	    USB_DESCTYPE_DEVICE, 0,
-	    0,
-	    &descriptor_tmp, sizeof(descriptor_tmp),
-	    &actually_transferred);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/* Verify that all data has been transferred. */
-	if (actually_transferred < sizeof(descriptor_tmp)) {
-		return ELIMIT;
-	}
-
-	/* Everything is okay, copy the descriptor. */
-	memcpy(descriptor, &descriptor_tmp,
-	    sizeof(descriptor_tmp));
-
-	return EOK;
-}
-
-
-/** Retrieve configuration descriptor of connected USB device.
- *
- * The function does not retrieve additional data binded with configuration
- * descriptor (such as its interface and endpoint descriptors) - use
- * usb_drv_req_get_full_configuration_descriptor() instead.
- *
- * @param[in] phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] index Configuration descriptor index.
- * @param[out] descriptor Storage for the configuration descriptor.
- * @return Error code.
- * @retval EBADMEM @p descriptor is NULL.
- */
-int usb_drv_req_get_bare_configuration_descriptor(int phone,
-    usb_address_t address, int index,
-    usb_standard_configuration_descriptor_t *descriptor)
-{
-	if (descriptor == NULL) {
-		return EBADMEM;
-	}
-	
-	size_t actually_transferred = 0;
-	usb_standard_configuration_descriptor_t descriptor_tmp;
-	int rc = usb_drv_req_get_descriptor(phone, address,
-	    USB_REQUEST_TYPE_STANDARD,
-	    USB_DESCTYPE_CONFIGURATION, 0,
-	    0,
-	    &descriptor_tmp, sizeof(descriptor_tmp),
-	    &actually_transferred);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/* Verify that all data has been transferred. */
-	if (actually_transferred < sizeof(descriptor_tmp)) {
-		return ELIMIT;
-	}
-
-	/* Everything is okay, copy the descriptor. */
-	memcpy(descriptor, &descriptor_tmp,
-	    sizeof(descriptor_tmp));
-
-	return EOK;
-}
-
-/** Retrieve full configuration descriptor of connected USB device.
- *
- * @warning The @p buffer might be touched (i.e. its contents changed)
- * even when error occurs.
- *
- * @param[in] phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] index Configuration descriptor index.
- * @param[out] buffer Buffer for the whole configuration descriptor.
- * @param[in] buffer_size Size of the prepared @p buffer.
- * @param[out] actual_buffer_size Bytes actually transfered.
- * @return Error code.
- * @retval EBADMEM @p descriptor is NULL.
- */
-int usb_drv_req_get_full_configuration_descriptor(int phone,
-    usb_address_t address, int index,
-    void *buffer, size_t buffer_size, size_t *actual_buffer_size)
-{
-	int rc = usb_drv_req_get_descriptor(phone, address,
-	    USB_REQUEST_TYPE_STANDARD,
-	    USB_DESCTYPE_CONFIGURATION, 0,
-	    0,
-	    buffer, buffer_size,
-	    actual_buffer_size);
-
-	return rc;
-}
-
-/** Update existing descriptor of a USB device.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] descriptor_type Descriptor type (device/configuration/...).
- * @param[in] descriptor_index Descriptor index.
- * @param[in] language Language index.
- * @param[in] descriptor Actual descriptor data.
- * @param[in] descriptor_size Descriptor size.
- * @return Error code.
- */
-int usb_drv_req_set_descriptor(int hc_phone, usb_address_t address,
-    uint8_t descriptor_type, uint8_t descriptor_index,
-    uint16_t language,
-    void *descriptor, size_t descriptor_size)
-{
-	// FIXME: check that descriptor is not too big
-
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_SET_DESCRIPTOR, descriptor_index, descriptor_type,
-	    language, descriptor_size);
-
-	int rc = usb_drv_psync_control_write(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet),
-	    descriptor, descriptor_size);
-
-	return rc;
-}
-
-/** Determine current configuration value of USB device.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[out] configuration_value Current configuration value.
- * @return Error code.
- */
-int usb_drv_req_get_configuration(int hc_phone, usb_address_t address,
-    uint8_t *configuration_value)
-{
-	if (configuration_value == NULL) {
-		return EBADMEM;
-	}
-
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_IN,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_GET_CONFIGURATION, 0, 0, 1);
-
-	uint8_t value;
-	size_t transfered;
-	int rc = usb_drv_psync_control_read(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), &value, 1, &transfered);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if (transfered != 1) {
-		return ERANGE;
-	}
-
-	*configuration_value = value;
-
-	return EOK;
-}
-
-/** Set configuration of USB device.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] configuration_value New configuration value.
- * @return Error code.
- */
-int usb_drv_req_set_configuration(int hc_phone, usb_address_t address,
-    uint8_t configuration_value)
-{
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_SET_CONFIGURATION, configuration_value, 0,
-	    0, 0);
-
-	int rc = usb_drv_psync_control_write(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), NULL, 0);
-
-	return rc;
-}
-
-/** Determine alternate setting of USB device interface.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] interface_index Interface index.
- * @param[out] alternate_setting Value of alternate setting.
- * @return Error code.
- */
-int usb_drv_req_get_interface(int hc_phone, usb_address_t address,
-    uint16_t interface_index, uint8_t *alternate_setting)
-{
-	if (alternate_setting == NULL) {
-		return EBADMEM;
-	}
-
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_IN,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
-	    USB_DEVREQ_GET_INTERFACE, 0, interface_index, 1);
-
-	uint8_t alternate;
-	size_t transfered;
-	int rc = usb_drv_psync_control_read(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), &alternate, 1, &transfered);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if (transfered != 1) {
-		return ERANGE;
-	}
-
-	*alternate_setting = alternate;
-
-	return EOK;
-}
-
-/** Select an alternate setting of USB device interface.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] interface_index Interface index.
- * @param[in] alternate_setting Value of alternate setting.
- * @return Error code.
- */
-int usb_drv_req_set_interface(int hc_phone, usb_address_t address,
-    uint16_t interface_index, uint8_t alternate_setting)
-{
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
-	    USB_DEVREQ_SET_INTERFACE, alternate_setting, 0,
-	    0, 0);
-
-	int rc = usb_drv_psync_control_write(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), NULL, 0);
-
-	return rc;
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/usbmem.c
===================================================================
--- uspace/lib/usb/src/usbmem.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/usbmem.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2011 Matus Dekanek
+ * 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 libc
+ * @{
+ */
+/** @file implementation of special memory management, used mostly in usb stack
+ */
+
+#include <adt/hash_table.h>
+#include <adt/list.h>
+#include <as.h>
+#include <errno.h>
+#include <malloc.h>
+
+#include "usb/usbmem.h"
+
+#define ADDR_BUCKETS 1537
+
+//address translation tables
+static hash_table_t * pa2va_table = NULL;
+static hash_table_t * va2pa_table = NULL;
+
+/**
+ * address translation hashtable item
+ */
+typedef struct{
+	unsigned long addr;
+	unsigned long translation;
+	link_t link;
+
+}addr_node_t;
+
+static hash_index_t addr_hash(unsigned long key[])
+{
+	return (3*key[0]<<4) % ADDR_BUCKETS;
+}
+
+static int addr_compare(unsigned long key[], hash_count_t keys,
+    link_t *item)
+{
+	addr_node_t *addr_node = hash_table_get_instance(item, addr_node_t, link);
+	return (addr_node->addr == key[0]);
+}
+
+static void addr_remove_callback(link_t * item)
+{
+	//delete item
+	addr_node_t *addr_node = hash_table_get_instance(item, addr_node_t, link);
+	free(addr_node);
+}
+
+
+static hash_table_operations_t addr_devices_ops = {
+	.hash = addr_hash,
+	.compare = addr_compare,
+	.remove_callback = addr_remove_callback
+};
+
+/**
+ * create node for address translation hashtable
+ * @param addr
+ * @param translation
+ * @return
+ */
+static addr_node_t * create_addr_node(void * addr, void * translation){
+	addr_node_t * node = (addr_node_t*)malloc(sizeof(addr_node_t));
+	node->addr = (unsigned long)addr;
+	node->translation = (unsigned long)translation;
+	return node;
+}
+
+/**
+ * allocate size on heap and register it`s pa<->va translation
+ *
+ * If physical address + size is 2GB or higher, nothing is allocated and NULL
+ * is returned.
+ * @param size
+ * @param alignment
+ * @return
+ */
+void * mman_malloc(
+	size_t size,
+	size_t alignment,
+	unsigned long max_physical_address)
+{
+	if (size == 0)
+		return NULL;
+	if (alignment == 0)
+		return NULL;
+	//check if tables were initialized
+	if(!pa2va_table){
+		pa2va_table = (hash_table_t*)malloc(sizeof(hash_table_t*));
+		va2pa_table = (hash_table_t*)malloc(sizeof(hash_table_t*));
+		hash_table_create(pa2va_table, ADDR_BUCKETS, 1,
+		    &addr_devices_ops);
+		hash_table_create(va2pa_table, ADDR_BUCKETS, 1,
+		    &addr_devices_ops);
+	}
+	//allocate
+	void * vaddr = memalign(alignment, size);
+	
+	//get translation
+	void * paddr = NULL;
+	int opResult = as_get_physical_mapping(vaddr,(uintptr_t*)&paddr);
+	if(opResult != EOK){
+		//something went wrong
+		free(vaddr);
+		return NULL;
+	}
+	if((unsigned long)paddr + size > max_physical_address){
+		//unusable address for usb
+		free(vaddr);
+		return NULL;
+	}
+	//store translation
+	addr_node_t * pa2vaNode = create_addr_node(paddr,vaddr);
+	addr_node_t * va2paNode = create_addr_node(vaddr,paddr);
+
+	unsigned long keypaddr = (unsigned long)paddr;
+	unsigned long keyvaddr = (unsigned long)vaddr;
+	hash_table_insert(pa2va_table, (&keypaddr), &pa2vaNode->link);
+	hash_table_insert(va2pa_table, (&keyvaddr), &va2paNode->link);
+	//return
+	return vaddr;
+
+}
+
+/**
+ * get virtual address from physical
+ * @param addr
+ * @return translated virtual address or null
+ */
+void * mman_getVA(void * addr){
+	unsigned long keypaddr = (unsigned long)addr;
+	link_t * link = hash_table_find(pa2va_table, &keypaddr);
+	if(!link) return NULL;
+	addr_node_t * node = hash_table_get_instance(link, addr_node_t, link);
+	return (void*)node->translation;
+}
+
+/**
+ * get physical address from virtual
+ * @param addr
+ * @return physical address or null
+ */
+void * mman_getPA(void * addr){
+	unsigned long keyvaddr = (unsigned long)addr;
+	link_t * link = hash_table_find(va2pa_table, &keyvaddr);
+	if(!link) return NULL;
+	addr_node_t * node = hash_table_get_instance(link, addr_node_t, link);
+	return (void*)node->translation;
+}
+
+/**
+ * free the address and deregister it from pa<->va translation
+ * @param vaddr if NULL, nothing happens
+ */
+void mman_free(void * vaddr){
+	if(!vaddr)
+		return;
+	//get paddress
+	void * paddr = mman_getPA(vaddr);
+	unsigned long keypaddr = (unsigned long)paddr;
+	unsigned long keyvaddr = (unsigned long)vaddr;
+	//remove mapping
+	hash_table_remove(pa2va_table,&keypaddr, 1);
+	hash_table_remove(va2pa_table,&keyvaddr, 1);
+	//free address
+	free(vaddr);
+}
+
+
+
+/** @}
+ */
Index: uspace/lib/usbvirt/Makefile
===================================================================
--- uspace/lib/usbvirt/Makefile	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usbvirt/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -30,6 +30,5 @@
 LIBRARY = libusbvirt
 
-LIBS = $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS = -I$(LIBUSB_PREFIX)/include -Iinclude
+EXTRA_CFLAGS = -I$(LIBUSB_PREFIX)/include -I$(LIBDRV_PREFIX)/include -Iinclude
 
 SOURCES = \
Index: uspace/lib/usbvirt/include/usbvirt/device.h
===================================================================
--- uspace/lib/usbvirt/include/usbvirt/device.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usbvirt/include/usbvirt/device.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusbvirt usb
+/** @addtogroup libusbvirt
  * @{
  */
@@ -37,6 +37,6 @@
 
 #include <usb/usb.h>
+#include <usb/request.h>
 #include <usb/descriptor.h>
-#include <usb/devreq.h>
 
 /** Request type of a control transfer. */
Index: uspace/lib/usbvirt/include/usbvirt/hub.h
===================================================================
--- uspace/lib/usbvirt/include/usbvirt/hub.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usbvirt/include/usbvirt/hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusbvirt usb
+/** @addtogroup libusbvirt
  * @{
  */
Index: uspace/lib/usbvirt/src/callback.c
===================================================================
--- uspace/lib/usbvirt/src/callback.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usbvirt/src/callback.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusbvirt usb
+/** @addtogroup libusbvirt
  * @{
  */
@@ -54,15 +54,15 @@
 	
 	if (address != device->address) {
-		ipc_answer_0(iid, EADDRNOTAVAIL);
+		async_answer_0(iid, EADDRNOTAVAIL);
 		return;
 	}
 	
 	if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
 	
 	if (expected_len == 0) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -74,5 +74,5 @@
 		
 	if (rc != EOK) {
-		ipc_answer_0(iid, rc);
+		async_answer_0(iid, rc);
 		return;
 	}
@@ -80,5 +80,5 @@
 	rc = device->transaction_setup(device, endpoint, buffer, len);
 	
-	ipc_answer_0(iid, rc);
+	async_answer_0(iid, rc);
 }
 
@@ -92,10 +92,10 @@
 	
 	if (address != device->address) {
-		ipc_answer_0(iid, EADDRNOTAVAIL);
+		async_answer_0(iid, EADDRNOTAVAIL);
 		return;
 	}
 	
 	if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -111,5 +111,5 @@
 			
 		if (rc != EOK) {
-			ipc_answer_0(iid, rc);
+			async_answer_0(iid, rc);
 			return;
 		}
@@ -122,5 +122,5 @@
 	}
 	
-	ipc_answer_0(iid, rc);
+	async_answer_0(iid, rc);
 }
 
@@ -135,10 +135,10 @@
 	
 	if (address != device->address) {
-		ipc_answer_0(iid, EADDRNOTAVAIL);
+		async_answer_0(iid, EADDRNOTAVAIL);
 		return;
 	}
 	
 	if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -157,11 +157,14 @@
 		ipc_callid_t callid;
 		if (!async_data_read_receive(&callid, &receive_len)) {
-			ipc_answer_0(iid, EINVAL);
+			async_answer_0(iid, EINVAL);
 			return;
 		}
-		async_data_read_finalize(callid, buffer, receive_len);
-	}
-	
-	ipc_answer_0(iid, rc);
+		if (len > receive_len) {
+			len = receive_len;
+		}
+		async_data_read_finalize(callid, buffer, len);
+	}
+	
+	async_answer_1(iid, rc, len);
 }
 
@@ -171,5 +174,5 @@
 {
 	if (device->name == NULL) {
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 	}
 	
@@ -179,5 +182,5 @@
 	size_t accepted_size;
 	if (!async_data_read_receive(&callid, &accepted_size)) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -188,5 +191,5 @@
 	async_data_read_finalize(callid, device->name, accepted_size);
 	
-	ipc_answer_1(iid, EOK, accepted_size);
+	async_answer_1(iid, EOK, accepted_size);
 }
 
@@ -194,5 +197,5 @@
 void device_callback_connection(usbvirt_device_t *device, ipc_callid_t iid, ipc_call_t *icall)
 {
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
@@ -203,5 +206,5 @@
 		switch (IPC_GET_IMETHOD(call)) {
 			case IPC_M_PHONE_HUNGUP:
-				ipc_answer_0(callid, EOK);
+				async_answer_0(callid, EOK);
 				return;
 			
@@ -223,5 +226,5 @@
 			
 			default:
-				ipc_answer_0(callid, EINVAL);
+				async_answer_0(callid, EINVAL);
 				break;
 		}
Index: uspace/lib/usbvirt/src/ctrlpipe.c
===================================================================
--- uspace/lib/usbvirt/src/ctrlpipe.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usbvirt/src/ctrlpipe.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusbvirt usb
+/** @addtogroup libusbvirt
  * @{
  */
Index: uspace/lib/usbvirt/src/debug.c
===================================================================
--- uspace/lib/usbvirt/src/debug.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usbvirt/src/debug.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusbvirt usb
+/** @addtogroup libusbvirt
  * @{
  */
Index: uspace/lib/usbvirt/src/main.c
===================================================================
--- uspace/lib/usbvirt/src/main.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usbvirt/src/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusbvirt usb
+/** @addtogroup libusbvirt
  * @{
  */
@@ -159,5 +159,5 @@
 {
 	if (dev->vhcd_phone > 0) {
-		ipc_hangup(dev->vhcd_phone);
+		async_hangup(dev->vhcd_phone);
 	}
 	
@@ -173,5 +173,5 @@
 	virtual_device_t *dev = find_device_by_id(0);
 	if (dev == NULL) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		printf("Ooops\n");
 		return;
@@ -183,5 +183,5 @@
 /** Create necessary phones for communication with virtual HCD.
  * This function wraps following calls:
- * -# open <code>/dev/devices/\\virt\\usbhc for reading
+ * -# open <code>/dev/devices/\\virt\\usbhc</code> for reading
  * -# access phone of file opened in previous step
  * -# create callback through just opened phone
@@ -203,5 +203,5 @@
 	}
 	
-	const char *vhc_path = "/virt/usbhc";
+	const char *vhc_path = "/virt/usbhc/hc";
 	int rc;
 	devman_handle_t handle;
@@ -220,6 +220,5 @@
 	}
 	
-	sysarg_t phonehash;
-	rc = ipc_connect_to_me(hcd_phone, 0, 0, 0, &phonehash);
+	rc = async_connect_to_me(hcd_phone, 0, 0, 0, callback_connection);
 	if (rc != EOK) {
 		printf("ipc_connect_to_me() failed\n");
@@ -232,6 +231,4 @@
 	virtual_device->vhcd_phone = hcd_phone;
 	virtual_device->id = 0;
-	
-	async_new_connection(phonehash, 0, NULL, callback_connection);
 	
 	return EOK;
Index: uspace/lib/usbvirt/src/private.h
===================================================================
--- uspace/lib/usbvirt/src/private.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usbvirt/src/private.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusbvirt usb
+/** @addtogroup libusbvirt
  * @{
  */
Index: uspace/lib/usbvirt/src/stdreq.c
===================================================================
--- uspace/lib/usbvirt/src/stdreq.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usbvirt/src/stdreq.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusbvirt usb
+/** @addtogroup libusbvirt
  * @{
  */
@@ -36,5 +36,5 @@
 #include <stdlib.h>
 #include <mem.h>
-#include <usb/devreq.h>
+#include <usb/request.h>
 
 #include "private.h"
Index: uspace/lib/usbvirt/src/transaction.c
===================================================================
--- uspace/lib/usbvirt/src/transaction.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usbvirt/src/transaction.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusbvirt usb
+/** @addtogroup libusbvirt
  * @{
  */
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -51,9 +51,9 @@
 #include <libarch/ddi.h>
 #include <ddi.h>
-#include <ipc/ipc.h>
 #include <ipc/bd.h>
 #include <async.h>
 #include <as.h>
 #include <fibril_synch.h>
+#include <stdint.h>
 #include <str.h>
 #include <devmap.h>
@@ -62,4 +62,5 @@
 #include <errno.h>
 #include <bool.h>
+#include <byteorder.h>
 #include <task.h>
 #include <macros.h>
@@ -74,6 +75,9 @@
 #define LEGACY_CTLS 4
 
-/** Physical block size. Should be always 512. */
-static const size_t block_size = 512;
+/**
+ * Size of data returned from Identify Device or Identify Packet Device
+ * command.
+ */
+static const size_t identify_data_size = 512;
 
 /** Size of the communication area. */
@@ -106,10 +110,16 @@
 static int ata_bd_write_blocks(int disk_id, uint64_t ba, size_t cnt,
     const void *buf);
-static int ata_bd_read_block(int disk_id, uint64_t ba, size_t cnt,
+static int ata_rcmd_read(int disk_id, uint64_t ba, size_t cnt,
     void *buf);
-static int ata_bd_write_block(int disk_id, uint64_t ba, size_t cnt,
+static int ata_rcmd_write(int disk_id, uint64_t ba, size_t cnt,
     const void *buf);
 static int disk_init(disk_t *d, int disk_id);
 static int drive_identify(int drive_id, void *buf);
+static int identify_pkt_dev(int dev_idx, void *buf);
+static int ata_cmd_packet(int dev_idx, const void *cpkt, size_t cpkt_size,
+    void *obuf, size_t obuf_size);
+static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size);
+static int ata_pcmd_read_12(int dev_idx, uint64_t ba, size_t cnt,
+    void *obuf, size_t obuf_size);
 static void disk_print_summary(disk_t *d);
 static int coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc);
@@ -204,15 +214,20 @@
 	printf("%s: ", d->model);
 
-	switch (d->amode) {
-	case am_chs:
-		printf("CHS %u cylinders, %u heads, %u sectors",
-		    disk->geom.cylinders, disk->geom.heads, disk->geom.sectors);
-		break;
-	case am_lba28:
-		printf("LBA-28");
-		break;
-	case am_lba48:
-		printf("LBA-48");
-		break;
+	if (d->dev_type == ata_reg_dev) {
+		switch (d->amode) {
+		case am_chs:
+			printf("CHS %u cylinders, %u heads, %u sectors",
+			    disk->geom.cylinders, disk->geom.heads,
+			    disk->geom.sectors);
+			break;
+		case am_lba28:
+			printf("LBA-28");
+			break;
+		case am_lba48:
+			printf("LBA-48");
+			break;
+		}
+	} else {
+		printf("PACKET");
 	}
 
@@ -266,5 +281,5 @@
 	sysarg_t method;
 	devmap_handle_t dh;
-	int flags;
+	unsigned int flags;
 	int retval;
 	uint64_t ba;
@@ -282,13 +297,13 @@
 
 	if (disk_id < 0 || disk[disk_id].present == false) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
 
 	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -296,5 +311,5 @@
 	fs_va = as_get_mappable_page(comm_size);
 	if (fs_va == NULL) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -308,5 +323,5 @@
 		case IPC_M_PHONE_HUNGUP:
 			/* The other side has hung up. */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case BD_READ_BLOCKS:
@@ -314,5 +329,5 @@
 			    IPC_GET_ARG2(call));
 			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
+			if (cnt * disk[disk_id].block_size > comm_size) {
 				retval = ELIMIT;
 				break;
@@ -324,5 +339,5 @@
 			    IPC_GET_ARG2(call));
 			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
+			if (cnt * disk[disk_id].block_size > comm_size) {
 				retval = ELIMIT;
 				break;
@@ -331,8 +346,8 @@
 			break;
 		case BD_GET_BLOCK_SIZE:
-			ipc_answer_1(callid, EOK, block_size);
+			async_answer_1(callid, EOK, disk[disk_id].block_size);
 			continue;
 		case BD_GET_NUM_BLOCKS:
-			ipc_answer_2(callid, EOK, LOWER32(disk[disk_id].blocks),
+			async_answer_2(callid, EOK, LOWER32(disk[disk_id].blocks),
 			    UPPER32(disk[disk_id].blocks));
 			continue;
@@ -341,5 +356,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -354,4 +369,5 @@
 	identify_data_t idata;
 	uint8_t model[40];
+	ata_inquiry_data_t inq_data;
 	uint16_t w;
 	uint8_t c;
@@ -360,11 +376,42 @@
 	unsigned i;
 
+	d->present = false;
+	fibril_mutex_initialize(&d->lock);
+
+	/* Try identify command. */
 	rc = drive_identify(disk_id, &idata);
-	if (rc != EOK) {
-		d->present = false;
-		return rc;
-	}
-
-	if ((idata.caps & cap_lba) == 0) {
+	if (rc == EOK) {
+		/* Success. It's a register (non-packet) device. */
+		printf("ATA register-only device found.\n");
+		d->dev_type = ata_reg_dev;
+	} else if (rc == EIO) {
+		/*
+		 * There is something, but not a register device.
+		 * It could be a packet device.
+		 */
+		rc = identify_pkt_dev(disk_id, &idata);
+		if (rc == EOK) {
+			/* We have a packet device. */
+			d->dev_type = ata_pkt_dev;
+		} else {
+			/* Nope. Something's there, but not recognized. */
+			return EIO;
+		}
+	} else {
+		/* Operation timed out. That means there is no device there. */
+		return EIO;
+	}
+
+	printf("device caps: 0x%04x\n", idata.caps);
+	if (d->dev_type == ata_pkt_dev) {
+		/* Packet device */
+		d->amode = 0;
+
+		d->geom.cylinders = 0;
+		d->geom.heads = 0;
+		d->geom.sectors = 0;
+
+		d->blocks = 0;
+	} else if ((idata.caps & rd_cap_lba) == 0) {
 		/* Device only supports CHS addressing. */
 		d->amode = am_chs;
@@ -423,7 +470,25 @@
 	d->model[pos] = '\0';
 
+	if (d->dev_type == ata_pkt_dev) {
+		/* Send inquiry. */
+		rc = ata_pcmd_inquiry(0, &inq_data, sizeof(inq_data));
+		if (rc != EOK) {
+			printf("Device inquiry failed.\n");
+			d->present = false;
+			return EIO;
+		}
+
+		/* Check device type. */
+		if (INQUIRY_PDEV_TYPE(inq_data.pdev_type) != PDEV_TYPE_CDROM)
+			printf("Warning: Peripheral device type is not CD-ROM.\n");
+
+		/* Assume 2k block size for now. */
+		d->block_size = 2048;
+	} else {
+		/* Assume register Read always uses 512-byte blocks. */
+		d->block_size = 512;
+	}
+
 	d->present = true;
-	fibril_mutex_initialize(&d->lock);
-
 	return EOK;
 }
@@ -436,5 +501,10 @@
 
 	while (cnt > 0) {
-		rc = ata_bd_read_block(disk_id, ba, 1, buf);
+		if (disk[disk_id].dev_type == ata_reg_dev)
+			rc = ata_rcmd_read(disk_id, ba, 1, buf);
+		else
+			rc = ata_pcmd_read_12(disk_id, ba, 1, buf,
+			    disk[disk_id].block_size);
+
 		if (rc != EOK)
 			return rc;
@@ -442,5 +512,5 @@
 		++ba;
 		--cnt;
-		buf += block_size;
+		buf += disk[disk_id].block_size;
 	}
 
@@ -454,6 +524,9 @@
 	int rc;
 
+	if (disk[disk_id].dev_type != ata_reg_dev)
+		return ENOTSUP;
+
 	while (cnt > 0) {
-		rc = ata_bd_write_block(disk_id, ba, 1, buf);
+		rc = ata_rcmd_write(disk_id, ba, 1, buf);
 		if (rc != EOK)
 			return rc;
@@ -461,5 +534,5 @@
 		++ba;
 		--cnt;
-		buf += block_size;
+		buf += disk[disk_id].block_size;
 	}
 
@@ -474,4 +547,7 @@
  * @param disk_id	Device ID, 0 or 1.
  * @param buf		Pointer to a 512-byte buffer.
+ *
+ * @return		ETIMEOUT on timeout (this can mean the device is
+ *			not present). EIO if device responds with error.
  */
 static int drive_identify(int disk_id, void *buf)
@@ -485,5 +561,5 @@
 
 	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
-		return EIO;
+		return ETIMEOUT;
 
 	pio_write_8(&cmd->drive_head, drv_head);
@@ -494,15 +570,15 @@
 	 */
 	if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
-		return EIO;
+		return ETIMEOUT;
 
 	pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE);
 
 	if (wait_status(0, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
-		return EIO;
+		return ETIMEOUT;
 
 	/* Read data from the disk buffer. */
 
 	if ((status & SR_DRQ) != 0) {
-		for (i = 0; i < block_size / 2; i++) {
+		for (i = 0; i < identify_data_size / 2; i++) {
 			data = pio_read_16(&cmd->data_port);
 			((uint16_t *) buf)[i] = data;
@@ -510,6 +586,204 @@
 	}
 
+	if ((status & SR_ERR) != 0) {
+		return EIO;
+	}
+
+	return EOK;
+}
+
+/** Issue Identify Packet Device command.
+ *
+ * Reads @c identify data into the provided buffer. This is used to detect
+ * whether an ATAPI device is present and if so, to determine its parameters.
+ *
+ * @param dev_idx	Device index, 0 or 1.
+ * @param buf		Pointer to a 512-byte buffer.
+ */
+static int identify_pkt_dev(int dev_idx, void *buf)
+{
+	uint16_t data;
+	uint8_t status;
+	uint8_t drv_head;
+	size_t i;
+
+	drv_head = ((dev_idx != 0) ? DHR_DRV : 0);
+
+	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
+		return EIO;
+
+	pio_write_8(&cmd->drive_head, drv_head);
+
+	/* For ATAPI commands we do not need to wait for DRDY. */
+	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
+		return EIO;
+
+	pio_write_8(&cmd->command, CMD_IDENTIFY_PKT_DEV);
+
+	if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
+		return EIO;
+
+	/* Read data from the device buffer. */
+
+	if ((status & SR_DRQ) != 0) {
+		for (i = 0; i < identify_data_size / 2; i++) {
+			data = pio_read_16(&cmd->data_port);
+			((uint16_t *) buf)[i] = data;
+		}
+	}
+
 	if ((status & SR_ERR) != 0)
 		return EIO;
+
+	return EOK;
+}
+
+/** Issue packet command (i. e. write a command packet to the device).
+ *
+ * Only data-in commands are supported (e.g. inquiry, read).
+ *
+ * @param dev_idx	Device index (0 or 1)
+ * @param obuf		Buffer for storing data read from device
+ * @param obuf_size	Size of obuf in bytes
+ *
+ * @return EOK on success, EIO on error.
+ */
+static int ata_cmd_packet(int dev_idx, const void *cpkt, size_t cpkt_size,
+    void *obuf, size_t obuf_size)
+{
+	size_t i;
+	uint8_t status;
+	uint8_t drv_head;
+	disk_t *d;
+	size_t data_size;
+	uint16_t val;
+
+	d = &disk[dev_idx];
+	fibril_mutex_lock(&d->lock);
+
+	/* New value for Drive/Head register */
+	drv_head =
+	    ((dev_idx != 0) ? DHR_DRV : 0);
+
+	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	pio_write_8(&cmd->drive_head, drv_head);
+
+	if (wait_status(0, ~(SR_BSY|SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	/* Byte count <- max. number of bytes we can read in one transfer. */
+	pio_write_8(&cmd->cylinder_low, 0xfe);
+	pio_write_8(&cmd->cylinder_high, 0xff);
+
+	pio_write_8(&cmd->command, CMD_PACKET);
+
+	if (wait_status(SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	/* Write command packet. */
+	for (i = 0; i < (cpkt_size + 1) / 2; i++)
+		pio_write_16(&cmd->data_port, ((uint16_t *) cpkt)[i]);
+
+	if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	if ((status & SR_DRQ) == 0) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	/* Read byte count. */
+	data_size = (uint16_t) pio_read_8(&cmd->cylinder_low) +
+	    ((uint16_t) pio_read_8(&cmd->cylinder_high) << 8);
+
+	/* Check whether data fits into output buffer. */
+	if (data_size > obuf_size) {
+		/* Output buffer is too small to store data. */
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	/* Read data from the device buffer. */
+	for (i = 0; i < (data_size + 1) / 2; i++) {
+		val = pio_read_16(&cmd->data_port);
+		((uint16_t *) obuf)[i] = val;
+	}
+
+	if (status & SR_ERR) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	fibril_mutex_unlock(&d->lock);
+
+	return EOK;
+}
+
+/** Issue ATAPI Inquiry.
+ *
+ * @param dev_idx	Device index (0 or 1)
+ * @param obuf		Buffer for storing inquiry data read from device
+ * @param obuf_size	Size of obuf in bytes
+ *
+ * @return EOK on success, EIO on error.
+ */
+static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size)
+{
+	ata_pcmd_inquiry_t cp;
+	int rc;
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.opcode = PCMD_INQUIRY;
+	cp.alloc_len = min(obuf_size, 0xff); /* Allocation length */
+
+	rc = ata_cmd_packet(0, &cp, sizeof(cp), obuf, obuf_size);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+/** Issue ATAPI read(12) command.
+ *
+ * Output buffer must be large enough to hold the data, otherwise the
+ * function will fail.
+ *
+ * @param dev_idx	Device index (0 or 1)
+ * @param ba		Starting block address
+ * @param cnt		Number of blocks to read
+ * @param obuf		Buffer for storing inquiry data read from device
+ * @param obuf_size	Size of obuf in bytes
+ *
+ * @return EOK on success, EIO on error.
+ */
+static int ata_pcmd_read_12(int dev_idx, uint64_t ba, size_t cnt,
+    void *obuf, size_t obuf_size)
+{
+	ata_pcmd_read_12_t cp;
+	int rc;
+
+	if (ba > UINT32_MAX)
+		return EINVAL;
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.opcode = PCMD_READ_12;
+	cp.ba = host2uint32_t_be(ba);
+	cp.nblocks = host2uint32_t_be(cnt);
+
+	rc = ata_cmd_packet(0, &cp, sizeof(cp), obuf, obuf_size);
+	if (rc != EOK)
+		return rc;
 
 	return EOK;
@@ -525,5 +799,5 @@
  * @return EOK on success, EIO on error.
  */
-static int ata_bd_read_block(int disk_id, uint64_t ba, size_t blk_cnt,
+static int ata_rcmd_read(int disk_id, uint64_t ba, size_t blk_cnt,
     void *buf)
 {
@@ -580,5 +854,5 @@
 		/* Read data from the device buffer. */
 
-		for (i = 0; i < block_size / 2; i++) {
+		for (i = 0; i < disk[disk_id].block_size / 2; i++) {
 			data = pio_read_16(&cmd->data_port);
 			((uint16_t *) buf)[i] = data;
@@ -602,5 +876,5 @@
  * @return EOK on success, EIO on error.
  */
-static int ata_bd_write_block(int disk_id, uint64_t ba, size_t cnt,
+static int ata_rcmd_write(int disk_id, uint64_t ba, size_t cnt,
     const void *buf)
 {
@@ -656,5 +930,5 @@
 		/* Write data to the device buffer. */
 
-		for (i = 0; i < block_size / 2; i++) {
+		for (i = 0; i < disk[disk_id].block_size / 2; i++) {
 			pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]);
 		}
Index: uspace/srv/bd/ata_bd/ata_bd.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/bd/ata_bd/ata_bd.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -53,6 +53,11 @@
 };
 
-/** Block addressing mode. */
-enum addr_mode {
+enum ata_dev_type {
+	ata_reg_dev,	/* Register device (no packet feature set support) */
+	ata_pkt_dev	/* Packet device (supports packet feature set). */
+};
+
+/** Register device block addressing mode. */
+enum rd_addr_mode {
 	am_chs,		/**< CHS block addressing */
 	am_lba28,	/**< LBA-28 block addressing */
@@ -62,6 +67,5 @@
 /** Block coordinates */
 typedef struct {
-	/** Addressing mode used */
-	enum addr_mode amode;
+	enum rd_addr_mode amode;
 
 	union {
@@ -90,5 +94,10 @@
 typedef struct {
 	bool present;
-	enum addr_mode amode;
+
+	/** Device type */
+	enum ata_dev_type dev_type;
+
+	/** Addressing mode to use (if register device) */
+	enum rd_addr_mode amode;
 
 	/*
@@ -102,4 +111,5 @@
 
 	uint64_t blocks;
+	size_t block_size;
 
 	char model[STR_BOUNDS(40) + 1];
Index: uspace/srv/bd/ata_bd/ata_hw.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_hw.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/bd/ata_bd/ata_hw.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -134,8 +134,10 @@
 	CMD_WRITE_SECTORS	= 0x30,
 	CMD_WRITE_SECTORS_EXT	= 0x34,
+	CMD_PACKET		= 0xA0,
+	CMD_IDENTIFY_PKT_DEV	= 0xA1,
 	CMD_IDENTIFY_DRIVE	= 0xEC
 };
 
-/** Data returned from @c identify command. */
+/** Data returned from identify device and identify packet device command. */
 typedef struct {
 	uint16_t gen_conf;
@@ -159,5 +161,5 @@
 	uint16_t max_rw_multiple;
 	uint16_t _res48;
-	uint16_t caps;
+	uint16_t caps;		/* Different meaning for packet device */
 	uint16_t _res50;
 	uint16_t pio_timing;
@@ -214,9 +216,22 @@
 } identify_data_t;
 
-enum ata_caps {
-	cap_iordy	= 0x0800,
-	cap_iordy_cbd	= 0x0400,
-	cap_lba		= 0x0200,
-	cap_dma		= 0x0100
+/** Capability bits for register device. */
+enum ata_regdev_caps {
+	rd_cap_iordy		= 0x0800,
+	rd_cap_iordy_cbd	= 0x0400,
+	rd_cap_lba		= 0x0200,
+	rd_cap_dma		= 0x0100
+};
+
+/** Capability bits for packet device. */
+enum ata_pktdev_caps {
+	pd_cap_ildma		= 0x8000,
+	pd_cap_cmdqueue		= 0x4000,
+	pd_cap_overlap		= 0x2000,
+	pd_cap_need_softreset	= 0x1000,	/* Obsolete (ATAPI-6) */
+	pd_cap_iordy		= 0x0800,
+	pd_cap_iordy_dis	= 0x0400,
+	pd_cap_lba		= 0x0200,	/* Must be on */
+	pd_cap_dma		= 0x0100
 };
 
@@ -226,4 +241,56 @@
 };
 
+/** ATA packet command codes. */
+enum ata_pkt_command {
+	PCMD_INQUIRY		= 0x12,
+	PCMD_READ_12		= 0xa8
+};
+
+/** ATAPI Inquiry command */
+typedef struct {
+	uint8_t opcode;		/**< Operation code (PCMD_INQUIRY) */
+	uint8_t _res0;
+	uint8_t _res1;
+	uint8_t _res2;
+	uint8_t alloc_len;	/**< Allocation length */
+	uint8_t _res3;
+	uint8_t _res4;
+	uint8_t _res5;
+	uint32_t _res6;
+} __attribute__ ((packed)) ata_pcmd_inquiry_t;
+
+/** ATAPI Read(12) command */
+typedef struct {
+	uint8_t opcode;		/**< Operation code (PCMD_READ_12) */
+	uint8_t _res0;
+	uint32_t ba;		/**< Starting block address */
+	uint32_t nblocks;	/**< Number of blocks to transfer */
+	uint8_t _res1;
+	uint8_t _res2;
+} __attribute__ ((packed)) ata_pcmd_read_12_t;
+
+/** Data returned from Inquiry command (mandatory part) */
+typedef struct {
+	uint8_t pdev_type;	/** Reserved, Peripheral device type */
+	uint8_t rmb;		/** RMB, Reserved */
+	uint8_t std_version;	/** ISO version, ECMA version, ANSI version */
+	uint8_t atapi_ver_rdf;	/** ATAPI version, Response data format */
+	uint8_t additional_len;	/** Additional length */
+	uint8_t _res0;
+	uint8_t _res1;
+	uint8_t _res2;
+	uint8_t vendor_id[8];	/** Vendor ID */
+	uint8_t product_id[8];	/** Product ID */
+	uint8_t product_rev[4];	/** Product revision level */
+} ata_inquiry_data_t;
+
+/** Extract value of ata_inquiry_data_t.pdev_type */
+#define INQUIRY_PDEV_TYPE(val) ((val) & 0x1f)
+
+/** Values for ata_inquiry_data_t.pdev_type */
+enum ata_pdev_type {
+	PDEV_TYPE_CDROM		= 0x05
+};
+
 #endif
 
Index: uspace/srv/bd/file_bd/file_bd.c
===================================================================
--- uspace/srv/bd/file_bd/file_bd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/bd/file_bd/file_bd.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,5 +41,4 @@
 #include <stdio.h>
 #include <unistd.h>
-#include <ipc/ipc.h>
 #include <ipc/bd.h>
 #include <async.h>
@@ -178,5 +177,5 @@
 	sysarg_t method;
 	size_t comm_size;
-	int flags;
+	unsigned int flags;
 	int retval;
 	uint64_t ba;
@@ -184,8 +183,8 @@
 
 	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -193,5 +192,5 @@
 	fs_va = as_get_mappable_page(comm_size);
 	if (fs_va == NULL) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -205,5 +204,5 @@
 		case IPC_M_PHONE_HUNGUP:
 			/* The other side has hung up. */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case BD_READ_BLOCKS:
@@ -228,8 +227,8 @@
 			break;
 		case BD_GET_BLOCK_SIZE:
-			ipc_answer_1(callid, EOK, block_size);
+			async_answer_1(callid, EOK, block_size);
 			continue;
 		case BD_GET_NUM_BLOCKS:
-			ipc_answer_2(callid, EOK, LOWER32(num_blocks),
+			async_answer_2(callid, EOK, LOWER32(num_blocks),
 			    UPPER32(num_blocks));
 			continue;
@@ -238,5 +237,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/bd/gxe_bd/gxe_bd.c
===================================================================
--- uspace/srv/bd/gxe_bd/gxe_bd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/bd/gxe_bd/gxe_bd.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
 #include <libarch/ddi.h>
 #include <ddi.h>
-#include <ipc/ipc.h>
 #include <ipc/bd.h>
 #include <async.h>
@@ -161,5 +160,5 @@
 	sysarg_t method;
 	devmap_handle_t dh;
-	int flags;
+	unsigned int flags;
 	int retval;
 	uint64_t ba;
@@ -177,18 +176,18 @@
 
 	if (disk_id < 0) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
 
 	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
 
 	if (comm_size < block_size) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -196,5 +195,5 @@
 	fs_va = as_get_mappable_page(comm_size);
 	if (fs_va == NULL) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -208,5 +207,5 @@
 		case IPC_M_PHONE_HUNGUP:
 			/* The other side has hung up. */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case BD_READ_BLOCKS:
@@ -231,5 +230,5 @@
 			break;
 		case BD_GET_BLOCK_SIZE:
-			ipc_answer_1(callid, EOK, block_size);
+			async_answer_1(callid, EOK, block_size);
 			continue;
 		case BD_GET_NUM_BLOCKS:
@@ -240,5 +239,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/bd/part/guid_part/guid_part.c
===================================================================
--- uspace/srv/bd/part/guid_part/guid_part.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/bd/part/guid_part/guid_part.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -47,5 +47,4 @@
 #include <stdlib.h>
 #include <unistd.h>
-#include <ipc/ipc.h>
 #include <ipc/bd.h>
 #include <async.h>
@@ -316,5 +315,5 @@
 	sysarg_t method;
 	devmap_handle_t dh;
-	int flags;
+	unsigned int flags;
 	int retval;
 	aoff64_t ba;
@@ -335,5 +334,5 @@
 
 	if (part == NULL) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -342,8 +341,8 @@
 
 	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -351,5 +350,5 @@
 	fs_va = as_get_mappable_page(comm_size);
 	if (fs_va == NULL) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -363,5 +362,5 @@
 		case IPC_M_PHONE_HUNGUP:
 			/* The other side has hung up. */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case BD_READ_BLOCKS:
@@ -386,8 +385,8 @@
 			break;
 		case BD_GET_BLOCK_SIZE:
-			ipc_answer_1(callid, EOK, block_size);
+			async_answer_1(callid, EOK, block_size);
 			continue;
 		case BD_GET_NUM_BLOCKS:
-			ipc_answer_2(callid, EOK, LOWER32(part->length),
+			async_answer_2(callid, EOK, LOWER32(part->length),
 			    UPPER32(part->length));
 			continue;
@@ -396,5 +395,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/bd/part/mbr_part/mbr_part.c
===================================================================
--- uspace/srv/bd/part/mbr_part/mbr_part.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/bd/part/mbr_part/mbr_part.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -57,5 +57,4 @@
 #include <stdlib.h>
 #include <unistd.h>
-#include <ipc/ipc.h>
 #include <ipc/bd.h>
 #include <async.h>
@@ -394,5 +393,5 @@
 	sysarg_t method;
 	devmap_handle_t dh;
-	int flags;
+	unsigned int flags;
 	int retval;
 	uint64_t ba;
@@ -413,5 +412,5 @@
 
 	if (part == NULL) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -420,8 +419,8 @@
 
 	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -429,5 +428,5 @@
 	fs_va = as_get_mappable_page(comm_size);
 	if (fs_va == NULL) {
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -441,5 +440,5 @@
 		case IPC_M_PHONE_HUNGUP:
 			/* The other side has hung up. */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case BD_READ_BLOCKS:
@@ -464,8 +463,8 @@
 			break;
 		case BD_GET_BLOCK_SIZE:
-			ipc_answer_1(callid, EOK, block_size);
+			async_answer_1(callid, EOK, block_size);
 			continue;
 		case BD_GET_NUM_BLOCKS:
-			ipc_answer_2(callid, EOK, LOWER32(part->length),
+			async_answer_2(callid, EOK, LOWER32(part->length),
 			    UPPER32(part->length));
 			continue;
@@ -474,5 +473,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/bd/rd/rd.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/ns.h>
@@ -98,10 +97,10 @@
 	 * Answer the first IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	/*
 	 * Now we wait for the client to send us its communication as_area.
 	 */
-	int flags;
+	unsigned int flags;
 	if (async_share_out_receive(&callid, &comm_size, &flags)) {
 		fs_va = as_get_mappable_page(comm_size);
@@ -109,5 +108,5 @@
 			(void) async_share_out_finalize(callid, fs_va);
 		} else {
-			ipc_answer_0(callid, EHANGUP);
+			async_answer_0(callid, EHANGUP);
 			return;
 		}
@@ -118,5 +117,5 @@
 		 * Close the connection.
 		 */
-		ipc_answer_0(callid, EHANGUP);
+		async_answer_0(callid, EHANGUP);
 		return;
 	}
@@ -130,5 +129,5 @@
 			 * Answer the message and exit the fibril.
 			 */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case BD_READ_BLOCKS:
@@ -153,8 +152,8 @@
 			break;
 		case BD_GET_BLOCK_SIZE:
-			ipc_answer_1(callid, EOK, block_size);
+			async_answer_1(callid, EOK, block_size);
 			continue;
 		case BD_GET_NUM_BLOCKS:
-			ipc_answer_2(callid, EOK, LOWER32(rd_size / block_size),
+			async_answer_2(callid, EOK, LOWER32(rd_size / block_size),
 			    UPPER32(rd_size / block_size));
 			continue;
@@ -169,5 +168,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/clip/clip.c
===================================================================
--- uspace/srv/clip/clip.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/clip/clip.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -29,6 +29,6 @@
 #include <stdio.h>
 #include <bool.h>
-#include <ipc/ipc.h>
 #include <async.h>
+#include <ipc/ns.h>
 #include <ipc/services.h>
 #include <ipc/clipboard.h>
@@ -62,10 +62,10 @@
 		
 		fibril_mutex_unlock(&clip_mtx);
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		break;
 	case CLIPBOARD_TAG_DATA:
 		rc = async_data_write_accept((void **) &data, false, 0, 0, 0, &size);
 		if (rc != EOK) {
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 			break;
 		}
@@ -81,8 +81,8 @@
 		
 		fibril_mutex_unlock(&clip_mtx);
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		break;
 	default:
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(rid, EINVAL);
 	}
 }
@@ -99,6 +99,6 @@
 	case CLIPBOARD_TAG_DATA:
 		if (!async_data_read_receive(&callid, &size)) {
-			ipc_answer_0(callid, EINVAL);
-			ipc_answer_0(rid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			async_answer_0(rid, EINVAL);
 			break;
 		}
@@ -106,6 +106,6 @@
 		if (clip_tag != CLIPBOARD_TAG_DATA) {
 			/* So far we only understand binary data */
-			ipc_answer_0(callid, EOVERFLOW);
-			ipc_answer_0(rid, EOVERFLOW);
+			async_answer_0(callid, EOVERFLOW);
+			async_answer_0(rid, EOVERFLOW);
 			break;
 		}
@@ -113,6 +113,6 @@
 		if (clip_size != size) {
 			/* The client expects different size of data */
-			ipc_answer_0(callid, EOVERFLOW);
-			ipc_answer_0(rid, EOVERFLOW);
+			async_answer_0(callid, EOVERFLOW);
+			async_answer_0(rid, EOVERFLOW);
 			break;
 		}
@@ -120,9 +120,9 @@
 		sysarg_t retval = async_data_read_finalize(callid, clip_data, size);
 		if (retval != EOK) {
-			ipc_answer_0(rid, retval);
+			async_answer_0(rid, retval);
 			break;
 		}
 		
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 	default:
 		/*
@@ -130,5 +130,5 @@
 		 * data from the clipbard
 		 */
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		break;
 	}
@@ -145,5 +145,5 @@
 	
 	fibril_mutex_unlock(&clip_mtx);
-	ipc_answer_2(rid, EOK, (sysarg_t) size, (sysarg_t) tag);
+	async_answer_2(rid, EOK, (sysarg_t) size, (sysarg_t) tag);
 }
 
@@ -151,5 +151,5 @@
 {
 	/* Accept connection */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	bool cont = true;
@@ -172,5 +172,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOENT);
+			async_answer_0(callid, ENOENT);
 		}
 	}
@@ -183,6 +183,5 @@
 	async_set_client_connection(clip_connection);
 	
-	sysarg_t phonead;
-	if (ipc_connect_to_me(PHONE_NS, SERVICE_CLIPBOARD, 0, 0, &phonead) != 0) 
+	if (service_register(SERVICE_CLIPBOARD) != EOK)
 		return -1;
 	
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/devman/devman.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,4 +41,6 @@
 #include "devman.h"
 
+fun_node_t *find_node_child(fun_node_t *parent, const char *name);
+
 /* hash table operations */
 
@@ -51,13 +53,20 @@
     link_t *item)
 {
-	node_t *dev = hash_table_get_instance(item, node_t, devman_link);
+	dev_node_t *dev = hash_table_get_instance(item, dev_node_t, devman_dev);
 	return (dev->handle == (devman_handle_t) key[0]);
 }
 
-static int devmap_devices_compare(unsigned long key[], hash_count_t keys,
+static int devman_functions_compare(unsigned long key[], hash_count_t keys,
     link_t *item)
 {
-	node_t *dev = hash_table_get_instance(item, node_t, devmap_link);
-	return (dev->devmap_handle == (devmap_handle_t) key[0]);
+	fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devman_fun);
+	return (fun->handle == (devman_handle_t) key[0]);
+}
+
+static int devmap_functions_compare(unsigned long key[], hash_count_t keys,
+    link_t *item)
+{
+	fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devmap_fun);
+	return (fun->devmap_handle == (devmap_handle_t) key[0]);
 }
 
@@ -82,7 +91,13 @@
 };
 
+static hash_table_operations_t devman_functions_ops = {
+	.hash = devices_hash,
+	.compare = devman_functions_compare,
+	.remove_callback = devices_remove_callback
+};
+
 static hash_table_operations_t devmap_devices_ops = {
 	.hash = devices_hash,
-	.compare = devmap_devices_compare,
+	.compare = devmap_functions_compare,
 	.remove_callback = devices_remove_callback
 };
@@ -381,28 +396,52 @@
 }
 
-/** Create root device node in the device tree.
+/** Create root device and function node in the device tree.
  *
  * @param tree	The device tree.
  * @return	True on success, false otherwise.
  */
-bool create_root_node(dev_tree_t *tree)
-{
-	node_t *node;
-
-	printf(NAME ": create_root_node\n");
-
+bool create_root_nodes(dev_tree_t *tree)
+{
+	fun_node_t *fun;
+	dev_node_t *dev;
+	
+	printf(NAME ": create_root_nodes\n");
+	
 	fibril_rwlock_write_lock(&tree->rwlock);
-	node = create_dev_node();
-	if (node != NULL) {
-		insert_dev_node(tree, node, clone_string(""), NULL);
-		match_id_t *id = create_match_id();
-		id->id = clone_string("root");
-		id->score = 100;
-		add_match_id(&node->match_ids, id);
-		tree->root_node = node;
-	}
+	
+	/*
+	 * Create root function. This is a pseudo function to which
+	 * the root device node is attached. It allows us to match
+	 * the root device driver in a standard manner, i.e. against
+	 * the parent function.
+	 */
+	
+	fun = create_fun_node();
+	if (fun == NULL) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		return false;
+	}
+	
+	insert_fun_node(tree, fun, clone_string(""), NULL);
+	match_id_t *id = create_match_id();
+	id->id = clone_string("root");
+	id->score = 100;
+	add_match_id(&fun->match_ids, id);
+	tree->root_node = fun;
+	
+	/*
+	 * Create root device node.
+	 */
+	dev = create_dev_node();
+	if (dev == NULL) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		return false;
+	}
+	
+	insert_dev_node(tree, dev, fun);
+	
 	fibril_rwlock_write_unlock(&tree->rwlock);
-
-	return node != NULL;
+	
+	return dev != NULL;
 }
 
@@ -422,5 +461,5 @@
  *			is found.
  */
-driver_t *find_best_match_driver(driver_list_t *drivers_list, node_t *node)
+driver_t *find_best_match_driver(driver_list_t *drivers_list, dev_node_t *node)
 {
 	driver_t *best_drv = NULL, *drv = NULL;
@@ -450,13 +489,13 @@
  * @param drv		The driver.
  */
-void attach_driver(node_t *node, driver_t *drv)
+void attach_driver(dev_node_t *dev, driver_t *drv)
 {
 	printf(NAME ": attach_driver %s to device %s\n",
-	    drv->name, node->pathname);
+	    drv->name, dev->pfun->pathname);
 	
 	fibril_mutex_lock(&drv->driver_mutex);
 	
-	node->drv = drv;
-	list_append(&node->driver_devices, &drv->devices);
+	dev->drv = drv;
+	list_append(&dev->driver_devices, &drv->devices);
 	
 	fibril_mutex_unlock(&drv->driver_mutex);
@@ -538,5 +577,5 @@
 static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree)
 {
-	node_t *dev;
+	dev_node_t *dev;
 	link_t *link;
 	int phone;
@@ -559,5 +598,5 @@
 	link = driver->devices.next;
 	while (link != &driver->devices) {
-		dev = list_get_instance(link, node_t, driver_devices);
+		dev = list_get_instance(link, dev_node_t, driver_devices);
 		if (dev->passed_to_driver) {
 			link = link->next;
@@ -598,5 +637,5 @@
 	}
 
-	ipc_hangup(phone);
+	async_hangup(phone);
 
 	/*
@@ -677,11 +716,11 @@
 }
 
-/** Create devmap path and name for the device. */
-static void devmap_register_tree_device(node_t *node, dev_tree_t *tree)
+/** Create devmap path and name for the function. */
+void devmap_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
 {
 	char *devmap_pathname = NULL;
 	char *devmap_name = NULL;
 	
-	asprintf(&devmap_name, "%s", node->pathname);
+	asprintf(&devmap_name, "%s", fun->pathname);
 	if (devmap_name == NULL)
 		return;
@@ -697,7 +736,7 @@
 	
 	devmap_device_register_with_iface(devmap_pathname,
-	    &node->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
-	
-	tree_add_devmap_device(tree, node);
+	    &fun->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
+	
+	tree_add_devmap_function(tree, fun);
 	
 	free(devmap_name);
@@ -710,5 +749,5 @@
  * @param node		The device's node in the device tree.
  */
-void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)
+void add_device(int phone, driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
 {
 	/*
@@ -717,5 +756,5 @@
 	 */
 	printf(NAME ": add_device (driver `%s', device `%s')\n", drv->name,
-	    node->name);
+	    dev->pfun->name);
 	
 	sysarg_t rc;
@@ -724,16 +763,16 @@
 	/* Send the device to the driver. */
 	devman_handle_t parent_handle;
-	if (node->parent) {
-		parent_handle = node->parent->handle;
+	if (dev->pfun) {
+		parent_handle = dev->pfun->handle;
 	} else {
 		parent_handle = 0;
 	}
 
-	aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, node->handle,
+	aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, dev->handle,
 	    parent_handle, &answer);
 	
 	/* Send the device's name to the driver. */
-	rc = async_data_write_start(phone, node->name,
-	    str_size(node->name) + 1);
+	rc = async_data_write_start(phone, dev->pfun->name,
+	    str_size(dev->pfun->name) + 1);
 	if (rc != EOK) {
 		/* TODO handle error */
@@ -745,15 +784,14 @@
 	switch(rc) {
 	case EOK:
-		node->state = DEVICE_USABLE;
-		devmap_register_tree_device(node, tree);
+		dev->state = DEVICE_USABLE;
 		break;
 	case ENOENT:
-		node->state = DEVICE_NOT_PRESENT;
+		dev->state = DEVICE_NOT_PRESENT;
 		break;
 	default:
-		node->state = DEVICE_INVALID;
-	}
-	
-	node->passed_to_driver = true;
+		dev->state = DEVICE_INVALID;
+	}
+	
+	dev->passed_to_driver = true;
 
 	return;
@@ -767,18 +805,23 @@
  *			successfully assigned to the device, false otherwise.
  */
-bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree)
-{
+bool assign_driver(dev_node_t *dev, driver_list_t *drivers_list,
+    dev_tree_t *tree)
+{
+	assert(dev != NULL);
+	assert(drivers_list != NULL);
+	assert(tree != NULL);
+	
 	/*
 	 * Find the driver which is the most suitable for handling this device.
 	 */
-	driver_t *drv = find_best_match_driver(drivers_list, node);
+	driver_t *drv = find_best_match_driver(drivers_list, dev);
 	if (drv == NULL) {
 		printf(NAME ": no driver found for device '%s'.\n",
-		    node->pathname);
+		    dev->pfun->pathname);
 		return false;
 	}
 	
 	/* Attach the driver to the device. */
-	attach_driver(node, drv);
+	attach_driver(dev, drv);
 	
 	fibril_mutex_lock(&drv->driver_mutex);
@@ -794,6 +837,6 @@
 		int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
 		if (phone >= 0) {
-			add_device(phone, drv, node, tree);
-			ipc_hangup(phone);
+			add_device(phone, drv, dev, tree);
+			async_hangup(phone);
 		}
 	}
@@ -818,15 +861,17 @@
 	hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1,
 	    &devman_devices_ops);
-	hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1,
+	hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1,
+	    &devman_functions_ops);
+	hash_table_create(&tree->devmap_functions, DEVICE_BUCKETS, 1,
 	    &devmap_devices_ops);
 	
 	fibril_rwlock_initialize(&tree->rwlock);
 	
-	/* Create root node and add it to the device tree. */
-	if (!create_root_node(tree))
+	/* Create root function and root device and add them to the device tree. */
+	if (!create_root_nodes(tree))
 		return false;
 
 	/* Find suitable driver and start it. */
-	return assign_driver(tree->root_node, drivers_list, tree);
+	return assign_driver(tree->root_node->child, drivers_list, tree);
 }
 
@@ -837,13 +882,13 @@
  * @return		A device node structure.
  */
-node_t *create_dev_node(void)
-{
-	node_t *res = malloc(sizeof(node_t));
+dev_node_t *create_dev_node(void)
+{
+	dev_node_t *res = malloc(sizeof(dev_node_t));
 	
 	if (res != NULL) {
-		memset(res, 0, sizeof(node_t));
-		list_initialize(&res->children);
-		list_initialize(&res->match_ids.ids);
-		list_initialize(&res->classes);
+		memset(res, 0, sizeof(dev_node_t));
+		list_initialize(&res->functions);
+		link_initialize(&res->driver_devices);
+		link_initialize(&res->devman_dev);
 	}
 	
@@ -855,14 +900,11 @@
  * @param node		The device node structure.
  */
-void delete_dev_node(node_t *node)
-{
-	assert(list_empty(&node->children));
-	assert(node->parent == NULL);
-	assert(node->drv == NULL);
-	
-	clean_match_ids(&node->match_ids);
-	free_not_null(node->name);
-	free_not_null(node->pathname);
-	free(node);
+void delete_dev_node(dev_node_t *dev)
+{
+	assert(list_empty(&dev->functions));
+	assert(dev->pfun == NULL);
+	assert(dev->drv == NULL);
+	
+	free(dev);
 }
 
@@ -873,5 +915,5 @@
  * @return		The device node.
  */
-node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
+dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
 {
 	unsigned long key = handle;
@@ -881,5 +923,5 @@
 	
 	link = hash_table_find(&tree->devman_devices, &key);
-	return hash_table_get_instance(link, node_t, devman_link);
+	return hash_table_get_instance(link, dev_node_t, devman_dev);
 }
 
@@ -890,15 +932,88 @@
  * @return		The device node.
  */
-node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle)
-{
-	node_t *node = NULL;
+dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle)
+{
+	dev_node_t *dev = NULL;
 	
 	fibril_rwlock_read_lock(&tree->rwlock);
-	node = find_dev_node_no_lock(tree, handle);
+	dev = find_dev_node_no_lock(tree, handle);
 	fibril_rwlock_read_unlock(&tree->rwlock);
 	
-	return node;
-}
-
+	return dev;
+}
+
+/* Function nodes */
+
+/** Create a new function node.
+ *
+ * @return		A function node structure.
+ */
+fun_node_t *create_fun_node(void)
+{
+	fun_node_t *res = malloc(sizeof(fun_node_t));
+	
+	if (res != NULL) {
+		memset(res, 0, sizeof(fun_node_t));
+		link_initialize(&res->dev_functions);
+		list_initialize(&res->match_ids.ids);
+		list_initialize(&res->classes);
+		link_initialize(&res->devman_fun);
+		link_initialize(&res->devmap_fun);
+	}
+	
+	return res;
+}
+
+/** Delete a function node.
+ *
+ * @param fun		The device node structure.
+ */
+void delete_fun_node(fun_node_t *fun)
+{
+	assert(fun->dev == NULL);
+	assert(fun->child == NULL);
+	
+	clean_match_ids(&fun->match_ids);
+	free_not_null(fun->name);
+	free_not_null(fun->pathname);
+	free(fun);
+}
+
+/** Find the function node with the specified handle.
+ *
+ * @param tree		The device tree where we look for the device node.
+ * @param handle	The handle of the function.
+ * @return		The function node.
+ */
+fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
+{
+	unsigned long key = handle;
+	link_t *link;
+	
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+	
+	link = hash_table_find(&tree->devman_functions, &key);
+	if (link == NULL)
+		return NULL;
+	
+	return hash_table_get_instance(link, fun_node_t, devman_fun);
+}
+
+/** Find the function node with the specified handle.
+ *
+ * @param tree		The device tree where we look for the device node.
+ * @param handle	The handle of the function.
+ * @return		The function node.
+ */
+fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle)
+{
+	fun_node_t *fun = NULL;
+	
+	fibril_rwlock_read_lock(&tree->rwlock);
+	fun = find_fun_node_no_lock(tree, handle);
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	return fun;
+}
 
 /** Create and set device's full path in device tree.
@@ -909,14 +1024,14 @@
  *			resources etc.).
  */
-static bool set_dev_path(node_t *node, node_t *parent)
-{
-	assert(node->name != NULL);
-	
-	size_t pathsize = (str_size(node->name) + 1);
+static bool set_fun_path(fun_node_t *fun, fun_node_t *parent)
+{
+	assert(fun->name != NULL);
+	
+	size_t pathsize = (str_size(fun->name) + 1);
 	if (parent != NULL)
 		pathsize += str_size(parent->pathname) + 1;
 	
-	node->pathname = (char *) malloc(pathsize);
-	if (node->pathname == NULL) {
+	fun->pathname = (char *) malloc(pathsize);
+	if (fun->pathname == NULL) {
 		printf(NAME ": failed to allocate device path.\n");
 		return false;
@@ -924,9 +1039,9 @@
 	
 	if (parent != NULL) {
-		str_cpy(node->pathname, pathsize, parent->pathname);
-		str_append(node->pathname, pathsize, "/");
-		str_append(node->pathname, pathsize, node->name);
+		str_cpy(fun->pathname, pathsize, parent->pathname);
+		str_append(fun->pathname, pathsize, "/");
+		str_append(fun->pathname, pathsize, fun->name);
 	} else {
-		str_cpy(node->pathname, pathsize, node->name);
+		str_cpy(fun->pathname, pathsize, fun->name);
 	}
 	
@@ -944,44 +1059,81 @@
  *			etc.).
  */
-bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name,
-    node_t *parent)
-{
-	assert(node != NULL);
+bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun)
+{
+	assert(dev != NULL);
 	assert(tree != NULL);
-	assert(dev_name != NULL);
 	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
 	
-	node->name = dev_name;
-	if (!set_dev_path(node, parent)) {
+	/* Add the node to the handle-to-node map. */
+	dev->handle = ++tree->current_handle;
+	unsigned long key = dev->handle;
+	hash_table_insert(&tree->devman_devices, &key, &dev->devman_dev);
+
+	/* Add the node to the list of its parent's children. */
+	printf("insert_dev_node: dev=%p, dev->pfun := %p\n", dev, pfun);
+	dev->pfun = pfun;
+	pfun->child = dev;
+	
+	return true;
+}
+
+/** Insert new function into device tree.
+ *
+ * @param tree		The device tree.
+ * @param node		The newly added function node. 
+ * @param dev_name	The name of the newly added function.
+ * @param parent	Owning device node.
+ *
+ * @return		True on success, false otherwise (insufficient resources
+ *			etc.).
+ */
+bool insert_fun_node(dev_tree_t *tree, fun_node_t *fun, char *fun_name,
+    dev_node_t *dev)
+{
+	fun_node_t *pfun;
+	
+	assert(fun != NULL);
+	assert(tree != NULL);
+	assert(fun_name != NULL);
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
+	
+	/*
+	 * The root function is a special case, it does not belong to any
+	 * device so for the root function dev == NULL.
+	 */
+	pfun = (dev != NULL) ? dev->pfun : NULL;
+	
+	fun->name = fun_name;
+	if (!set_fun_path(fun, pfun)) {
 		return false;
 	}
 	
 	/* Add the node to the handle-to-node map. */
-	node->handle = ++tree->current_handle;
-	unsigned long key = node->handle;
-	hash_table_insert(&tree->devman_devices, &key, &node->devman_link);
+	fun->handle = ++tree->current_handle;
+	unsigned long key = fun->handle;
+	hash_table_insert(&tree->devman_functions, &key, &fun->devman_fun);
 
 	/* Add the node to the list of its parent's children. */
-	node->parent = parent;
-	if (parent != NULL)
-		list_append(&node->sibling, &parent->children);
+	fun->dev = dev;
+	if (dev != NULL)
+		list_append(&fun->dev_functions, &dev->functions);
 	
 	return true;
 }
 
-/** Find device node with a specified path in the device tree.
+/** Find function node with a specified path in the device tree.
  * 
- * @param path		The path of the device node in the device tree.
+ * @param path		The path of the function node in the device tree.
  * @param tree		The device tree.
- * @return		The device node if it is present in the tree, NULL
+ * @return		The function node if it is present in the tree, NULL
  *			otherwise.
  */
-node_t *find_dev_node_by_path(dev_tree_t *tree, char *path)
+fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path)
 {
 	fibril_rwlock_read_lock(&tree->rwlock);
 	
-	node_t *dev = tree->root_node;
+	fun_node_t *fun = tree->root_node;
 	/*
-	 * Relative path to the device from its parent (but with '/' at the
+	 * Relative path to the function from its parent (but with '/' at the
 	 * beginning)
 	 */
@@ -990,5 +1142,5 @@
 	bool cont = (rel_path[0] == '/');
 	
-	while (cont && dev != NULL) {
+	while (cont && fun != NULL) {
 		next_path_elem  = get_path_elem_end(rel_path + 1);
 		if (next_path_elem[0] == '/') {
@@ -999,5 +1151,5 @@
 		}
 		
-		dev = find_node_child(dev, rel_path + 1);
+		fun = find_node_child(fun, rel_path + 1);
 		
 		if (cont) {
@@ -1010,27 +1162,27 @@
 	fibril_rwlock_read_unlock(&tree->rwlock);
 	
-	return dev;
-}
-
-/** Find child device node with a specified name.
+	return fun;
+}
+
+/** Find child function node with a specified name.
  *
  * Device tree rwlock should be held at least for reading.
  *
- * @param parent	The parent device node.
- * @param name		The name of the child device node.
- * @return		The child device node.
- */
-node_t *find_node_child(node_t *parent, const char *name)
-{
-	node_t *dev;
+ * @param parent	The parent function node.
+ * @param name		The name of the child function.
+ * @return		The child function node.
+ */
+fun_node_t *find_node_child(fun_node_t *pfun, const char *name)
+{
+	fun_node_t *fun;
 	link_t *link;
 	
-	link = parent->children.next;
-	
-	while (link != &parent->children) {
-		dev = list_get_instance(link, node_t, sibling);
+	link = pfun->child->functions.next;
+	
+	while (link != &pfun->child->functions) {
+		fun = list_get_instance(link, fun_node_t, dev_functions);
 		
-		if (str_cmp(name, dev->name) == 0)
-			return dev;
+		if (str_cmp(name, fun->name) == 0)
+			return fun;
 		
 		link = link->next;
@@ -1071,7 +1223,7 @@
 	if (info != NULL) {
 		memset(info, 0, sizeof(dev_class_info_t));
-		list_initialize(&info->dev_classes);
-		list_initialize(&info->devmap_link);
-		list_initialize(&info->link);
+		link_initialize(&info->dev_classes);
+		link_initialize(&info->devmap_link);
+		link_initialize(&info->link);
 	}
 	
@@ -1115,5 +1267,5 @@
 }
 
-/** Add the device to the class.
+/** Add the device function to the class.
  *
  * The device may be added to multiple classes and a class may contain multiple
@@ -1128,12 +1280,18 @@
  *			with the class.
  */
-dev_class_info_t *add_device_to_class(node_t *dev, dev_class_t *cl,
+dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl,
     const char *base_dev_name)
 {
-	dev_class_info_t *info = create_dev_class_info();
+	dev_class_info_t *info;
+
+	assert(fun != NULL);
+	assert(cl != NULL);
+
+	info = create_dev_class_info();
+
 	
 	if (info != NULL) {
 		info->dev_class = cl;
-		info->dev = dev;
+		info->fun = fun;
 		
 		/* Add the device to the class. */
@@ -1143,5 +1301,5 @@
 		
 		/* Add the class to the device. */
-		list_append(&info->dev_classes, &dev->classes);
+		list_append(&info->dev_classes, &fun->classes);
 		
 		/* Create unique name for the device within the class. */
@@ -1197,5 +1355,5 @@
 	list_initialize(&class_list->classes);
 	fibril_rwlock_initialize(&class_list->rwlock);
-	hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1,
+	hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1,
 	    &devmap_devices_class_ops);
 }
@@ -1204,23 +1362,23 @@
 /* Devmap devices */
 
-node_t *find_devmap_tree_device(dev_tree_t *tree, devmap_handle_t devmap_handle)
-{
-	node_t *dev = NULL;
+fun_node_t *find_devmap_tree_function(dev_tree_t *tree, devmap_handle_t devmap_handle)
+{
+	fun_node_t *fun = NULL;
 	link_t *link;
 	unsigned long key = (unsigned long) devmap_handle;
 	
 	fibril_rwlock_read_lock(&tree->rwlock);
-	link = hash_table_find(&tree->devmap_devices, &key);
+	link = hash_table_find(&tree->devmap_functions, &key);
 	if (link != NULL)
-		dev = hash_table_get_instance(link, node_t, devmap_link);
+		fun = hash_table_get_instance(link, fun_node_t, devmap_fun);
 	fibril_rwlock_read_unlock(&tree->rwlock);
 	
-	return dev;
-}
-
-node_t *find_devmap_class_device(class_list_t *classes,
+	return fun;
+}
+
+fun_node_t *find_devmap_class_function(class_list_t *classes,
     devmap_handle_t devmap_handle)
 {
-	node_t *dev = NULL;
+	fun_node_t *fun = NULL;
 	dev_class_info_t *cli;
 	link_t *link;
@@ -1228,31 +1386,31 @@
 	
 	fibril_rwlock_read_lock(&classes->rwlock);
-	link = hash_table_find(&classes->devmap_devices, &key);
+	link = hash_table_find(&classes->devmap_functions, &key);
 	if (link != NULL) {
 		cli = hash_table_get_instance(link, dev_class_info_t,
 		    devmap_link);
-		dev = cli->dev;
+		fun = cli->fun;
 	}
 	fibril_rwlock_read_unlock(&classes->rwlock);
 	
-	return dev;
-}
-
-void class_add_devmap_device(class_list_t *class_list, dev_class_info_t *cli)
+	return fun;
+}
+
+void class_add_devmap_function(class_list_t *class_list, dev_class_info_t *cli)
 {
 	unsigned long key = (unsigned long) cli->devmap_handle;
 	
 	fibril_rwlock_write_lock(&class_list->rwlock);
-	hash_table_insert(&class_list->devmap_devices, &key, &cli->devmap_link);
+	hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link);
 	fibril_rwlock_write_unlock(&class_list->rwlock);
 
-	assert(find_devmap_class_device(class_list, cli->devmap_handle) != NULL);
-}
-
-void tree_add_devmap_device(dev_tree_t *tree, node_t *node)
-{
-	unsigned long key = (unsigned long) node->devmap_handle;
+	assert(find_devmap_class_function(class_list, cli->devmap_handle) != NULL);
+}
+
+void tree_add_devmap_function(dev_tree_t *tree, fun_node_t *fun)
+{
+	unsigned long key = (unsigned long) fun->devmap_handle;
 	fibril_rwlock_write_lock(&tree->rwlock);
-	hash_table_insert(&tree->devmap_devices, &key, &node->devmap_link);
+	hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun);
 	fibril_rwlock_write_unlock(&tree->rwlock);
 }
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/devman/devman.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,5 +40,4 @@
 #include <adt/list.h>
 #include <adt/hash_table.h>
-#include <ipc/ipc.h>
 #include <ipc/devman.h>
 #include <ipc/devmap.h>
@@ -57,6 +56,9 @@
 #define DEVMAP_SEPARATOR '\\'
 
-struct node;
-typedef struct node node_t;
+struct dev_node;
+typedef struct dev_node dev_node_t;
+
+struct fun_node;
+typedef struct fun_node fun_node_t;
 
 typedef enum {
@@ -118,55 +120,26 @@
 } device_state_t;
 
-/** Representation of a node in the device tree. */
-struct node {
+/** Device node in the device tree. */
+struct dev_node {
 	/** The global unique identifier of the device. */
 	devman_handle_t handle;
-	/** The name of the device specified by its parent. */
-	char *name;
-	
-	/**
-	 * Full path and name of the device in device hierarchi (i. e. in full
-	 * path in device tree).
-	 */
-	char *pathname;
-	
-	/** The node of the parent device. */
-	node_t *parent;
-	
-	/**
-	 * Pointers to previous and next child devices in the linked list of
-	 * parent device's node.
-	 */
-	link_t sibling;
-	
-	/** List of child device nodes. */
-	link_t children;
-	/** List of device ids for device-to-driver matching. */
-	match_id_list_t match_ids;
+	
+	/** (Parent) function the device is attached to. */
+	fun_node_t *pfun;
+	
+	/** List of device functions. */
+	link_t functions;
 	/** Driver of this device. */
 	driver_t *drv;
 	/** The state of the device. */
 	device_state_t state;
-	/**
-	 * Pointer to the previous and next device in the list of devices
-	 * owned by one driver.
-	 */
+	/** Link to list of devices owned by driver (driver_t.devices) */
 	link_t driver_devices;
 	
-	/** The list of device classes to which this device belongs. */
-	link_t classes;
-	/** Devmap handle if the device is registered by devmapper. */
-	devmap_handle_t devmap_handle;
-	
 	/**
 	 * Used by the hash table of devices indexed by devman device handles.
 	 */
-	link_t devman_link;
-	
-	/**
-	 * Used by the hash table of devices indexed by devmap device handles.
-	 */
-	link_t devmap_link;
-
+	link_t devman_dev;
+	
 	/**
 	 * Whether this device was already passed to the driver.
@@ -174,9 +147,47 @@
 	bool passed_to_driver;
 };
+
+/** Function node in the device tree. */
+struct fun_node {
+	/** The global unique identifier of the function */
+	devman_handle_t handle;
+	/** Name of the function, assigned by the device driver */
+	char *name;
+	
+	/** Full path and name of the device in device hierarchy */
+	char *pathname;
+	
+	/** Device which this function belongs to */
+	dev_node_t *dev;
+	
+	/** Link to list of functions in the device (ddf_dev_t.functions) */
+	link_t dev_functions;
+	
+	/** Child device node (if any attached). */
+	dev_node_t *child;
+	/** List of device ids for device-to-driver matching. */
+	match_id_list_t match_ids;
+	
+	/** The list of device classes to which this device function belongs. */
+	link_t classes;
+	/** Devmap handle if the device function is registered by devmap. */
+	devmap_handle_t devmap_handle;
+	
+	/**
+	 * Used by the hash table of functions indexed by devman device handles.
+	 */
+	link_t devman_fun;
+	
+	/**
+	 * Used by the hash table of functions indexed by devmap device handles.
+	 */
+	link_t devmap_fun;
+};
+
 
 /** Represents device tree. */
 typedef struct dev_tree {
 	/** Root device node. */
-	node_t *root_node;
+	fun_node_t *root_node;
 	
 	/**
@@ -192,9 +203,12 @@
 	hash_table_t devman_devices;
 	
+	/** Hash table of all devices indexed by devman handles. */
+	hash_table_t devman_functions;
+	
 	/**
 	 * Hash table of devices registered by devmapper, indexed by devmap
 	 * handles.
 	 */
-	hash_table_t devmap_devices;
+	hash_table_t devmap_functions;
 } dev_tree_t;
 
@@ -228,7 +242,7 @@
 
 /**
- * Provides n-to-m mapping between device nodes and classes - each device may
- * be register to the arbitrary number of classes and each class may contain
- * the arbitrary number of devices.
+ * Provides n-to-m mapping between function nodes and classes - each function
+ * can register in an arbitrary number of classes and each class can contain
+ * an arbitrary number of device functions.
  */
 typedef struct dev_class_info {
@@ -236,5 +250,5 @@
 	dev_class_t *dev_class;
 	/** The device. */
-	node_t *dev;
+	fun_node_t *fun;
 	
 	/**
@@ -250,5 +264,5 @@
 	link_t dev_classes;
 	
-	/** The name of the device within the class. */
+	/** The name of the device function within the class. */
 	char *dev_name;
 	/** The handle of the device by device mapper in the class namespace. */
@@ -271,5 +285,5 @@
 	 * indexed by devmap handles.
 	 */
-	hash_table_t devmap_devices;
+	hash_table_t devmap_functions;
 	
 	/** Fibril mutex for list of classes. */
@@ -279,5 +293,5 @@
 /* Match ids and scores */
 
-extern int get_match_score(driver_t *, node_t *);
+extern int get_match_score(driver_t *, dev_node_t *);
 
 extern bool parse_match_ids(char *, match_id_list_t *);
@@ -293,10 +307,10 @@
 extern int lookup_available_drivers(driver_list_t *, const char *);
 
-extern driver_t *find_best_match_driver(driver_list_t *, node_t *);
-extern bool assign_driver(node_t *, driver_list_t *, dev_tree_t *);
+extern driver_t *find_best_match_driver(driver_list_t *, dev_node_t *);
+extern bool assign_driver(dev_node_t *, driver_list_t *, dev_tree_t *);
 
 extern void add_driver(driver_list_t *, driver_t *);
-extern void attach_driver(node_t *, driver_t *);
-extern void add_device(int, driver_t *, node_t *, dev_tree_t *);
+extern void attach_driver(dev_node_t *, driver_t *);
+extern void add_device(int, driver_t *, dev_node_t *, dev_tree_t *);
 extern bool start_driver(driver_t *);
 
@@ -311,17 +325,24 @@
 /* Device nodes */
 
-extern node_t *create_dev_node(void);
-extern void delete_dev_node(node_t *node);
-extern node_t *find_dev_node_no_lock(dev_tree_t *tree,
+extern dev_node_t *create_dev_node(void);
+extern void delete_dev_node(dev_node_t *node);
+extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree,
     devman_handle_t handle);
-extern node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle);
-extern node_t *find_dev_node_by_path(dev_tree_t *, char *);
-extern node_t *find_node_child(node_t *, const char *);
+extern dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle);
+extern dev_node_t *find_dev_function(dev_node_t *, const char *);
+
+extern fun_node_t *create_fun_node(void);
+extern void delete_fun_node(fun_node_t *);
+extern fun_node_t *find_fun_node_no_lock(dev_tree_t *tree,
+    devman_handle_t handle);
+extern fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle);
+extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *);
 
 /* Device tree */
 
 extern bool init_device_tree(dev_tree_t *, driver_list_t *);
-extern bool create_root_node(dev_tree_t *);
-extern bool insert_dev_node(dev_tree_t *, node_t *, char *, node_t *);
+extern bool create_root_nodes(dev_tree_t *);
+extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *);
+extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *);
 
 /* Device classes */
@@ -331,5 +352,5 @@
 extern size_t get_new_class_dev_idx(dev_class_t *);
 extern char *create_dev_name_for_class(dev_class_t *, const char *);
-extern dev_class_info_t *add_device_to_class(node_t *, dev_class_t *,
+extern dev_class_info_t *add_function_to_class(fun_node_t *, dev_class_t *,
     const char *);
 
@@ -342,9 +363,11 @@
 /* Devmap devices */
 
-extern node_t *find_devmap_tree_device(dev_tree_t *, devmap_handle_t);
-extern node_t *find_devmap_class_device(class_list_t *, devmap_handle_t);
-
-extern void class_add_devmap_device(class_list_t *, dev_class_info_t *);
-extern void tree_add_devmap_device(dev_tree_t *, node_t *);
+extern void devmap_register_tree_function(fun_node_t *, dev_tree_t *);
+
+extern fun_node_t *find_devmap_tree_function(dev_tree_t *, devmap_handle_t);
+extern fun_node_t *find_devmap_class_function(class_list_t *, devmap_handle_t);
+
+extern void class_add_devmap_function(class_list_t *, dev_class_info_t *);
+extern void tree_add_devmap_function(dev_tree_t *, fun_node_t *);
 
 #endif
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/devman/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -75,5 +75,5 @@
 	iid = async_get_call(&icall);
 	if (IPC_GET_IMETHOD(icall) != DEVMAN_DRIVER_REGISTER) {
-		ipc_answer_0(iid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
 		return NULL;
 	}
@@ -84,5 +84,5 @@
 	int rc = async_data_write_accept((void **) &drv_name, true, 0, 0, 0, 0);
 	if (rc != EOK) {
-		ipc_answer_0(iid, rc);
+		async_answer_0(iid, rc);
 		return NULL;
 	}
@@ -98,5 +98,5 @@
 		free(drv_name);
 		drv_name = NULL;
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		return NULL;
 	}
@@ -110,6 +110,6 @@
 	ipc_callid_t callid = async_get_call(&call);
 	if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) {
-		ipc_answer_0(callid, ENOTSUP);
-		ipc_answer_0(iid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
+		async_answer_0(iid, ENOTSUP);
 		return NULL;
 	}
@@ -121,6 +121,6 @@
 	    driver->name);
 	
-	ipc_answer_0(callid, EOK);
-	ipc_answer_0(iid, EOK);
+	async_answer_0(callid, EOK);
+	async_answer_0(iid, EOK);
 	
 	return driver;
@@ -144,5 +144,5 @@
 		printf(NAME ": ERROR: devman_receive_match_id - invalid "
 		    "protocol.\n");
-		ipc_answer_0(callid, EINVAL); 
+		async_answer_0(callid, EINVAL); 
 		delete_match_id(match_id);
 		return EINVAL;
@@ -152,9 +152,9 @@
 		printf(NAME ": ERROR: devman_receive_match_id - failed to "
 		    "allocate match id.\n");
-		ipc_answer_0(callid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
 		return ENOMEM;
 	}
 	
-	ipc_answer_0(callid, EOK);
+	async_answer_0(callid, EOK);
 	
 	match_id->score = IPC_GET_ARG1(call);
@@ -199,70 +199,99 @@
 static int assign_driver_fibril(void *arg)
 {
-	node_t *node = (node_t *) arg;
-	assign_driver(node, &drivers_list, &device_tree);
+	dev_node_t *dev_node = (dev_node_t *) arg;
+	assign_driver(dev_node, &drivers_list, &device_tree);
 	return EOK;
 }
 
-/** Handle child device registration.
+/** Handle function registration.
  *
  * Child devices are registered by their parent's device driver.
  */
-static void devman_add_child(ipc_callid_t callid, ipc_call_t *call)
-{
-	devman_handle_t parent_handle = IPC_GET_ARG1(*call);
-	sysarg_t match_count = IPC_GET_ARG2(*call);
+static void devman_add_function(ipc_callid_t callid, ipc_call_t *call)
+{
+	fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call);
+	devman_handle_t dev_handle = IPC_GET_ARG2(*call);
+	sysarg_t match_count = IPC_GET_ARG3(*call);
 	dev_tree_t *tree = &device_tree;
 	
 	fibril_rwlock_write_lock(&tree->rwlock);
-	node_t *parent = find_dev_node_no_lock(&device_tree, parent_handle);
-	
-	if (parent == NULL) {
+
+	dev_node_t *dev = NULL;
+	dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle);
+	
+	if (pdev == NULL) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
-		ipc_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	char *dev_name = NULL;
-	int rc = async_data_write_accept((void **)&dev_name, true, 0, 0, 0, 0);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	if (ftype != fun_inner && ftype != fun_exposed) {
+		/* Unknown function type */
+		printf(NAME ": Error, unknown function type provided by driver!\n");
+
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+	
+	char *fun_name = NULL;
+	int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0);
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
-		ipc_answer_0(callid, rc);
-		return;
-	}
-	
-	node_t *node = create_dev_node();
-	if (!insert_dev_node(&device_tree, node, dev_name, parent)) {
+		async_answer_0(callid, rc);
+		return;
+	}
+	
+	fun_node_t *fun = create_fun_node();
+	if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
-		delete_dev_node(node);
-		ipc_answer_0(callid, ENOMEM);
-		return;
+		delete_fun_node(fun);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	if (ftype == fun_inner) {
+		dev = create_dev_node();
+		if (dev == NULL) {
+			fibril_rwlock_write_unlock(&tree->rwlock);
+			delete_fun_node(fun);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+
+		insert_dev_node(tree, dev, fun);
 	}
 
 	fibril_rwlock_write_unlock(&tree->rwlock);
 	
-	printf(NAME ": devman_add_child %s\n", node->pathname);
-	
-	devman_receive_match_ids(match_count, &node->match_ids);
-
-	/*
-	 * Try to find a suitable driver and assign it to the device.  We do
-	 * not want to block the current fibril that is used for processing
-	 * incoming calls: we will launch a separate fibril to handle the
-	 * driver assigning. That is because assign_driver can actually include
-	 * task spawning which could take some time.
-	 */
-	fid_t assign_fibril = fibril_create(assign_driver_fibril, node);
-	if (assign_fibril == 0) {
+	printf(NAME ": devman_add_function %s\n", fun->pathname);
+	
+	devman_receive_match_ids(match_count, &fun->match_ids);
+
+	if (ftype == fun_inner) {
+		assert(dev != NULL);
 		/*
-		 * Fallback in case we are out of memory.
-		 * Probably not needed as we will die soon anyway ;-).
+		 * Try to find a suitable driver and assign it to the device.  We do
+		 * not want to block the current fibril that is used for processing
+		 * incoming calls: we will launch a separate fibril to handle the
+		 * driver assigning. That is because assign_driver can actually include
+		 * task spawning which could take some time.
 		 */
-		(void) assign_driver_fibril(node);
+		fid_t assign_fibril = fibril_create(assign_driver_fibril, dev);
+		if (assign_fibril == 0) {
+			/*
+			 * Fallback in case we are out of memory.
+			 * Probably not needed as we will die soon anyway ;-).
+			 */
+			(void) assign_driver_fibril(fun);
+		} else {
+			fibril_add_ready(assign_fibril);
+		}
 	} else {
-		fibril_add_ready(assign_fibril);
-	}
-
+		devmap_register_tree_function(fun, tree);
+	}
+	
 	/* Return device handle to parent's driver. */
-	ipc_answer_1(callid, EOK, node->handle);
+	async_answer_1(callid, EOK, fun->handle);
 }
 
@@ -288,10 +317,10 @@
 	 * mapper.
 	 */
-	class_add_devmap_device(&class_list, cli);
+	class_add_devmap_function(&class_list, cli);
 	
 	free(devmap_pathname);
 }
 
-static void devman_add_device_to_class(ipc_callid_t callid, ipc_call_t *call)
+static void devman_add_function_to_class(ipc_callid_t callid, ipc_call_t *call)
 {
 	devman_handle_t handle = IPC_GET_ARG1(*call);
@@ -302,24 +331,24 @@
 	    0, 0, 0, 0);
 	if (rc != EOK) {
-		ipc_answer_0(callid, rc);
+		async_answer_0(callid, rc);
 		return;
 	}	
 	
-	node_t *dev = find_dev_node(&device_tree, handle);
-	if (dev == NULL) {
-		ipc_answer_0(callid, ENOENT);
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(callid, ENOENT);
 		return;
 	}
 	
 	dev_class_t *cl = get_dev_class(&class_list, class_name);
-	dev_class_info_t *class_info = add_device_to_class(dev, cl, NULL);
+	dev_class_info_t *class_info = add_function_to_class(fun, cl, NULL);
 	
 	/* Register the device's class alias by devmapper. */
 	devmap_register_class_dev(class_info);
 	
-	printf(NAME ": device '%s' added to class '%s', class name '%s' was "
-	    "asigned to it\n", dev->pathname, class_name, class_info->dev_name);
-
-	ipc_answer_0(callid, EOK);
+	printf(NAME ": function'%s' added to class '%s', class name '%s' was "
+	    "asigned to it\n", fun->pathname, class_name, class_info->dev_name);
+
+	async_answer_0(callid, EOK);
 }
 
@@ -343,5 +372,5 @@
 {
 	/* Accept the connection. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	driver_t *driver = devman_driver_register();
@@ -372,12 +401,12 @@
 			cont = false;
 			continue;
-		case DEVMAN_ADD_CHILD_DEVICE:
-			devman_add_child(callid, &call);
+		case DEVMAN_ADD_FUNCTION:
+			devman_add_function(callid, &call);
 			break;
 		case DEVMAN_ADD_DEVICE_TO_CLASS:
-			devman_add_device_to_class(callid, &call);
+			devman_add_function_to_class(callid, &call);
 			break;
 		default:
-			ipc_answer_0(callid, EINVAL); 
+			async_answer_0(callid, EINVAL); 
 			break;
 		}
@@ -387,5 +416,5 @@
 /** Find handle for the device instance identified by the device's path in the
  * device tree. */
-static void devman_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
+static void devman_function_get_handle(ipc_callid_t iid, ipc_call_t *icall)
 {
 	char *pathname;
@@ -393,18 +422,18 @@
 	int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
 	if (rc != EOK) {
-		ipc_answer_0(iid, rc);
-		return;
-	}
-	
-	node_t * dev = find_dev_node_by_path(&device_tree, pathname);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname);
 	
 	free(pathname);
 
-	if (dev == NULL) {
-		ipc_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	ipc_answer_1(iid, EOK, dev->handle);
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	async_answer_1(iid, EOK, fun->handle);
 }
 
@@ -414,5 +443,5 @@
 {
 	/* Accept connection. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	bool cont = true;
@@ -426,8 +455,8 @@
 			continue;
 		case DEVMAN_DEVICE_GET_HANDLE:
-			devman_device_get_handle(callid, &call);
+			devman_function_get_handle(callid, &call);
 			break;
 		default:
-			ipc_answer_0(callid, ENOENT);
+			async_answer_0(callid, ENOENT);
 		}
 	}
@@ -438,10 +467,25 @@
 {
 	devman_handle_t handle = IPC_GET_ARG2(*icall);
-	
-	node_t *dev = find_dev_node(&device_tree, handle);
-	if (dev == NULL) {
-		printf(NAME ": devman_forward error - no device with handle %" PRIun
-		    " was found.\n", handle);
-		ipc_answer_0(iid, ENOENT);
+	devman_handle_t fwd_h;
+	fun_node_t *fun = NULL;
+	dev_node_t *dev = NULL;
+	
+	fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL)
+		dev = find_dev_node(&device_tree, handle);
+	else
+		dev = fun->dev;
+
+	if (fun == NULL && dev == NULL) {
+		printf(NAME ": devman_forward error - no device or function with "
+		    "handle %" PRIun " was found.\n", handle);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	if (fun == NULL && !drv_to_parent) {
+		printf(NAME ": devman_forward error - cannot connect to "
+		    "handle %" PRIun ", refers to a device.\n", handle);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
@@ -450,9 +494,14 @@
 	
 	if (drv_to_parent) {
-		if (dev->parent != NULL)
-			driver = dev->parent->drv;
+		/* Connect to parent function of a device (or device function). */
+		if (dev->pfun->dev != NULL)
+			driver = dev->pfun->dev->drv;
+		fwd_h = dev->pfun->handle;
 	} else if (dev->state == DEVICE_USABLE) {
+		/* Connect to the specified function */
 		driver = dev->drv;
 		assert(driver != NULL);
+
+		fwd_h = handle;
 	}
 	
@@ -460,6 +509,6 @@
 		printf(NAME ": devman_forward error - the device %" PRIun \
 		    " (%s) is not in usable state.\n",
-		    handle, dev->pathname);
-		ipc_answer_0(iid, ENOENT);
+		    handle, dev->pfun->pathname);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
@@ -475,11 +524,17 @@
 		    driver->name);
 		printf("the driver's phone is %" PRIun ").\n", driver->phone);
-		ipc_answer_0(iid, EINVAL);
-		return;
-	}
-
-	printf(NAME ": devman_forward: forward connection to device %s to "
-	    "driver %s.\n", dev->pathname, driver->name);
-	ipc_forward_fast(iid, driver->phone, method, dev->handle, 0, IPC_FF_NONE);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	if (fun != NULL) {
+		printf(NAME ": devman_forward: forward connection to function %s to "
+		    "driver %s.\n", fun->pathname, driver->name);
+	} else {
+		printf(NAME ": devman_forward: forward connection to device %s to "
+		    "driver %s.\n", dev->pfun->pathname, driver->name);
+	}
+
+	async_forward_fast(iid, driver->phone, method, fwd_h, 0, IPC_FF_NONE);
 }
 
@@ -489,24 +544,27 @@
 {
 	devmap_handle_t devmap_handle = IPC_GET_ARG2(*icall);
-	node_t *dev;
-
-	dev = find_devmap_tree_device(&device_tree, devmap_handle);
-	if (dev == NULL)
-		dev = find_devmap_class_device(&class_list, devmap_handle);
-	
-	if (dev == NULL || dev->drv == NULL) {
-		ipc_answer_0(iid, ENOENT);
-		return;
-	}
+	fun_node_t *fun;
+	dev_node_t *dev;
+
+	fun = find_devmap_tree_function(&device_tree, devmap_handle);
+	if (fun == NULL)
+		fun = find_devmap_class_function(&class_list, devmap_handle);
+	
+	if (fun == NULL || fun->dev->drv == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	dev = fun->dev;
 	
 	if (dev->state != DEVICE_USABLE || dev->drv->phone <= 0) {
-		ipc_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	ipc_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, dev->handle, 0,
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	async_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, fun->handle, 0,
 	    IPC_FF_NONE);
 	printf(NAME ": devman_connection_devmapper: forwarded connection to "
-	    "device %s to driver %s.\n", dev->pathname, dev->drv->name);
+	    "device %s to driver %s.\n", fun->pathname, dev->drv->name);
 }
 
@@ -536,5 +594,5 @@
 	default:
 		/* No such interface */
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 	}
 }
@@ -587,6 +645,5 @@
 
 	/* Register device manager at naming service. */
-	sysarg_t phonead;
-	if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAN, 0, 0, &phonead) != 0)
+	if (service_register(SERVICE_DEVMAN) != EOK)
 		return -1;
 
Index: uspace/srv/devman/match.c
===================================================================
--- uspace/srv/devman/match.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/devman/match.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -57,8 +57,8 @@
 }
 
-int get_match_score(driver_t *drv, node_t *dev)
+int get_match_score(driver_t *drv, dev_node_t *dev)
 {
 	link_t *drv_head = &drv->match_ids.ids;
-	link_t *dev_head = &dev->match_ids.ids;
+	link_t *dev_head = &dev->pfun->match_ids.ids;
 	
 	if (list_empty(drv_head) || list_empty(dev_head))
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/devmap/devmap.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -374,5 +374,5 @@
 	
 	if (IPC_GET_IMETHOD(icall) != DEVMAP_DRIVER_REGISTER) {
-		ipc_answer_0(iid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
 		return NULL;
 	}
@@ -381,5 +381,5 @@
 	    (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
 	if (driver == NULL) {
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return NULL;
 	}
@@ -392,5 +392,5 @@
 	if (rc != EOK) {
 		free(driver);
-		ipc_answer_0(iid, rc);
+		async_answer_0(iid, rc);
 		return NULL;
 	}
@@ -405,11 +405,11 @@
 		free(driver->name);
 		free(driver);
-		ipc_answer_0(callid, ENOTSUP);
-		ipc_answer_0(iid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
+		async_answer_0(iid, ENOTSUP);
 		return NULL;
 	}
 	
 	driver->phone = IPC_GET_ARG5(call);
-	ipc_answer_0(callid, EOK);
+	async_answer_0(callid, EOK);
 	
 	/*
@@ -423,5 +423,6 @@
 	 */
 	list_initialize(&driver->devices);
-	list_initialize(&(driver->drivers));
+
+	link_initialize(&driver->drivers);
 	
 	fibril_mutex_lock(&drivers_list_mutex);
@@ -438,5 +439,5 @@
 	fibril_mutex_unlock(&drivers_list_mutex);
 	
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	return driver;
@@ -456,5 +457,5 @@
 	
 	if (driver->phone != 0)
-		ipc_hangup(driver->phone);
+		async_hangup(driver->phone);
 	
 	/* Remove it from list of drivers */
@@ -491,5 +492,5 @@
 {
 	if (driver == NULL) {
-		ipc_answer_0(iid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
 		return;
 	}
@@ -499,5 +500,5 @@
 	    (devmap_device_t *) malloc(sizeof(devmap_device_t));
 	if (device == NULL) {
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
@@ -512,5 +513,5 @@
 	if (rc != EOK) {
 		free(device);
-		ipc_answer_0(iid, rc);
+		async_answer_0(iid, rc);
 		return;
 	}
@@ -520,5 +521,5 @@
 		free(fqdn);
 		free(device);
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -534,10 +535,10 @@
 		free(device->name);
 		free(device);
-		ipc_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	list_initialize(&(device->devices));
-	list_initialize(&(device->driver_devices));
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	link_initialize(&device->devices);
+	link_initialize(&device->driver_devices);
 	
 	/* Check that device is not already registered */
@@ -549,5 +550,5 @@
 		free(device->name);
 		free(device);
-		ipc_answer_0(iid, EEXISTS);
+		async_answer_0(iid, EEXISTS);
 		return;
 	}
@@ -571,5 +572,5 @@
 	fibril_mutex_unlock(&devices_list_mutex);
 	
-	ipc_answer_1(iid, EOK, device->handle);
+	async_answer_1(iid, EOK, device->handle);
 }
 
@@ -602,14 +603,14 @@
 	if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
 		fibril_mutex_unlock(&devices_list_mutex);
-		ipc_answer_0(callid, ENOENT);
+		async_answer_0(callid, ENOENT);
 		return;
 	}
 	
 	if (dev->forward_interface == 0) {
-		ipc_forward_fast(callid, dev->driver->phone,
+		async_forward_fast(callid, dev->driver->phone,
 		    dev->handle, 0, 0,
 		    IPC_FF_NONE);
 	} else {
-		ipc_forward_fast(callid, dev->driver->phone,
+		async_forward_fast(callid, dev->driver->phone,
 		    dev->forward_interface, dev->handle, 0,
 		    IPC_FF_NONE);
@@ -633,5 +634,5 @@
 	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(iid, rc);
+		async_answer_0(iid, rc);
 		return;
 	}
@@ -641,5 +642,5 @@
 	if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
 		free(fqdn);
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -668,5 +669,5 @@
 		}
 		
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		free(ns_name);
 		free(name);
@@ -675,5 +676,5 @@
 	}
 	
-	ipc_answer_1(iid, EOK, dev->handle);
+	async_answer_1(iid, EOK, dev->handle);
 	
 	fibril_mutex_unlock(&devices_list_mutex);
@@ -696,5 +697,5 @@
 	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(iid, rc);
+		async_answer_0(iid, rc);
 		return;
 	}
@@ -721,5 +722,5 @@
 		}
 		
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		free(name);
 		fibril_mutex_unlock(&devices_list_mutex);
@@ -727,5 +728,5 @@
 	}
 	
-	ipc_answer_1(iid, EOK, namespace->handle);
+	async_answer_1(iid, EOK, namespace->handle);
 	
 	fibril_mutex_unlock(&devices_list_mutex);
@@ -743,9 +744,9 @@
 		    devmap_device_find_handle(IPC_GET_ARG1(*icall));
 		if (dev == NULL)
-			ipc_answer_1(iid, EOK, DEV_HANDLE_NONE);
+			async_answer_1(iid, EOK, DEV_HANDLE_NONE);
 		else
-			ipc_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
+			async_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
 	} else
-		ipc_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
+		async_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
 	
 	fibril_mutex_unlock(&devices_list_mutex);
@@ -755,5 +756,5 @@
 {
 	fibril_mutex_lock(&devices_list_mutex);
-	ipc_answer_1(iid, EOK, list_count(&namespaces_list));
+	async_answer_1(iid, EOK, list_count(&namespaces_list));
 	fibril_mutex_unlock(&devices_list_mutex);
 }
@@ -766,7 +767,7 @@
 	    devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
 	if (namespace == NULL)
-		ipc_answer_0(iid, EEXISTS);
+		async_answer_0(iid, EEXISTS);
 	else
-		ipc_answer_1(iid, EOK, namespace->refcnt);
+		async_answer_1(iid, EOK, namespace->refcnt);
 	
 	fibril_mutex_unlock(&devices_list_mutex);
@@ -778,12 +779,12 @@
 	size_t size;
 	if (!async_data_read_receive(&callid, &size)) {
-		ipc_answer_0(callid, EREFUSED);
-		ipc_answer_0(iid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
 		return;
 	}
 	
 	if ((size % sizeof(dev_desc_t)) != 0) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -794,6 +795,6 @@
 	if (count != list_count(&namespaces_list)) {
 		fibril_mutex_unlock(&devices_list_mutex);
-		ipc_answer_0(callid, EOVERFLOW);
-		ipc_answer_0(iid, EOVERFLOW);
+		async_answer_0(callid, EOVERFLOW);
+		async_answer_0(iid, EOVERFLOW);
 		return;
 	}
@@ -802,6 +803,6 @@
 	if (desc == NULL) {
 		fibril_mutex_unlock(&devices_list_mutex);
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
@@ -824,5 +825,5 @@
 	fibril_mutex_unlock(&devices_list_mutex);
 	
-	ipc_answer_0(iid, retval);
+	async_answer_0(iid, retval);
 }
 
@@ -835,12 +836,12 @@
 	size_t size;
 	if (!async_data_read_receive(&callid, &size)) {
-		ipc_answer_0(callid, EREFUSED);
-		ipc_answer_0(iid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
 		return;
 	}
 	
 	if ((size % sizeof(dev_desc_t)) != 0) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -852,6 +853,6 @@
 	if (namespace == NULL) {
 		fibril_mutex_unlock(&devices_list_mutex);
-		ipc_answer_0(callid, ENOENT);
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
@@ -860,6 +861,6 @@
 	if (count != namespace->refcnt) {
 		fibril_mutex_unlock(&devices_list_mutex);
-		ipc_answer_0(callid, EOVERFLOW);
-		ipc_answer_0(iid, EOVERFLOW);
+		async_answer_0(callid, EOVERFLOW);
+		async_answer_0(iid, EOVERFLOW);
 		return;
 	}
@@ -868,6 +869,6 @@
 	if (desc == NULL) {
 		fibril_mutex_unlock(&devices_list_mutex);
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(iid, EREFUSED);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, EREFUSED);
 		return;
 	}
@@ -891,5 +892,5 @@
 	fibril_mutex_unlock(&devices_list_mutex);
 	
-	ipc_answer_0(iid, retval);
+	async_answer_0(iid, retval);
 }
 
@@ -910,5 +911,5 @@
 	if (!fnd) {
 		fibril_mutex_unlock(&null_devices_mutex);
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
@@ -920,5 +921,5 @@
 	if (dev_name == NULL) {
 		fibril_mutex_unlock(&null_devices_mutex);
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
@@ -928,5 +929,5 @@
 	if (device == NULL) {
 		fibril_mutex_unlock(&null_devices_mutex);
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
@@ -938,10 +939,10 @@
 		fibril_mutex_lock(&devices_list_mutex);
 		fibril_mutex_unlock(&null_devices_mutex);
-		ipc_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	list_initialize(&(device->devices));
-	list_initialize(&(device->driver_devices));
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	link_initialize(&device->devices);
+	link_initialize(&device->driver_devices);
 	
 	/* Get unique device handle */
@@ -960,5 +961,5 @@
 	fibril_mutex_unlock(&null_devices_mutex);
 	
-	ipc_answer_1(iid, EOK, (sysarg_t) i);
+	async_answer_1(iid, EOK, (sysarg_t) i);
 }
 
@@ -967,5 +968,5 @@
 	sysarg_t i = IPC_GET_ARG1(*icall);
 	if (i >= NULL_DEVICES) {
-		ipc_answer_0(iid, ELIMIT);
+		async_answer_0(iid, ELIMIT);
 		return;
 	}
@@ -975,5 +976,5 @@
 	if (null_devices[i] == NULL) {
 		fibril_mutex_unlock(&null_devices_mutex);
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
@@ -986,5 +987,5 @@
 	
 	fibril_mutex_unlock(&null_devices_mutex);
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 }
 
@@ -1012,5 +1013,5 @@
 {
 	/* Accept connection */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	devmap_driver_t *driver = devmap_driver_register();
@@ -1029,7 +1030,7 @@
 		case DEVMAP_DRIVER_UNREGISTER:
 			if (NULL == driver)
-				ipc_answer_0(callid, ENOENT);
+				async_answer_0(callid, ENOENT);
 			else
-				ipc_answer_0(callid, EOK);
+				async_answer_0(callid, EOK);
 			break;
 		case DEVMAP_DEVICE_REGISTER:
@@ -1048,5 +1049,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOENT);
+			async_answer_0(callid, ENOENT);
 		}
 	}
@@ -1067,5 +1068,5 @@
 {
 	/* Accept connection */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	bool cont = true;
@@ -1106,5 +1107,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOENT);
+			async_answer_0(callid, ENOENT);
 		}
 	}
@@ -1130,5 +1131,5 @@
 	default:
 		/* No such interface */
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 	}
 }
@@ -1150,6 +1151,5 @@
 	
 	/* Register device mapper at naming service */
-	sysarg_t phonead;
-	if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0) 
+	if (service_register(SERVICE_DEVMAP) != EOK)
 		return -1;
 	
Index: uspace/srv/fs/devfs/devfs.c
===================================================================
--- uspace/srv/fs/devfs/devfs.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/fs/devfs/devfs.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,6 +40,6 @@
 
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
+#include <ipc/ns.h>
 #include <async.h>
 #include <errno.h>
@@ -62,5 +62,5 @@
 {
 	if (iid)
-		ipc_answer_0(iid, EOK);
+		async_answer_0(iid, EOK);
 	
 	while (true) {
@@ -111,5 +111,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOTSUP);
+			async_answer_0(callid, ENOTSUP);
 			break;
 		}
@@ -126,5 +126,5 @@
 	}
 	
-	int vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
+	int vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
 	if (vfs_phone < EOK) {
 		printf(NAME ": Unable to connect to VFS\n");
Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <macros.h>
 #include <bool.h>
@@ -131,4 +130,5 @@
 {
 	devfs_node_t *node = (devfs_node_t *) pfn->data;
+	int ret;
 	
 	if (node->handle == 0) {
@@ -146,6 +146,7 @@
 				
 				if (str_cmp(devs[pos].name, component) == 0) {
+					ret = devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
 					free(devs);
-					return devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
+					return ret;
 				}
 			}
@@ -163,6 +164,7 @@
 				for (pos = 0; pos < count; pos++) {
 					if (str_cmp(devs[pos].name, component) == 0) {
+						ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
 						free(devs);
-						return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
+						return ret;
 					}
 				}
@@ -185,6 +187,7 @@
 			for (pos = 0; pos < count; pos++) {
 				if (str_cmp(devs[pos].name, component) == 0) {
+					ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
 					free(devs);
-					return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
+					return ret;
 				}
 			}
@@ -275,5 +278,4 @@
 				fibril_mutex_unlock(&devices_mutex);
 
-				free(dev);
 				return ENOENT;
 			}
@@ -465,10 +467,10 @@
 	    0, NULL);
 	if (retval != EOK) {
-		ipc_answer_0(rid, retval);
+		async_answer_0(rid, retval);
 		return;
 	}
 	
 	free(opts);
-	ipc_answer_3(rid, EOK, 0, 0, 0);
+	async_answer_3(rid, EOK, 0, 0, 0);
 }
 
@@ -480,5 +482,5 @@
 void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_answer_0(rid, ENOTSUP);
+	async_answer_0(rid, ENOTSUP);
 }
 
@@ -513,6 +515,6 @@
 		size_t size;
 		if (!async_data_read_receive(&callid, &size)) {
-			ipc_answer_0(callid, EINVAL);
-			ipc_answer_0(rid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			async_answer_0(rid, EINVAL);
 			return;
 		}
@@ -535,5 +537,5 @@
 			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
 			free(desc);
-			ipc_answer_1(rid, EOK, 1);
+			async_answer_1(rid, EOK, 1);
 			return;
 		}
@@ -550,5 +552,5 @@
 				async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
 				free(desc);
-				ipc_answer_1(rid, EOK, 1);
+				async_answer_1(rid, EOK, 1);
 				return;
 			}
@@ -557,6 +559,6 @@
 		}
 		
-		ipc_answer_0(callid, ENOENT);
-		ipc_answer_1(rid, ENOENT, 0);
+		async_answer_0(callid, ENOENT);
+		async_answer_1(rid, ENOENT, 0);
 		return;
 	}
@@ -569,6 +571,6 @@
 		size_t size;
 		if (!async_data_read_receive(&callid, &size)) {
-			ipc_answer_0(callid, EINVAL);
-			ipc_answer_0(rid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			async_answer_0(rid, EINVAL);
 			return;
 		}
@@ -580,11 +582,11 @@
 			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
 			free(desc);
-			ipc_answer_1(rid, EOK, 1);
+			async_answer_1(rid, EOK, 1);
 			return;
 		}
 		
 		free(desc);
-		ipc_answer_0(callid, ENOENT);
-		ipc_answer_1(rid, ENOENT, 0);
+		async_answer_0(callid, ENOENT);
+		async_answer_1(rid, ENOENT, 0);
 		return;
 	}
@@ -601,5 +603,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(rid, ENOENT);
+			async_answer_0(rid, ENOENT);
 			return;
 		}
@@ -611,6 +613,6 @@
 		if (!async_data_read_receive(&callid, NULL)) {
 			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(callid, EINVAL);
-			ipc_answer_0(rid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			async_answer_0(rid, EINVAL);
 			return;
 		}
@@ -623,5 +625,5 @@
 		
 		/* Forward the IPC_M_DATA_READ request to the driver */
-		ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+		async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 		fibril_mutex_unlock(&devices_mutex);
 		
@@ -632,9 +634,9 @@
 		
 		/* Driver reply is the final result of the whole operation */
-		ipc_answer_1(rid, rc, bytes);
-		return;
-	}
-	
-	ipc_answer_0(rid, ENOENT);
+		async_answer_1(rid, rc, bytes);
+		return;
+	}
+	
+	async_answer_0(rid, ENOENT);
 }
 
@@ -643,5 +645,5 @@
 	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
 	if (index == 0) {
-		ipc_answer_0(rid, ENOTSUP);
+		async_answer_0(rid, ENOTSUP);
 		return;
 	}
@@ -651,5 +653,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		ipc_answer_0(rid, ENOTSUP);
+		async_answer_0(rid, ENOTSUP);
 		return;
 	}
@@ -665,5 +667,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(rid, ENOENT);
+			async_answer_0(rid, ENOENT);
 			return;
 		}
@@ -675,6 +677,6 @@
 		if (!async_data_write_receive(&callid, NULL)) {
 			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(callid, EINVAL);
-			ipc_answer_0(rid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			async_answer_0(rid, EINVAL);
 			return;
 		}
@@ -687,5 +689,5 @@
 		
 		/* Forward the IPC_M_DATA_WRITE request to the driver */
-		ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+		async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 		
 		fibril_mutex_unlock(&devices_mutex);
@@ -697,14 +699,14 @@
 		
 		/* Driver reply is the final result of the whole operation */
-		ipc_answer_1(rid, rc, bytes);
-		return;
-	}
-	
-	ipc_answer_0(rid, ENOENT);
+		async_answer_1(rid, rc, bytes);
+		return;
+	}
+	
+	async_answer_0(rid, ENOENT);
 }
 
 void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_answer_0(rid, ENOTSUP);
+	async_answer_0(rid, ENOTSUP);
 }
 
@@ -714,5 +716,5 @@
 	
 	if (index == 0) {
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		return;
 	}
@@ -722,5 +724,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		return;
 	}
@@ -735,5 +737,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(rid, ENOENT);
+			async_answer_0(rid, ENOENT);
 			return;
 		}
@@ -744,5 +746,5 @@
 		
 		if (dev->refcount == 0) {
-			ipc_hangup(dev->phone);
+			async_hangup(dev->phone);
 			hash_table_remove(&devices, key, DEVICES_KEYS);
 		}
@@ -750,9 +752,9 @@
 		fibril_mutex_unlock(&devices_mutex);
 		
-		ipc_answer_0(rid, EOK);
-		return;
-	}
-	
-	ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, EOK);
+		return;
+	}
+	
+	async_answer_0(rid, ENOENT);
 }
 
@@ -762,5 +764,5 @@
 	
 	if (index == 0) {
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		return;
 	}
@@ -770,5 +772,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		return;
 	}
@@ -783,5 +785,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(rid, ENOENT);
+			async_answer_0(rid, ENOENT);
 			return;
 		}
@@ -802,14 +804,14 @@
 		
 		/* Driver reply is the final result of the whole operation */
-		ipc_answer_0(rid, rc);
-		return;
-	}
-	
-	ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, rc);
+		return;
+	}
+	
+	async_answer_0(rid, ENOENT);
 }
 
 void devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_answer_0(rid, ENOTSUP);
+	async_answer_0(rid, ENOTSUP);
 }
 
Index: uspace/srv/fs/devfs/devfs_ops.h
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/fs/devfs/devfs_ops.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,5 +34,5 @@
 #define DEVFS_DEVFS_OPS_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 #include <bool.h>
 
Index: uspace/srv/fs/fat/fat.c
===================================================================
--- uspace/srv/fs/fat/fat.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/fs/fat/fat.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,6 +38,6 @@
 
 #include "fat.h"
-#include <ipc/ipc.h>
 #include <ipc/services.h>
+#include <ipc/ns.h>
 #include <async.h>
 #include <errno.h>
@@ -84,5 +84,5 @@
 		 * created by IPC_M_CONNECT_TO_ME.
 		 */
-		ipc_answer_0(iid, EOK);
+		async_answer_0(iid, EOK);
 	}
 	
@@ -136,5 +136,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOTSUP);
+			async_answer_0(callid, ENOTSUP);
 			break;
 		}
@@ -153,5 +153,5 @@
 		goto err;
 
-	vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
+	vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
 	if (vfs_phone < EOK) {
 		printf(NAME ": failed to connect to VFS\n");
Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/fs/fat/fat.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,5 +35,4 @@
 
 #include "fat_fat.h"
-#include <ipc/ipc.h>
 #include <fibril_synch.h>
 #include <libfs.h>
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -42,5 +42,4 @@
 #include <libfs.h>
 #include <libblock.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/devmap.h>
@@ -955,5 +954,5 @@
 	
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -970,5 +969,5 @@
 	rc = block_init(devmap_handle, BS_SIZE);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -978,5 +977,5 @@
 	if (rc != EOK) {
 		block_fini(devmap_handle);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -987,5 +986,5 @@
 	if (BPS(bs) != BS_SIZE) {
 		block_fini(devmap_handle);
-		ipc_answer_0(rid, ENOTSUP);
+		async_answer_0(rid, ENOTSUP);
 		return;
 	}
@@ -995,5 +994,5 @@
 	if (rc != EOK) {
 		block_fini(devmap_handle);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1004,5 +1003,5 @@
 		(void) block_cache_fini(devmap_handle);
 		block_fini(devmap_handle);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1012,5 +1011,5 @@
 		(void) block_cache_fini(devmap_handle);
 		block_fini(devmap_handle);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1022,5 +1021,5 @@
 		block_fini(devmap_handle);
 		fat_idx_fini_by_devmap_handle(devmap_handle);
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		return;
 	}
@@ -1032,5 +1031,5 @@
 		block_fini(devmap_handle);
 		fat_idx_fini_by_devmap_handle(devmap_handle);
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		return;
 	}
@@ -1044,5 +1043,5 @@
 		block_fini(devmap_handle);
 		fat_idx_fini_by_devmap_handle(devmap_handle);
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		return;
 	}
@@ -1062,5 +1061,5 @@
 	fibril_mutex_unlock(&ridxp->lock);
 
-	ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
+	async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
 }
 
@@ -1079,5 +1078,5 @@
 	rc = fat_root_get(&fn, devmap_handle);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1090,5 +1089,5 @@
 	if (nodep->refcnt != 2) {
 		(void) fat_node_put(fn);
-		ipc_answer_0(rid, EBUSY);
+		async_answer_0(rid, EBUSY);
 		return;
 	}
@@ -1110,5 +1109,5 @@
 	block_fini(devmap_handle);
 
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
@@ -1138,9 +1137,9 @@
 	rc = fat_node_get(&fn, devmap_handle, index);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
 	if (!fn) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -1151,6 +1150,6 @@
 	if (!async_data_read_receive(&callid, &len)) {
 		fat_node_put(fn);
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -1175,6 +1174,6 @@
 			if (rc != EOK) {
 				fat_node_put(fn);
-				ipc_answer_0(callid, rc);
-				ipc_answer_0(rid, rc);
+				async_answer_0(callid, rc);
+				async_answer_0(rid, rc);
 				return;
 			}
@@ -1184,5 +1183,5 @@
 			if (rc != EOK) {
 				fat_node_put(fn);
-				ipc_answer_0(rid, rc);
+				async_answer_0(rid, rc);
 				return;
 			}
@@ -1241,12 +1240,12 @@
 miss:
 		rc = fat_node_put(fn);
-		ipc_answer_0(callid, rc != EOK ? rc : ENOENT);
-		ipc_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
+		async_answer_0(callid, rc != EOK ? rc : ENOENT);
+		async_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
 		return;
 
 err:
 		(void) fat_node_put(fn);
-		ipc_answer_0(callid, rc);
-		ipc_answer_0(rid, rc);
+		async_answer_0(callid, rc);
+		async_answer_0(rid, rc);
 		return;
 
@@ -1257,5 +1256,5 @@
 
 	rc = fat_node_put(fn);
-	ipc_answer_1(rid, rc, (sysarg_t)bytes);
+	async_answer_1(rid, rc, (sysarg_t)bytes);
 }
 
@@ -1277,9 +1276,9 @@
 	rc = fat_node_get(&fn, devmap_handle, index);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
 	if (!fn) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -1290,6 +1289,6 @@
 	if (!async_data_write_receive(&callid, &len)) {
 		(void) fat_node_put(fn);
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -1319,6 +1318,6 @@
 		if (rc != EOK) {
 			(void) fat_node_put(fn);
-			ipc_answer_0(callid, rc);
-			ipc_answer_0(rid, rc);
+			async_answer_0(callid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -1326,6 +1325,6 @@
 		if (rc != EOK) {
 			(void) fat_node_put(fn);
-			ipc_answer_0(callid, rc);
-			ipc_answer_0(rid, rc);
+			async_answer_0(callid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -1336,5 +1335,5 @@
 		if (rc != EOK) {
 			(void) fat_node_put(fn);
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -1345,5 +1344,5 @@
 		size = nodep->size;
 		rc = fat_node_put(fn);
-		ipc_answer_2(rid, rc, bytes, nodep->size);
+		async_answer_2(rid, rc, bytes, nodep->size);
 		return;
 	} else {
@@ -1361,6 +1360,6 @@
 			/* could not allocate a chain of nclsts clusters */
 			(void) fat_node_put(fn);
-			ipc_answer_0(callid, rc);
-			ipc_answer_0(rid, rc);
+			async_answer_0(callid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -1370,6 +1369,6 @@
 			(void) fat_free_clusters(bs, devmap_handle, mcl);
 			(void) fat_node_put(fn);
-			ipc_answer_0(callid, rc);
-			ipc_answer_0(rid, rc);
+			async_answer_0(callid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -1379,6 +1378,6 @@
 			(void) fat_free_clusters(bs, devmap_handle, mcl);
 			(void) fat_node_put(fn);
-			ipc_answer_0(callid, rc);
-			ipc_answer_0(rid, rc);
+			async_answer_0(callid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -1390,5 +1389,5 @@
 			(void) fat_free_clusters(bs, devmap_handle, mcl);
 			(void) fat_node_put(fn);
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -1401,5 +1400,5 @@
 			(void) fat_free_clusters(bs, devmap_handle, mcl);
 			(void) fat_node_put(fn);
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -1407,5 +1406,5 @@
 		nodep->dirty = true;		/* need to sync node */
 		rc = fat_node_put(fn);
-		ipc_answer_2(rid, rc, bytes, size);
+		async_answer_2(rid, rc, bytes, size);
 		return;
 	}
@@ -1425,9 +1424,9 @@
 	rc = fat_node_get(&fn, devmap_handle, index);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
 	if (!fn) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -1475,5 +1474,5 @@
 out:
 	fat_node_put(fn);
-	ipc_answer_0(rid, rc);
+	async_answer_0(rid, rc);
 	return;
 }
@@ -1481,5 +1480,5 @@
 void fat_close(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
@@ -1493,14 +1492,14 @@
 	rc = fat_node_get(&fn, devmap_handle, index);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
 	if (!fn) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
 
 	rc = fat_destroy_node(fn);
-	ipc_answer_0(rid, rc);
+	async_answer_0(rid, rc);
 }
 
@@ -1523,9 +1522,9 @@
 	int rc = fat_node_get(&fn, devmap_handle, index);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
 	if (!fn) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -1537,5 +1536,5 @@
 	
 	fat_node_put(fn);
-	ipc_answer_0(rid, rc);
+	async_answer_0(rid, rc);
 }
 
Index: uspace/srv/fs/tmpfs/tmpfs.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/fs/tmpfs/tmpfs.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -42,6 +42,6 @@
 
 #include "tmpfs.h"
-#include <ipc/ipc.h>
 #include <ipc/services.h>
+#include <ipc/ns.h>
 #include <async.h>
 #include <errno.h>
@@ -90,5 +90,5 @@
 		 * created by IPC_M_CONNECT_TO_ME.
 		 */
-		ipc_answer_0(iid, EOK);
+		async_answer_0(iid, EOK);
 	}
 	
@@ -142,5 +142,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOTSUP);
+			async_answer_0(callid, ENOTSUP);
 			break;
 		}
@@ -157,5 +157,5 @@
 	}
 
-	int vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
+	int vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
 	if (vfs_phone < EOK) {
 		printf(NAME ": Unable to connect to VFS\n");
Index: uspace/srv/fs/tmpfs/tmpfs.h
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,5 +34,4 @@
 #define TMPFS_TMPFS_H_
 
-#include <ipc/ipc.h>
 #include <libfs.h>
 #include <atomic.h>
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
 #include "tmpfs.h"
 #include "../../vfs/vfs.h"
-#include <ipc/ipc.h>
 #include <macros.h>
 #include <stdint.h>
@@ -450,5 +449,5 @@
 	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -459,5 +458,5 @@
 		(void) tmpfs_node_put(rootfn);
 		free(opts);
-		ipc_answer_0(rid, EEXIST);
+		async_answer_0(rid, EEXIST);
 		return;
 	}
@@ -466,5 +465,5 @@
 	if (!tmpfs_instance_init(devmap_handle)) {
 		free(opts);
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		return;
 	}
@@ -475,10 +474,10 @@
 	if (str_cmp(opts, "restore") == 0) {
 		if (tmpfs_restore(devmap_handle))
-			ipc_answer_3(rid, EOK, rootp->index, rootp->size,
+			async_answer_3(rid, EOK, rootp->index, rootp->size,
 			    rootp->lnkcnt);
 		else
-			ipc_answer_0(rid, ELIMIT);
+			async_answer_0(rid, ELIMIT);
 	} else {
-		ipc_answer_3(rid, EOK, rootp->index, rootp->size,
+		async_answer_3(rid, EOK, rootp->index, rootp->size,
 		    rootp->lnkcnt);
 	}
@@ -496,5 +495,5 @@
 
 	tmpfs_instance_done(devmap_handle);
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
@@ -526,5 +525,5 @@
 	hlp = hash_table_find(&nodes, key);
 	if (!hlp) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -538,6 +537,6 @@
 	size_t size;
 	if (!async_data_read_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -566,6 +565,6 @@
 
 		if (lnk == &nodep->cs_head) {
-			ipc_answer_0(callid, ENOENT);
-			ipc_answer_1(rid, ENOENT, 0);
+			async_answer_0(callid, ENOENT);
+			async_answer_1(rid, ENOENT, 0);
 			return;
 		}
@@ -581,5 +580,5 @@
 	 * Answer the VFS_READ call.
 	 */
-	ipc_answer_1(rid, EOK, bytes);
+	async_answer_1(rid, EOK, bytes);
 }
 
@@ -601,5 +600,5 @@
 	hlp = hash_table_find(&nodes, key);
 	if (!hlp) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -613,6 +612,6 @@
 	size_t size;
 	if (!async_data_write_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);	
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(callid, EINVAL);	
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -624,5 +623,5 @@
 		/* The file size is not changing. */
 		(void) async_data_write_finalize(callid, nodep->data + pos, size);
-		ipc_answer_2(rid, EOK, size, nodep->size);
+		async_answer_2(rid, EOK, size, nodep->size);
 		return;
 	}
@@ -637,6 +636,6 @@
 	void *newdata = realloc(nodep->data, nodep->size + delta);
 	if (!newdata) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_2(rid, EOK, 0, nodep->size);
+		async_answer_0(callid, ENOMEM);
+		async_answer_2(rid, EOK, 0, nodep->size);
 		return;
 	}
@@ -646,5 +645,5 @@
 	nodep->data = newdata;
 	(void) async_data_write_finalize(callid, nodep->data + pos, size);
-	ipc_answer_2(rid, EOK, size, nodep->size);
+	async_answer_2(rid, EOK, size, nodep->size);
 }
 
@@ -665,5 +664,5 @@
 	link_t *hlp = hash_table_find(&nodes, key);
 	if (!hlp) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -672,10 +671,10 @@
 	
 	if (size == nodep->size) {
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		return;
 	}
 	
 	if (size > SIZE_MAX) {
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		return;
 	}
@@ -683,5 +682,5 @@
 	void *newdata = realloc(nodep->data, size);
 	if (!newdata) {
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		return;
 	}
@@ -694,10 +693,10 @@
 	nodep->size = size;
 	nodep->data = newdata;
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
 void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
@@ -715,5 +714,5 @@
 	hlp = hash_table_find(&nodes, key);
 	if (!hlp) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -721,5 +720,5 @@
 	    nh_link);
 	rc = tmpfs_destroy_node(FS_NODE(nodep));
-	ipc_answer_0(rid, rc);
+	async_answer_0(rid, rc);
 }
 
@@ -740,5 +739,5 @@
 	 * thus the sync operation is a no-op.
 	 */
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
Index: uspace/srv/hid/adb_mouse/adb_dev.c
===================================================================
--- uspace/srv/hid/adb_mouse/adb_dev.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/adb_mouse/adb_dev.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,5 +34,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/adb.h>
 #include <async.h>
@@ -68,12 +67,9 @@
 
 	/* NB: The callback connection is slotted for removal */
-	sysarg_t phonehash;
-	if (ipc_connect_to_me(dev_phone, 0, 0, 0, &phonehash) != 0) {
+	if (async_connect_to_me(dev_phone, 0, 0, 0, adb_dev_events) != 0) {
 		printf(NAME ": Failed to create callback from device\n");
 		return false;
 	}
-
-	async_new_connection(phonehash, 0, NULL, adb_dev_events);
-
+	
 	return 0;
 }
@@ -99,5 +95,5 @@
 			retval = ENOENT;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hid/adb_mouse/adb_mouse.c
===================================================================
--- uspace/srv/hid/adb_mouse/adb_mouse.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/adb_mouse/adb_mouse.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/mouse.h>
 #include <stdio.h>
@@ -98,5 +97,5 @@
 	int retval;
 
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	while (1) {
@@ -105,9 +104,9 @@
 		case IPC_M_PHONE_HUNGUP:
 			if (client_phone != -1) {
-				ipc_hangup(client_phone);
+				async_hangup(client_phone);
 				client_phone = -1;
 			}
 
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case IPC_M_CONNECT_TO_ME:
@@ -122,5 +121,5 @@
 			retval = EINVAL;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hid/char_mouse/char_mouse.c
===================================================================
--- uspace/srv/hid/char_mouse/char_mouse.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/char_mouse/char_mouse.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/mouse.h>
 #include <stdio.h>
@@ -83,5 +82,5 @@
 	int retval;
 
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	while (1) {
@@ -90,9 +89,9 @@
 		case IPC_M_PHONE_HUNGUP:
 			if (client_phone != -1) {
-				ipc_hangup(client_phone);
+				async_hangup(client_phone);
 				client_phone = -1;
 			}
 
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case IPC_M_CONNECT_TO_ME:
@@ -107,5 +106,5 @@
 			retval = EINVAL;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hid/char_mouse/chardev.c
===================================================================
--- uspace/srv/hid/char_mouse/chardev.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/char_mouse/chardev.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,5 +34,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/char.h>
 #include <async.h>
@@ -70,11 +69,8 @@
 
 	/* NB: The callback connection is slotted for removal */
-	sysarg_t phonehash;
-	if (ipc_connect_to_me(dev_phone, 0, 0, 0, &phonehash) != 0) {
+	if (async_connect_to_me(dev_phone, 0, 0, 0, chardev_events) != 0) {
 		printf(NAME ": Failed to create callback from device\n");
 		return false;
 	}
-
-	async_new_connection(phonehash, 0, NULL, chardev_events);
 
 	return 0;
@@ -114,5 +110,5 @@
 			retval = ENOENT;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/console/console.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,5 +34,4 @@
 
 #include <libc.h>
-#include <ipc/ipc.h>
 #include <ipc/kbd.h>
 #include <io/keycode.h>
@@ -40,4 +39,5 @@
 #include <ipc/fb.h>
 #include <ipc/services.h>
+#include <ipc/ns.h>
 #include <errno.h>
 #include <ipc/console.h>
@@ -116,5 +116,5 @@
 static void curs_hide_sync(void)
 {
-	ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 
+	async_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 
 }
 
@@ -131,20 +131,20 @@
 static void screen_yield(void)
 {
-	ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD);
+	async_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
 }
 
 static void screen_reclaim(void)
 {
-	ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
+	async_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
 }
 
 static void kbd_yield(void)
 {
-	ipc_call_sync_0_0(kbd_phone, KBD_YIELD);
+	async_req_0_0(kbd_phone, KBD_YIELD);
 }
 
 static void kbd_reclaim(void)
 {
-	ipc_call_sync_0_0(kbd_phone, KBD_RECLAIM);
+	async_req_0_0(kbd_phone, KBD_RECLAIM);
 }
 
@@ -438,5 +438,5 @@
 			retval = ENOENT;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -474,5 +474,5 @@
 		}
 
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -485,5 +485,5 @@
 	
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -500,5 +500,5 @@
 	
 	gcons_notify_char(cons->index);
-	ipc_answer_1(rid, EOK, size);
+	async_answer_1(rid, EOK, size);
 	
 	free(buf);
@@ -510,6 +510,6 @@
 	size_t size;
 	if (!async_data_read_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -517,6 +517,6 @@
 	char *buf = (char *) malloc(size);
 	if (buf == NULL) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		return;
 	}
@@ -536,5 +536,5 @@
 	if (pos == size) {
 		(void) async_data_read_finalize(callid, buf, size);
-		ipc_answer_1(rid, EOK, size);
+		async_answer_1(rid, EOK, size);
 		free(buf);
 	} else {
@@ -554,5 +554,5 @@
 recheck:
 	if (keybuffer_pop(&cons->keybuffer, &ev)) {
-		ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);
+		async_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);
 	} else {
 		fibril_condvar_wait(&input_cv, &input_mutex);
@@ -580,5 +580,5 @@
 	
 	if (cons == NULL) {
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
@@ -599,5 +599,5 @@
 	
 	/* Accept the connection */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
@@ -659,5 +659,5 @@
 			rc = ccap_fb_to_con(fb_info.color_cap, &arg1);
 			if (rc != EOK) {
-				ipc_answer_0(callid, rc);
+				async_answer_0(callid, rc);
 				continue;
 			}
@@ -703,5 +703,5 @@
 			break;
 		}
-		ipc_answer_3(callid, EOK, arg1, arg2, arg3);
+		async_answer_3(callid, EOK, arg1, arg2, arg3);
 	}
 }
@@ -727,6 +727,7 @@
 	/* NB: The callback connection is slotted for removal */
 	sysarg_t phonehash;
+	sysarg_t taskhash;
 	int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, SERVICE_CONSOLE,
-	    0, 0, NULL, NULL, NULL, NULL, &phonehash);
+	    0, 0, NULL, NULL, NULL, &taskhash, &phonehash);
 	if (rc != EOK) {
 		printf(NAME ": Failed to create callback from input device\n");
@@ -734,5 +735,5 @@
 	}
 	
-	async_new_connection(phonehash, 0, NULL, keyboard_events);
+	async_new_connection(taskhash, phonehash, 0, NULL, keyboard_events);
 
 	printf(NAME ": we got a hit (new keyboard \"%s\").\n", path);
@@ -761,5 +762,5 @@
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
-		ipc_hangup(devmap_phone);
+		async_hangup(devmap_phone);
 		return retval;
 	}
@@ -768,5 +769,5 @@
 
 	if (retval != EOK) {
-		ipc_hangup(devmap_phone);
+		async_hangup(devmap_phone);
 		return retval;
 	}
@@ -774,5 +775,5 @@
 	devmap_handle_t handle = (devmap_handle_t) IPC_GET_ARG1(answer);
 
-	ipc_hangup(devmap_phone);
+	async_hangup(devmap_phone);
 
 	int phone = async_connect_me_to(PHONE_NS,
@@ -784,6 +785,7 @@
 	/* NB: The callback connection is slotted for removal */
 	sysarg_t phonehash;
+	sysarg_t taskhash;
 	int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, SERVICE_CONSOLE,
-	    0, 0, NULL, NULL, NULL, NULL, &phonehash);
+	    0, 0, NULL, NULL, NULL, &taskhash, &phonehash);
 	if (rc != EOK) {
 		printf(NAME ": Failed to create callback from input device\n");
@@ -791,5 +793,5 @@
 	}
 
-	async_new_connection(phonehash, 0, NULL, keyboard_events);
+	async_new_connection(taskhash, phonehash, 0, NULL, keyboard_events);
 
 	printf(NAME ": we got a hit (new keyboard \"/dev/%s\").\n",
@@ -862,6 +864,6 @@
 	}
 	
-	sysarg_t phonehash;
-	if (ipc_connect_to_me(mouse_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
+	if (async_connect_to_me(mouse_phone, SERVICE_CONSOLE, 0, 0, mouse_events)
+	    != 0) {
 		printf(NAME ": Failed to create callback from mouse device\n");
 		mouse_phone = -1;
@@ -869,9 +871,8 @@
 	}
 	
-	async_new_connection(phonehash, 0, NULL, mouse_events);
 skip_mouse:
 	
 	/* Connect to framebuffer driver */
-	fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
+	fb_info.phone = service_connect_blocking(SERVICE_VIDEO, 0, 0);
 	if (fb_info.phone < 0) {
 		printf(NAME ": Failed to connect to video service\n");
@@ -949,8 +950,7 @@
 	
 	/* Receive kernel notifications */
+	async_set_interrupt_received(interrupt_received);
 	if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
 		printf(NAME ": Error registering kconsole notifications\n");
-	
-	async_set_interrupt_received(interrupt_received);
 	
 	/* Start fibril for checking on hot-plugged keyboards. */
Index: uspace/srv/hid/console/gcons.c
===================================================================
--- uspace/srv/hid/console/gcons.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/console/gcons.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,5 +34,4 @@
 
 #include <ipc/fb.h>
-#include <ipc/ipc.h>
 #include <async.h>
 #include <stdio.h>
Index: uspace/srv/hid/fb/ega.c
===================================================================
--- uspace/srv/hid/fb/ega.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/fb/ega.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
 #include <align.h>
 #include <async.h>
-#include <ipc/ipc.h>
 #include <errno.h>
 #include <stdio.h>
@@ -46,5 +45,4 @@
 #include <as.h>
 #include <ipc/fb.h>
-#include <ipc/ipc.h>
 #include <ipc/ns.h>
 #include <ipc/services.h>
@@ -262,5 +260,5 @@
 	
 	if (client_connected) {
-		ipc_answer_0(iid, ELIMIT);
+		async_answer_0(iid, ELIMIT);
 		return;
 	}
@@ -268,5 +266,5 @@
 	/* Accept connection */
 	client_connected = 1;
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
@@ -296,5 +294,5 @@
 		case IPC_M_PHONE_HUNGUP:
 			client_connected = 0;
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			
 			/* Exit thread */
@@ -332,8 +330,8 @@
 			break;
 		case FB_GET_CSIZE:
-			ipc_answer_2(callid, EOK, scr_width, scr_height);
+			async_answer_2(callid, EOK, scr_width, scr_height);
 			continue;
 		case FB_GET_COLOR_CAP:
-			ipc_answer_1(callid, EOK, FB_CCAP_INDEXED);
+			async_answer_1(callid, EOK, FB_CCAP_INDEXED);
 			continue;
 		case FB_CLEAR:
@@ -440,5 +438,5 @@
 			retval = EINVAL;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hid/fb/fb.c
===================================================================
--- uspace/srv/hid/fb/fb.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/fb/fb.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -47,5 +47,4 @@
 #include <as.h>
 #include <ipc/fb.h>
-#include <ipc/ipc.h>
 #include <ipc/ns.h>
 #include <ipc/services.h>
@@ -1089,5 +1088,5 @@
 			void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
 			shm_size = IPC_GET_ARG2(*call);
-			if (ipc_answer_1(callid, EOK, (sysarg_t) dest)) {
+			if (async_answer_1(callid, EOK, (sysarg_t) dest)) {
 				shm_id = 0;
 				return false;
@@ -1166,5 +1165,5 @@
 	
 	if (handled)
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	return handled;
 }
@@ -1445,5 +1444,5 @@
 	}
 	if (handled)
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	return handled;
 }
@@ -1498,5 +1497,5 @@
 	
 	if (handled)
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	return handled;
 	
@@ -1582,5 +1581,5 @@
 	
 	if (client_connected) {
-		ipc_answer_0(iid, ELIMIT);
+		async_answer_0(iid, ELIMIT);
 		return;
 	}
@@ -1588,5 +1587,5 @@
 	/* Accept connection */
 	client_connected = true;
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
@@ -1641,5 +1640,5 @@
 				break;
 			}
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			
 			draw_char(vport, ch, col, row);
@@ -1674,8 +1673,8 @@
 			break;
 		case FB_GET_CSIZE:
-			ipc_answer_2(callid, EOK, vport->cols, vport->rows);
+			async_answer_2(callid, EOK, vport->cols, vport->rows);
 			continue;
 		case FB_GET_COLOR_CAP:
-			ipc_answer_1(callid, EOK, FB_CCAP_RGB);
+			async_answer_1(callid, EOK, FB_CCAP_RGB);
 			continue;
 		case FB_SCROLL:
@@ -1742,5 +1741,5 @@
 			break;
 		case FB_GET_RESOLUTION:
-			ipc_answer_2(callid, EOK, screen.xres, screen.yres);
+			async_answer_2(callid, EOK, screen.xres, screen.yres);
 			continue;
 		case FB_POINTER_MOVE:
@@ -1756,5 +1755,5 @@
 			retval = ENOENT;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hid/fb/main.c
===================================================================
--- uspace/srv/hid/fb/main.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/fb/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,6 +27,6 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
+#include <ipc/ns.h>
 #include <sysinfo.h>
 #include <async.h>
@@ -51,5 +51,5 @@
 	
 	dest = as_get_mappable_page(IPC_GET_ARG2(*call));
-	if (ipc_answer_1(callid, EOK, (sysarg_t) dest) == 0) {
+	if (async_answer_1(callid, EOK, (sysarg_t) dest) == 0) {
 		if (*area)
 			as_area_destroy(*area);
@@ -114,6 +114,5 @@
 		return -1;
 	
-	sysarg_t phonead;
-	if (ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, 0, &phonead) != 0) 
+	if (service_register(SERVICE_VIDEO) != EOK)
 		return -1;
 	
Index: uspace/srv/hid/fb/serial_console.c
===================================================================
--- uspace/srv/hid/fb/serial_console.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/fb/serial_console.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,4 @@
 
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <async.h>
 #include <ipc/fb.h>
@@ -319,10 +318,10 @@
 	
 	if (client_connected) {
-		ipc_answer_0(iid, ELIMIT);
+		async_answer_0(iid, ELIMIT);
 		return;
 	}
 	
 	client_connected = 1;
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	/* Clear the terminal, set scrolling region
@@ -348,5 +347,5 @@
 		case IPC_M_PHONE_HUNGUP:
 			client_connected = 0;
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			
 			/* Exit thread */
@@ -407,8 +406,8 @@
 			break;
 		case FB_GET_CSIZE:
-			ipc_answer_2(callid, EOK, scr_width, scr_height);
+			async_answer_2(callid, EOK, scr_width, scr_height);
 			continue;
 		case FB_GET_COLOR_CAP:
-			ipc_answer_1(callid, EOK, color ? FB_CCAP_INDEXED :
+			async_answer_1(callid, EOK, color ? FB_CCAP_INDEXED :
 			    FB_CCAP_STYLE);
 			continue;
@@ -478,5 +477,5 @@
 			retval = ENOENT;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hid/fb/serial_console.h
===================================================================
--- uspace/srv/hid/fb/serial_console.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/fb/serial_console.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,5 +39,6 @@
 #define FB_SERIAL_CONSOLE_H_
 
-#include <ipc/ipc.h>
+#include <sys/types.h>
+#include <ipc/common.h>
 
 typedef void (*putc_function_t)(char);
Index: uspace/srv/hid/kbd/generic/kbd.c
===================================================================
--- uspace/srv/hid/kbd/generic/kbd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/kbd/generic/kbd.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/kbd.h>
@@ -173,5 +172,5 @@
 	int retval;
 
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	while (1) {
@@ -180,9 +179,9 @@
 		case IPC_M_PHONE_HUNGUP:
 			if (client_phone != -1) {
-				ipc_hangup(client_phone);
+				async_hangup(client_phone);
 				client_phone = -1;
 			}
 			
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case IPC_M_CONNECT_TO_ME:
@@ -205,5 +204,5 @@
 			retval = EINVAL;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}	
 }
@@ -223,8 +222,6 @@
 	
 	if (cir_service) {
-		while (cir_phone < 0) {
-			cir_phone = ipc_connect_me_to_blocking(PHONE_NS, cir_service,
-			    0, 0);
-		}
+		while (cir_phone < 0)
+			cir_phone = service_connect_blocking(cir_service, 0, 0);
 	}
 	
Index: uspace/srv/hid/kbd/port/adb.c
===================================================================
--- uspace/srv/hid/kbd/port/adb.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/kbd/port/adb.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,5 +35,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/adb.h>
 #include <async.h>
@@ -71,11 +70,8 @@
 
 	/* NB: The callback connection is slotted for removal */
-	sysarg_t phonehash;
-	if (ipc_connect_to_me(dev_phone, 0, 0, 0, &phonehash) != 0) {
+	if (async_connect_to_me(dev_phone, 0, 0, 0, kbd_port_events) != 0) {
 		printf(NAME ": Failed to create callback from device\n");
 		return false;
 	}
-
-	async_new_connection(phonehash, 0, NULL, kbd_port_events);
 
 	return 0;
@@ -115,5 +111,5 @@
 			retval = ENOENT;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hid/kbd/port/chardev.c
===================================================================
--- uspace/srv/hid/kbd/port/chardev.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/kbd/port/chardev.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,5 +35,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/char.h>
 #include <async.h>
@@ -91,11 +90,8 @@
 
 	/* NB: The callback connection is slotted for removal */
-	sysarg_t phonehash;
-	if (ipc_connect_to_me(dev_phone, 0, 0, 0, &phonehash) != 0) {
+	if (async_connect_to_me(dev_phone, 0, 0, 0, kbd_port_events) != 0) {
 		printf(NAME ": Failed to create callback from device\n");
 		return -1;
 	}
-
-	async_new_connection(phonehash, 0, NULL, kbd_port_events);
 
 	return 0;
@@ -135,5 +131,5 @@
 			retval = ENOENT;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hid/kbd/port/gxemul.c
===================================================================
--- uspace/srv/hid/kbd/port/gxemul.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/kbd/port/gxemul.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,5 +35,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <async.h>
 #include <sysinfo.h>
@@ -74,5 +73,5 @@
 	async_set_interrupt_received(gxemul_irq_handler);
 	gxemul_cmds[0].addr = (void *) addr;
-	ipc_register_irq(inr, device_assign_devno(), 0, &gxemul_kbd);
+	register_irq(inr, device_assign_devno(), 0, &gxemul_kbd);
 	return 0;
 }
Index: uspace/srv/hid/kbd/port/msim.c
===================================================================
--- uspace/srv/hid/kbd/port/msim.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/kbd/port/msim.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,5 +35,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <async.h>
 #include <sysinfo.h>
@@ -74,5 +73,5 @@
 	msim_cmds[0].addr = (void *) vaddr;
 	async_set_interrupt_received(msim_irq_handler);
-	ipc_register_irq(inr, device_assign_devno(), 0, &msim_kbd);
+	register_irq(inr, device_assign_devno(), 0, &msim_kbd);
 	
 	return 0;
Index: uspace/srv/hid/kbd/port/ns16550.c
===================================================================
--- uspace/srv/hid/kbd/port/ns16550.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/kbd/port/ns16550.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,5 +35,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/irc.h>
 #include <async.h>
@@ -111,5 +110,5 @@
 	
 	async_set_interrupt_received(ns16550_irq_handler);
-	ipc_register_irq(inr, device_assign_devno(), inr, &ns16550_kbd);
+	register_irq(inr, device_assign_devno(), inr, &ns16550_kbd);
 	
 	return pio_enable((void *) ns16550_physical, 8, &vaddr);
Index: uspace/srv/hid/kbd/port/pl050.c
===================================================================
--- uspace/srv/hid/kbd/port/pl050.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/kbd/port/pl050.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,5 +37,4 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
-#include <ipc/ipc.h>
 #include <async.h>
 #include <unistd.h>
@@ -101,5 +100,5 @@
 	
 	async_set_interrupt_received(pl050_irq_handler);
-	ipc_register_irq(inr, device_assign_devno(), 0, &pl050_kbd);
+	register_irq(inr, device_assign_devno(), 0, &pl050_kbd);
 	
 	return 0;
Index: uspace/srv/hid/kbd/port/z8530.c
===================================================================
--- uspace/srv/hid/kbd/port/z8530.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/kbd/port/z8530.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,5 +35,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/irc.h>
 #include <async.h>
@@ -99,5 +98,5 @@
 	
 	async_set_interrupt_received(z8530_irq_handler);
-	ipc_register_irq(inr, device_assign_devno(), inr, &z8530_kbd);
+	register_irq(inr, device_assign_devno(), inr, &z8530_kbd);
 	
 	return 0;
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -42,5 +42,4 @@
 #include <io/console.h>
 #include <vfs/vfs.h>
-#include <ipc/ipc.h>
 #include <ipc/mouse.h>
 #include <async.h>
@@ -140,5 +139,5 @@
 
 	async_set_interrupt_received(s3c24xx_ts_irq_handler);
-	ipc_register_irq(inr, device_assign_devno(), 0, &ts_irq_code);
+	register_irq(inr, device_assign_devno(), 0, &ts_irq_code);
 
 	s3c24xx_ts_wait_for_int_mode(ts, updn_down);
@@ -377,5 +376,5 @@
 	int retval;
 
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	while (1) {
@@ -384,9 +383,9 @@
 		case IPC_M_PHONE_HUNGUP:
 			if (ts->client_phone != -1) {
-				ipc_hangup(ts->client_phone);
+				async_hangup(ts->client_phone);
 				ts->client_phone = -1;
 			}
 
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case IPC_M_CONNECT_TO_ME:
@@ -401,5 +400,5 @@
 			retval = EINVAL;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -209,10 +209,10 @@
 
 	if (dev_addr < 0) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
 
 	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	while (1) {
@@ -222,5 +222,5 @@
 		case IPC_M_PHONE_HUNGUP:
 			/* The other side has hung up. */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case IPC_M_CONNECT_TO_ME:
@@ -245,5 +245,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -276,5 +276,5 @@
 	cuda_irq_code.cmds[0].addr = (void *) &((cuda_t *) instance->cuda_kernel)->ifr;
 	async_set_interrupt_received(cuda_irq_handler);
-	ipc_register_irq(10, device_assign_devno(), 0, &cuda_irq_code);
+	register_irq(10, device_assign_devno(), 0, &cuda_irq_code);
 
 	/* Enable SR interrupt. */
Index: uspace/srv/hw/char/i8042/i8042.c
===================================================================
--- uspace/srv/hw/char/i8042/i8042.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hw/char/i8042/i8042.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,5 +40,4 @@
 #include <libarch/ddi.h>
 #include <devmap.h>
-#include <ipc/ipc.h>
 #include <async.h>
 #include <unistd.h>
@@ -199,6 +198,6 @@
 	i8042_kbd.cmds[0].addr = (void *) &((i8042_t *) i8042_kernel)->status;
 	i8042_kbd.cmds[3].addr = (void *) &((i8042_t *) i8042_kernel)->data;
-	ipc_register_irq(inr_a, device_assign_devno(), 0, &i8042_kbd);
-	ipc_register_irq(inr_b, device_assign_devno(), 0, &i8042_kbd);
+	register_irq(inr_a, device_assign_devno(), 0, &i8042_kbd);
+	register_irq(inr_b, device_assign_devno(), 0, &i8042_kbd);
 	printf("%s: registered for interrupts %" PRIun " and %" PRIun "\n",
 	    NAME, inr_a, inr_b);
@@ -236,10 +235,10 @@
 
 	if (dev_id < 0) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
 
 	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	printf(NAME ": accepted connection\n");
@@ -251,5 +250,5 @@
 		case IPC_M_PHONE_HUNGUP:
 			/* The other side has hung up. */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case IPC_M_CONNECT_TO_ME:
@@ -272,5 +271,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
Index: uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c
===================================================================
--- uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,5 +40,4 @@
 #include <libarch/ddi.h>
 #include <devmap.h>
-#include <ipc/ipc.h>
 #include <ipc/char.h>
 #include <async.h>
@@ -119,5 +118,5 @@
 
 	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	while (1) {
@@ -127,5 +126,5 @@
 		case IPC_M_PHONE_HUNGUP:
 			/* The other side has hung up. */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		case IPC_M_CONNECT_TO_ME:
@@ -144,5 +143,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -191,5 +190,5 @@
 	async_set_interrupt_received(s3c24xx_uart_irq_handler);
 
-	ipc_register_irq(inr, device_assign_devno(), 0, &uart_irq_code);
+	register_irq(inr, device_assign_devno(), 0, &uart_irq_code);
 
 	/* Enable FIFO, Tx trigger level: empty, Rx trigger level: 1 byte. */
Index: uspace/srv/hw/irc/apic/apic.c
===================================================================
--- uspace/srv/hw/irc/apic/apic.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hw/irc/apic/apic.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/irc.h>
@@ -75,5 +74,5 @@
 	 * Answer the first IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
@@ -82,12 +81,12 @@
 		switch (IPC_GET_IMETHOD(call)) {
 		case IRC_ENABLE_INTERRUPT:
-			ipc_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call)));
+			async_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call)));
 			break;
 		case IRC_CLEAR_INTERRUPT:
 			/* Noop */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			break;
 		default:
-			ipc_answer_0(callid, EINVAL);
+			async_answer_0(callid, EINVAL);
 			break;
 		}
@@ -108,6 +107,5 @@
 	
 	async_set_client_connection(apic_connection);
-	sysarg_t phonead;
-	ipc_connect_to_me(PHONE_NS, SERVICE_APIC, 0, 0, &phonead);
+	service_register(SERVICE_APIC);
 	
 	return true;
Index: uspace/srv/hw/irc/fhc/fhc.c
===================================================================
--- uspace/srv/hw/irc/fhc/fhc.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hw/irc/fhc/fhc.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -29,12 +29,11 @@
 /** @addtogroup fhc
  * @{
- */ 
+ */
 
 /**
- * @file	fhc.c
- * @brief	FHC bus controller driver.
+ * @file fhc.c
+ * @brief FHC bus controller driver.
  */
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/irc.h>
@@ -76,5 +75,5 @@
 	 * Answer the first IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	while (1) {
@@ -85,5 +84,5 @@
 		case IRC_ENABLE_INTERRUPT:
 			/* Noop */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			break;
 		case IRC_CLEAR_INTERRUPT:
@@ -92,13 +91,13 @@
 			case FHC_UART_INR:
 				fhc_uart_virt[FHC_UART_ICLR] = 0;
-				ipc_answer_0(callid, EOK);
+				async_answer_0(callid, EOK);
 				break;
 			default:
-				ipc_answer_0(callid, ENOTSUP);
+				async_answer_0(callid, ENOTSUP);
 				break;
 			}
 			break;
 		default:
-			ipc_answer_0(callid, EINVAL);
+			async_answer_0(callid, EINVAL);
 			break;
 		}
@@ -137,6 +136,5 @@
 	
 	async_set_client_connection(fhc_connection);
-	sysarg_t phonead;
-	ipc_connect_to_me(PHONE_NS, SERVICE_FHC, 0, 0, &phonead);
+	service_register(SERVICE_FHC);
 	
 	return true;
Index: uspace/srv/hw/irc/i8259/i8259.c
===================================================================
--- uspace/srv/hw/irc/i8259/i8259.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hw/irc/i8259/i8259.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/irc.h>
@@ -109,5 +108,5 @@
 	 * Answer the first IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
@@ -116,12 +115,12 @@
 		switch (IPC_GET_IMETHOD(call)) {
 		case IRC_ENABLE_INTERRUPT:
-			ipc_answer_0(callid, pic_enable_irq(IPC_GET_ARG1(call)));
+			async_answer_0(callid, pic_enable_irq(IPC_GET_ARG1(call)));
 			break;
 		case IRC_CLEAR_INTERRUPT:
 			/* Noop */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			break;
 		default:
-			ipc_answer_0(callid, EINVAL);
+			async_answer_0(callid, EINVAL);
 			break;
 		}
@@ -150,6 +149,5 @@
 	
 	async_set_client_connection(i8259_connection);
-	sysarg_t phonead;
-	ipc_connect_to_me(PHONE_NS, SERVICE_I8259, 0, 0, &phonead);
+	service_register(SERVICE_I8259);
 	
 	return true;
Index: uspace/srv/hw/irc/obio/obio.c
===================================================================
--- uspace/srv/hw/irc/obio/obio.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hw/irc/obio/obio.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,11 +27,11 @@
  */
 
-/** @addtogroup obio 
+/** @addtogroup obio
  * @{
- */ 
+ */
 
 /**
- * @file	obio.c
- * @brief	OBIO driver.
+ * @file obio.c
+ * @brief OBIO driver.
  *
  * OBIO is a short for on-board I/O. On UltraSPARC IIi and systems with U2P,
@@ -42,5 +42,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/irc.h>
@@ -86,5 +85,5 @@
 	 * Answer the first IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	while (1) {
@@ -95,13 +94,13 @@
 		case IRC_ENABLE_INTERRUPT:
 			/* Noop */
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			break;
 		case IRC_CLEAR_INTERRUPT:
 			inr = IPC_GET_ARG1(call);
 			base_virt[OBIO_CIR(inr & INO_MASK)] = 0;
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			break;
 		default:
-			ipc_answer_0(callid, EINVAL);
+			async_answer_0(callid, EINVAL);
 			break;
 		}
@@ -138,6 +137,5 @@
 	
 	async_set_client_connection(obio_connection);
-	sysarg_t phonead;
-	ipc_connect_to_me(PHONE_NS, SERVICE_OBIO, 0, 0, &phonead);
+	service_register(SERVICE_OBIO);
 	
 	return true;
Index: uspace/srv/hw/netif/ne2000/ne2000.c
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/hw/netif/ne2000/ne2000.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -43,6 +43,6 @@
 #include <malloc.h>
 #include <sysinfo.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
+#include <ipc/ns.h>
 #include <ipc/irc.h>
 #include <net/modules.h>
@@ -316,5 +316,5 @@
 		ne2k_cmds[5].addr = ne2k->port + DP_TSR;
 		
-		int rc = ipc_register_irq(ne2k->irq, device->device_id,
+		int rc = register_irq(ne2k->irq, device->device_id,
 		    device->device_id, &ne2k_code);
 		if (rc != EOK)
@@ -323,5 +323,5 @@
 		rc = ne2k_up(ne2k);
 		if (rc != EOK) {
-			ipc_unregister_irq(ne2k->irq, device->device_id);
+			unregister_irq(ne2k->irq, device->device_id);
 			return rc;
 		}
@@ -342,5 +342,5 @@
 		
 		ne2k_down(ne2k);
-		ipc_unregister_irq(ne2k->irq, device->device_id);
+		unregister_irq(ne2k->irq, device->device_id);
 		change_state(device, NETIF_STOPPED);
 	}
@@ -389,14 +389,11 @@
 	
 	if (irc_service) {
-		while (irc_phone < 0) {
-			irc_phone = ipc_connect_me_to_blocking(PHONE_NS, irc_service,
-			    0, 0);
-		}
+		while (irc_phone < 0)
+			irc_phone = service_connect_blocking(irc_service, 0, 0);
 	}
 	
 	async_set_interrupt_received(irq_handler);
 	
-	sysarg_t phonehash;
-	return ipc_connect_to_me(PHONE_NS, SERVICE_NE2000, 0, 0, &phonehash);
+	return async_connect_to_me(PHONE_NS, SERVICE_NE2000, 0, 0, NULL);
 }
 
Index: uspace/srv/loader/arch/abs32le/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/abs32le/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/loader/arch/abs32le/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -3,4 +3,5 @@
  * is the base address and the special interp section.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -54,8 +55,4 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	
-	_heap = .;
-	
 	/DISCARD/ : {
 		*(*);
Index: uspace/srv/loader/arch/amd64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/amd64/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/loader/arch/amd64/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,2 +1,7 @@
+/*
+ * The difference from _link.ld.in for regular statically-linked apps
+ * is the base address and the special interp section.
+ */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -6,4 +11,5 @@
 	text PT_LOAD FLAGS(5);
 	data PT_LOAD FLAGS(6);
+	debug PT_NOTE;
 }
 
@@ -11,7 +17,7 @@
 	.interp : {
 		*(.interp);
-	} : interp
-
-	/* . = 0x0000700000001000;*/
+	} :interp
+	
+	/* . = 0x0000700000001000; */
 	. = 0x70001000;
 	
@@ -19,4 +25,5 @@
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
@@ -27,4 +34,5 @@
 		*(.data);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -32,4 +40,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -37,16 +46,27 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(COMMON);
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x1000);
-	_heap = .;
+	
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); } :debug
+	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
+	.debug_aranges 0 : { *(.debug_aranges); } :debug
+	.debug_info 0 : { *(.debug_info); } :debug
+	.debug_line 0 : { *(.debug_line); } :debug
+	.debug_loc 0 : { *(.debug_loc); } :debug
+	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
+	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
+	.debug_ranges 0 : { *(.debug_ranges); } :debug
+	.debug_str 0 : { *(.debug_str); } :debug
+#endif
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/arch/arm32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/arm32/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/loader/arch/arm32/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -3,4 +3,5 @@
  * is the base address.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -16,13 +17,14 @@
 		*(.interp);
 	} : interp
-
+	
 	. = 0x70001000;
-
+	
 	.init ALIGN(0x1000): SUBALIGN(0x1000) {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
-        *(.rodata*);
+		*(.rodata*);
 	} :text
 	
@@ -32,4 +34,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -37,4 +40,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -42,18 +46,16 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
 		*(.scommon);
-        *(COMMON);
-        *(.bss);
+		*(COMMON);
+		*(.bss);
 	} :data
-	
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/arch/ia32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia32/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/loader/arch/ia32/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -3,4 +3,5 @@
  * is the base address and the special interp section.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -10,4 +11,5 @@
 	text PT_LOAD FILEHDR PHDRS FLAGS(5);
 	data PT_LOAD FLAGS(6);
+	debug PT_NOTE;
 }
 
@@ -52,7 +54,16 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	
-	_heap = .;
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); } :debug
+	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
+	.debug_aranges 0 : { *(.debug_aranges); } :debug
+	.debug_info 0 : { *(.debug_info); } :debug
+	.debug_line 0 : { *(.debug_line); } :debug
+	.debug_loc 0 : { *(.debug_loc); } :debug
+	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
+	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
+	.debug_ranges 0 : { *(.debug_ranges); } :debug
+	.debug_str 0 : { *(.debug_str); } :debug
+#endif
 	
 	/DISCARD/ : {
Index: uspace/srv/loader/arch/ia64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia64/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/loader/arch/ia64/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -12,22 +12,24 @@
 		*(.interp);
 	} :interp
-
+	
 	/* On Itanium code sections must be aligned to 16 bytes. */
 	. = ALIGN(0x800000000 + SIZEOF_HEADERS, 16);
-
+	
 	.init : {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		_gp = .;
 		*(.got*);
-	} :data	
+	} :data
+	
 	.data : {
 		*(.opd);
@@ -35,4 +37,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -40,4 +43,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -45,5 +49,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
@@ -52,10 +58,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
- 
+	
 	/DISCARD/ : {
 		*(*);
-        }
+	}
 }
Index: uspace/srv/loader/arch/mips32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/mips32/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/loader/arch/mips32/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -3,4 +3,5 @@
  * is the base address.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -16,5 +17,5 @@
 		*(.interp);
 	} :interp
-
+	
 	. = 0x70004000;
 	
@@ -22,19 +23,22 @@
 		*(.init);
 	} :text
+	
 	.text : {
-	        *(.text);
+		*(.text);
 		*(.rodata*);
 	} :text
-
+	
+	. = . + 0x4000;
+	
 	.data : {
 		*(.data);
 		*(.data.rel*);
 	} :data
-
+	
 	.got : {
 		_gp = .;
 		*(.got);
 	} :data
-
+	
 	.tdata : {
 		_tdata_start = .;
@@ -42,4 +46,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -47,18 +52,17 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-
+	
 	.sbss : {
 		*(.scommon);
 		*(.sbss);
-	}	
+	}
+	
 	.bss : {
 		*(.bss);
 		*(COMMON);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
-
+	
 	/DISCARD/ : {
 		*(*);
Index: uspace/srv/loader/arch/ppc32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ppc32/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/loader/arch/ppc32/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -3,4 +3,5 @@
  * is the base address.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -16,10 +17,11 @@
 		*(.interp);
 	} :interp
-
+	
 	. = 0x70001000;
-
+	
 	.init ALIGN(0x1000) : SUBALIGN(0x1000) {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
@@ -31,4 +33,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -36,4 +39,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -41,5 +45,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
@@ -47,11 +53,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/arch/sparc64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/sparc64/_link.ld.in	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/loader/arch/sparc64/_link.ld.in	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -12,25 +12,28 @@
 		*(.interp);
 	} :interp
-
+	
 	. = 0x70004000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		 _gp = .;
 		 *(.got*);
 	} :data
+	
 	.data : {
 		*(.data);
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -38,4 +41,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -43,5 +47,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
@@ -49,11 +55,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/elf_load.c
===================================================================
--- uspace/srv/loader/elf_load.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/loader/elf_load.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -109,5 +109,5 @@
 	int fd;
 	int rc;
-
+	
 	fd = open(file_name, O_RDONLY);
 	if (fd < 0) {
@@ -300,4 +300,5 @@
 	case PT_NULL:
 	case PT_PHDR:
+	case PT_NOTE:
 		break;
 	case PT_LOAD:
@@ -310,5 +311,4 @@
 	case PT_DYNAMIC:
 	case PT_SHLIB:
-	case PT_NOTE:
 	case PT_LOPROC:
 	case PT_HIPROC:
@@ -344,5 +344,5 @@
 	seg_ptr = (void *) seg_addr;
 
-	DPRINTF("Load segment at addr %p, size 0x%x\n", seg_addr,
+	DPRINTF("Load segment at addr %p, size 0x%x\n", (void *) seg_addr,
 		entry->p_memsz);
 
@@ -372,6 +372,7 @@
 	mem_sz = entry->p_memsz + (entry->p_vaddr - base);
 
-	DPRINTF("Map to seg_addr=%p-%p.\n", seg_addr,
-	entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
+	DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
+	    (void *) (entry->p_vaddr + bias +
+	    ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
 
 	/*
@@ -386,6 +387,6 @@
 	}
 
-	DPRINTF("as_area_create(%p, 0x%x, %d) -> 0x%lx\n",
-		base + bias, mem_sz, flags, (uintptr_t)a);
+	DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
+	    (void *) (base + bias), mem_sz, flags, (void *) a);
 
 	/*
@@ -464,5 +465,5 @@
 		    (void *)((uint8_t *)entry->sh_addr + elf->bias);
 		DPRINTF("Dynamic section found at %p.\n",
-			(uintptr_t)elf->info->dynamic);
+		    (void *) elf->info->dynamic);
 		break;
 	default:
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/loader/main.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -50,5 +50,4 @@
 #include <fcntl.h>
 #include <sys/types.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/loader.h>
@@ -95,5 +94,5 @@
 
 /** Used to limit number of connections to one. */
-static bool connected;
+static bool connected = false;
 
 static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
@@ -106,6 +105,6 @@
 	
 	if (!async_data_read_receive(&callid, &len)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -115,5 +114,5 @@
 	
 	async_data_read_finalize(callid, &task_id, len);
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
@@ -135,5 +134,5 @@
 	}
 	
-	ipc_answer_0(rid, rc);
+	async_answer_0(rid, rc);
 }
 
@@ -155,5 +154,5 @@
 	}
 	
-	ipc_answer_0(rid, rc);
+	async_answer_0(rid, rc);
 }
 
@@ -188,5 +187,5 @@
 		if (_argv == NULL) {
 			free(buf);
-			ipc_answer_0(rid, ENOMEM);
+			async_answer_0(rid, ENOMEM);
 			return;
 		}
@@ -220,5 +219,5 @@
 	}
 	
-	ipc_answer_0(rid, rc);
+	async_answer_0(rid, rc);
 }
 
@@ -244,5 +243,5 @@
 		if (_filv == NULL) {
 			free(buf);
-			ipc_answer_0(rid, ENOMEM);
+			async_answer_0(rid, ENOMEM);
 			return;
 		}
@@ -271,5 +270,5 @@
 	}
 	
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
@@ -287,5 +286,5 @@
 	if (rc != EE_OK) {
 		DPRINTF("Failed to load executable '%s'.\n", pathname);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return 1;
 	}
@@ -304,5 +303,5 @@
 		/* Statically linked program */
 		is_dyn_linked = false;
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		return 0;
 	}
@@ -312,10 +311,10 @@
 		DPRINTF("Failed to load interpreter '%s.'\n",
 		    prog_info.interp);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return 1;
 	}
 	
 	is_dyn_linked = true;
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 	
 	return 0;
@@ -343,9 +342,9 @@
 		DPRINTF("Entry point: %p\n", interp_info.entry);
 		
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		elf_run(&interp_info, &pcb);
 	} else {
 		/* Statically linked program */
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		elf_run(&prog_info, &pcb);
 	}
@@ -367,5 +366,5 @@
 	/* Already have a connection? */
 	if (connected) {
-		ipc_answer_0(iid, ELIMIT);
+		async_answer_0(iid, ELIMIT);
 		return;
 	}
@@ -374,5 +373,5 @@
 	
 	/* Accept the connection */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	/* Ignore parameters, the connection is already open */
@@ -414,5 +413,5 @@
 			DPRINTF("Responding EINVAL to method %d.\n",
 			    IPC_GET_IMETHOD(call));
-			ipc_answer_0(callid, EINVAL);
+			async_answer_0(callid, EINVAL);
 		}
 	}
@@ -423,23 +422,17 @@
 int main(int argc, char *argv[])
 {
-	sysarg_t phonead;
-	task_id_t id;
-	int rc;
-
-	connected = false;
-
+	/* Set a handler of incomming connections. */
+	async_set_client_connection(ldr_connection);
+	
 	/* Introduce this task to the NS (give it our task ID). */
-	id = task_get_id();
-	rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
+	task_id_t id = task_get_id();
+	int rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
 	if (rc != EOK)
 		return -1;
-
-	/* Set a handler of incomming connections. */
-	async_set_client_connection(ldr_connection);
 	
 	/* Register at naming service. */
-	if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0) 
+	if (service_register(SERVICE_LOAD) != EOK)
 		return -2;
-
+	
 	async_manager();
 	
Index: uspace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/il/arp/arp.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,5 +45,4 @@
 #include <task.h>
 #include <adt/measured_strings.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -428,5 +427,5 @@
 		case NET_IL_DEVICE_STATE:
 			/* Do nothing - keep the cache */
-			ipc_answer_0(iid, (sysarg_t) EOK);
+			async_answer_0(iid, (sysarg_t) EOK);
 			break;
 		
@@ -448,5 +447,5 @@
 				fibril_mutex_unlock(&arp_globals.lock);
 			}
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
@@ -454,9 +453,9 @@
 			rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
 			    IPC_GET_MTU(*icall));
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
 		default:
-			ipc_answer_0(iid, (sysarg_t) ENOTSUP);
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
 		}
 		
Index: uspace/srv/net/il/arp/arp.h
===================================================================
--- uspace/srv/net/il/arp/arp.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/il/arp/arp.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,8 +39,5 @@
 
 #include <fibril_synch.h>
-
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <net/packet.h>
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/il/ip/ip.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,5 +41,4 @@
 #include <stdio.h>
 #include <str.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -67,5 +66,5 @@
 #include <net_checksum.h>
 #include <icmp_client.h>
-#include <icmp_interface.h>
+#include <icmp_remote.h>
 #include <ip_client.h>
 #include <ip_interface.h>
@@ -1596,5 +1595,5 @@
 			rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
 			    IPC_GET_STATE(*icall));
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
@@ -1610,5 +1609,5 @@
 			}
 			
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
@@ -1616,9 +1615,9 @@
 			rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
 			    IPC_GET_MTU(*icall));
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
 		default:
-			ipc_answer_0(iid, (sysarg_t) ENOTSUP);
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
 		}
 		
Index: uspace/srv/net/il/ip/ip.h
===================================================================
--- uspace/srv/net/il/ip/ip.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/il/ip/ip.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,7 +39,5 @@
 
 #include <fibril_synch.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <net/inet.h>
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/net/net.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -47,5 +47,4 @@
 #include <str_error.h>
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -326,5 +325,4 @@
 static int net_module_start(async_client_conn_t client_connection)
 {
-	sysarg_t phonehash;
 	int rc;
 	
@@ -338,5 +336,5 @@
 		goto out;
 	
-	rc = ipc_connect_to_me(PHONE_NS, SERVICE_NETWORKING, 0, 0, &phonehash);
+	rc = async_connect_to_me(PHONE_NS, SERVICE_NETWORKING, 0, 0, NULL);
 	if (rc != EOK)
 		goto out;
@@ -687,5 +685,5 @@
 	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
Index: uspace/srv/net/net/net.h
===================================================================
--- uspace/srv/net/net/net.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/net/net.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -38,6 +38,4 @@
 #ifndef NET_NET_H_
 #define NET_NET_H_
-
-#include <ipc/ipc.h>
 
 #include <net/device.h>
Index: uspace/srv/net/net/net_standalone.c
===================================================================
--- uspace/srv/net/net/net_standalone.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/net/net_standalone.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,5 +40,4 @@
 #include <adt/measured_strings.h>
 #include <adt/module_map.h>
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 #include <errno.h>
Index: uspace/srv/net/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/netif/lo/lo.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -39,9 +39,6 @@
 #include <stdio.h>
 #include <str.h>
-
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/nil.h>
-
 #include <net/modules.h>
 #include <adt/measured_strings.h>
@@ -167,6 +164,5 @@
 int netif_initialize(void)
 {
-	sysarg_t phonehash;
-	return ipc_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, &phonehash);
+	return async_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, NULL);
 }
 
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/nil/eth/eth.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -43,10 +43,7 @@
 #include <str.h>
 #include <errno.h>
-
-#include <ipc/ipc.h>
 #include <ipc/nil.h>
 #include <ipc/net.h>
 #include <ipc/services.h>
-
 #include <net/modules.h>
 #include <net_checksum.h>
@@ -242,5 +239,5 @@
 			nil_device_state_msg_local(0, IPC_GET_DEVICE(*icall),
 			    IPC_GET_STATE(*icall));
-			ipc_answer_0(iid, EOK);
+			async_answer_0(iid, EOK);
 			break;
 		case NET_NIL_RECEIVED:
@@ -251,8 +248,8 @@
 				    IPC_GET_DEVICE(*icall), packet, 0);
 			
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		default:
-			ipc_answer_0(iid, (sysarg_t) ENOTSUP);
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
 		}
 		
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -41,5 +41,4 @@
 #include <stdio.h>
 #include <str.h>
-#include <ipc/ipc.h>
 #include <ipc/nil.h>
 #include <ipc/net.h>
@@ -112,5 +111,5 @@
 			rc = nil_device_state_msg_local(0,
 			    IPC_GET_DEVICE(*icall), IPC_GET_STATE(*icall));
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
@@ -122,9 +121,9 @@
 				    IPC_GET_DEVICE(*icall), packet, 0);
 			
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
 		default:
-			ipc_answer_0(iid, (sysarg_t) ENOTSUP);
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
 		}
 		
Index: uspace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/tl/icmp/icmp.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -33,5 +33,4 @@
 /** @file
  * ICMP module implementation.
- * @see icmp.h
  */
 
@@ -42,5 +41,4 @@
 #include <stdint.h>
 #include <str.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -51,4 +49,5 @@
 #include <byteorder.h>
 #include <errno.h>
+#include <adt/hash_table.h>
 
 #include <net/socket_codes.h>
@@ -64,5 +63,5 @@
 #include <net_checksum.h>
 #include <icmp_client.h>
-#include <icmp_interface.h>
+#include <icmp_remote.h>
 #include <il_remote.h>
 #include <ip_client.h>
@@ -73,31 +72,26 @@
 #include <icmp_header.h>
 
-#include "icmp.h"
-
-/** ICMP module name. */
+/** ICMP module name */
 #define NAME  "icmp"
 
-/** Default ICMP error reporting. */
-#define NET_DEFAULT_ICMP_ERROR_REPORTING	true
-
-/** Default ICMP echo replying. */
-#define NET_DEFAULT_ICMP_ECHO_REPLYING		true
-
-/** Original datagram length in bytes transfered to the error notification
- * message.
- */
-#define ICMP_KEEP_LENGTH	8
-
-/** Free identifier numbers pool start. */
-#define ICMP_FREE_IDS_START	1
-
-/** Free identifier numbers pool end. */
-#define ICMP_FREE_IDS_END	UINT16_MAX
-
-/** Computes the ICMP datagram checksum.
- *
- * @param[in,out] header The ICMP datagram header.
- * @param[in] length	The total datagram length.
- * @return		The computed checksum.
+/** Number of replies hash table keys */
+#define REPLY_KEYS  2
+
+/** Number of replies hash table buckets */
+#define REPLY_BUCKETS  1024
+
+/**
+ * Original datagram length in bytes transfered to the error
+ * notification message.
+ */
+#define ICMP_KEEP_LENGTH  8
+
+/** Compute the ICMP datagram checksum.
+ *
+ * @param[in,out] header ICMP datagram header.
+ * @param[in]     length Total datagram length.
+ *
+ * @return Computed checksum.
+ *
  */
 #define ICMP_CHECKSUM(header, length) \
@@ -105,181 +99,222 @@
 
 /** An echo request datagrams pattern. */
-#define ICMP_ECHO_TEXT		"Hello from HelenOS."
-
-/** Computes an ICMP reply data key.
- *
- * @param[in] id	The message identifier.
- * @param[in] sequence	The message sequence number.
- * @return		The computed ICMP reply data key.
- */
-#define ICMP_GET_REPLY_KEY(id, sequence) \
-	(((id) << 16) | (sequence & 0xFFFF))
-
-
-/** ICMP global data. */
-icmp_globals_t	icmp_globals;
-
-INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
-INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t);
-
-/** Releases the packet and returns the result.
- *
- * @param[in] packet	The packet queue to be released.
- * @param[in] result	The result to be returned.
- * @return		The result parameter.
- */
-static int icmp_release_and_return(packet_t *packet, int result)
-{
-	pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
-	return result;
-}
-
-/** Sends the ICMP message.
- *
- * Sets the message type and code and computes the checksum.
+#define ICMP_ECHO_TEXT  "ICMP hello from HelenOS."
+
+/** ICMP reply data. */
+typedef struct {
+	/** Hash table link */
+	link_t link;
+	
+	/** Reply identification and sequence */
+	icmp_param_t id;
+	icmp_param_t sequence;
+	
+	/** Reply signaling */
+	fibril_condvar_t condvar;
+	
+	/** Reply result */
+	int result;
+} icmp_reply_t;
+
+/** Global data */
+static int phone_net = -1;
+static int phone_ip = -1;
+static bool error_reporting = true;
+static bool echo_replying = true;
+static packet_dimension_t icmp_dimension;
+
+/** ICMP client identification counter */
+static atomic_t icmp_client;
+
+/** ICMP identifier and sequence number (client-specific) */
+static fibril_local icmp_param_t icmp_id;
+static fibril_local icmp_param_t icmp_seq;
+
+/** Reply hash table */
+static fibril_mutex_t reply_lock;
+static hash_table_t replies;
+
+static hash_index_t replies_hash(unsigned long key[])
+{
+	/*
+	 * ICMP identifier and sequence numbers
+	 * are 16-bit values.
+	 */
+	hash_index_t index = ((key[0] & 0xffff) << 16) | (key[1] & 0xffff);
+	return (index % REPLY_BUCKETS);
+}
+
+static int replies_compare(unsigned long key[], hash_count_t keys, link_t *item)
+{
+	icmp_reply_t *reply =
+	    hash_table_get_instance(item, icmp_reply_t, link);
+	
+	if (keys == 1)
+		return (reply->id == key[0]);
+	else
+		return ((reply->id == key[0]) && (reply->sequence == key[1]));
+}
+
+static void replies_remove_callback(link_t *item)
+{
+}
+
+static hash_table_operations_t reply_ops = {
+	.hash = replies_hash,
+	.compare = replies_compare,
+	.remove_callback = replies_remove_callback
+};
+
+/** Release the packet and return the result.
+ *
+ * @param[in] packet Packet queue to be released.
+ *
+ */
+static void icmp_release(packet_t *packet)
+{
+	pq_release_remote(phone_net, packet_get_id(packet));
+}
+
+/** Send the ICMP message.
+ *
+ * Set the message type and code and compute the checksum.
  * Error messages are sent only if allowed in the configuration.
- * Releases the packet on errors.
- *
- * @param[in] type	The message type.
- * @param[in] code	The message code.
- * @param[in] packet	The message packet to be sent.
- * @param[in] header	The ICMP header.
- * @param[in] error	The error service to be announced. Should be
- *			SERVICE_ICMP or zero.
- * @param[in] ttl	The time to live.
- * @param[in] tos	The type of service.
- * @param[in] dont_fragment The value indicating whether the datagram must not
- *			be fragmented. Is used as a MTU discovery.
- * @return		EOK on success.
- * @return		EPERM if the error message is not allowed.
- */
-static int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t *packet,
-    icmp_header_t *header, services_t error, ip_ttl_t ttl, ip_tos_t tos,
-    int dont_fragment)
-{
-	int rc;
-
+ * Release the packet on errors.
+ *
+ * @param[in] type          Message type.
+ * @param[in] code          Message code.
+ * @param[in] packet        Message packet to be sent.
+ * @param[in] header        ICMP header.
+ * @param[in] error         Error service to be announced. Should be
+ *                          SERVICE_ICMP or zero.
+ * @param[in] ttl           Time to live.
+ * @param[in] tos           Type of service.
+ * @param[in] dont_fragment Disable fragmentation.
+ *
+ * @return EOK on success.
+ * @return EPERM if the error message is not allowed.
+ *
+ */
+static int icmp_send_packet(icmp_type_t type, icmp_code_t code,
+    packet_t *packet, icmp_header_t *header, services_t error, ip_ttl_t ttl,
+    ip_tos_t tos, bool dont_fragment)
+{
 	/* Do not send an error if disabled */
-	if (error && !icmp_globals.error_reporting)
-		return icmp_release_and_return(packet, EPERM);
-
+	if ((error) && (!error_reporting)) {
+		icmp_release(packet);
+		return EPERM;
+	}
+	
 	header->type = type;
 	header->code = code;
+	
+	/*
+	 * The checksum needs to be calculated
+	 * with a virtual checksum field set to
+	 * zero.
+	 */
 	header->checksum = 0;
 	header->checksum = ICMP_CHECKSUM(header,
 	    packet_get_data_length(packet));
 	
-	rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
+	int rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
 	    dont_fragment, 0);
-	if (rc != EOK)
-		return icmp_release_and_return(packet, rc);
-
-	return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP,
-	    error);
-}
-
-/** Prepares the ICMP error packet.
- *
- * Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes.
- * Prefixes and returns the ICMP header.
- *
- * @param[in,out] packet The original packet.
+	if (rc != EOK) {
+		icmp_release(packet);
+		return rc;
+	}
+	
+	return ip_send_msg(phone_ip, -1, packet, SERVICE_ICMP, error);
+}
+
+/** Prepare the ICMP error packet.
+ *
+ * Truncate the original packet if longer than ICMP_KEEP_LENGTH bytes.
+ * Prefix and return the ICMP header.
+ *
+ * @param[in,out] packet Original packet.
+ *
  * @return The prefixed ICMP header.
  * @return NULL on errors.
+ *
  */
 static icmp_header_t *icmp_prepare_packet(packet_t *packet)
 {
-	icmp_header_t *header;
-	size_t header_length;
-	size_t total_length;
-
-	total_length = packet_get_data_length(packet);
+	size_t total_length = packet_get_data_length(packet);
 	if (total_length <= 0)
 		return NULL;
-
-	header_length = ip_client_header_length(packet);
+	
+	size_t header_length = ip_client_header_length(packet);
 	if (header_length <= 0)
 		return NULL;
-
+	
 	/* Truncate if longer than 64 bits (without the IP header) */
 	if ((total_length > header_length + ICMP_KEEP_LENGTH) &&
 	    (packet_trim(packet, 0,
-	    total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) {
+	    total_length - header_length - ICMP_KEEP_LENGTH) != EOK))
 		return NULL;
-	}
-
-	header = PACKET_PREFIX(packet, icmp_header_t);
+	
+	icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
 	if (!header)
 		return NULL;
-
+	
 	bzero(header, sizeof(*header));
 	return header;
 }
 
-/** Requests an echo message.
- *
- * Sends a packet with specified parameters to the target host and waits for
- * the reply upto the given timeout.
- * Blocks the caller until the reply or the timeout occurs.
- *
- * @param[in] id	The message identifier.
- * @param[in] sequence	The message sequence parameter.
- * @param[in] size	The message data length in bytes.
- * @param[in] timeout	The timeout in miliseconds.
- * @param[in] ttl	The time to live.
- * @param[in] tos	The type of service.
- * @param[in] dont_fragment The value indicating whether the datagram must not
- *			be fragmented. Is used as a MTU discovery.
- * @param[in] addr	The target host address.
- * @param[in] addrlen	The torget host address length.
- * @return		ICMP_ECHO on success.
- * @return		ETIMEOUT if the reply has not arrived before the
- *			timeout.
- * @return		ICMP type of the received error notification.
- * @return		EINVAL if the addrlen parameter is less or equal to
- *			zero.
- * @return		ENOMEM if there is not enough memory left.
- * @return		EPARTY if there was an internal error.
+/** Request an echo message.
+ *
+ * Send a packet with specified parameters to the target host
+ * and wait for the reply upto the given timeout.
+ * Block the caller until the reply or the timeout occurs.
+ *
+ * @param[in] id            Message identifier.
+ * @param[in] sequence      Message sequence parameter.
+ * @param[in] size          Message data length in bytes.
+ * @param[in] timeout       Timeout in miliseconds.
+ * @param[in] ttl           Time to live.
+ * @param[in] tos           Type of service.
+ * @param[in] dont_fragment Disable fragmentation.
+ * @param[in] addr          Target host address.
+ * @param[in] addrlen       Torget host address length.
+ *
+ * @return ICMP_ECHO on success.
+ * @return ETIMEOUT if the reply has not arrived before the
+ *         timeout.
+ * @return ICMP type of the received error notification.
+ * @return EINVAL if the addrlen parameter is less or equal to
+ *         zero.
+ * @return ENOMEM if there is not enough memory left.
+ *
  */
 static int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size,
-    mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment,
-    const struct sockaddr * addr, socklen_t addrlen)
-{
-	icmp_header_t *header;
-	packet_t *packet;
-	size_t length;
-	uint8_t *data;
-	icmp_reply_t *reply;
-	int reply_key;
-	int index;
-	int rc;
-
+    mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, bool dont_fragment,
+    const struct sockaddr *addr, socklen_t addrlen)
+{
 	if (addrlen <= 0)
 		return EINVAL;
-
-	length = (size_t) addrlen;
-	/* TODO do not ask all the time */
-	rc = ip_packet_size_req(icmp_globals.ip_phone, -1,
-	    &icmp_globals.packet_dimension);
-	if (rc != EOK)
-		return rc;
-
-	packet = packet_get_4_remote(icmp_globals.net_phone, size,
-	    icmp_globals.packet_dimension.addr_len,
-	    ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix,
-	    icmp_globals.packet_dimension.suffix);
+	
+	size_t length = (size_t) addrlen;
+	
+	packet_t *packet = packet_get_4_remote(phone_net, size,
+	    icmp_dimension.addr_len, ICMP_HEADER_SIZE + icmp_dimension.prefix,
+	    icmp_dimension.suffix);
 	if (!packet)
 		return ENOMEM;
-
+	
 	/* Prepare the requesting packet, set the destination address. */
-	rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
-	if (rc != EOK)
-		return icmp_release_and_return(packet, rc);
-
+	int rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
+	if (rc != EOK) {
+		icmp_release(packet);
+		return rc;
+	}
+	
 	/* Allocate space in the packet */
-	data = (uint8_t *) packet_suffix(packet, size);
-	if (!data)
-		return icmp_release_and_return(packet, ENOMEM);
-
+	uint8_t *data = (uint8_t *) packet_suffix(packet, size);
+	if (!data) {
+		icmp_release(packet);
+		return ENOMEM;
+	}
+	
 	/* Fill the data */
 	length = 0;
@@ -289,166 +324,164 @@
 	}
 	memcpy(data + length, ICMP_ECHO_TEXT, size - length);
-
+	
 	/* Prefix the header */
-	header = PACKET_PREFIX(packet, icmp_header_t);
-	if (!header)
-		return icmp_release_and_return(packet, ENOMEM);
-
-	bzero(header, sizeof(*header));
+	icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
+	if (!header) {
+		icmp_release(packet);
+		return ENOMEM;
+	}
+	
+	bzero(header, sizeof(icmp_header_t));
 	header->un.echo.identifier = id;
 	header->un.echo.sequence_number = sequence;
-
+	
 	/* Prepare the reply structure */
-	reply = malloc(sizeof(*reply));
-	if (!reply)
-		return icmp_release_and_return(packet, ENOMEM);
-
-	fibril_mutex_initialize(&reply->mutex);
-	fibril_mutex_lock(&reply->mutex);
+	icmp_reply_t *reply = malloc(sizeof(icmp_reply_t));
+	if (!reply) {
+		icmp_release(packet);
+		return ENOMEM;
+	}
+	
+	reply->id = id;
+	reply->sequence = sequence;
 	fibril_condvar_initialize(&reply->condvar);
-	reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier,
-	    header->un.echo.sequence_number);
-	index = icmp_replies_add(&icmp_globals.replies, reply_key, reply);
-	if (index < 0) {
-		free(reply);
-		return icmp_release_and_return(packet, index);
-	}
-
-	/* Unlock the globals so that we can wait for the reply */
-	fibril_rwlock_write_unlock(&icmp_globals.lock);
-
+	
+	/* Add the reply to the replies hash table */
+	fibril_mutex_lock(&reply_lock);
+	
+	unsigned long key[REPLY_KEYS] = {id, sequence};
+	hash_table_insert(&replies, key, &reply->link);
+	
 	/* Send the request */
 	icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos,
 	    dont_fragment);
-
+	
 	/* Wait for the reply. Timeout in microseconds. */
-	rc = fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex,
+	rc = fibril_condvar_wait_timeout(&reply->condvar, &reply_lock,
 	    timeout * 1000);
 	if (rc == EOK)
 		rc = reply->result;
-
-	/* Drop the reply mutex before locking the globals again */
-	fibril_mutex_unlock(&reply->mutex);
-	fibril_rwlock_write_lock(&icmp_globals.lock);
-
-	/* Destroy the reply structure */
-	icmp_replies_exclude_index(&icmp_globals.replies, index);
-
+	
+	/* Remove the reply from the replies hash table */
+	hash_table_remove(&replies, key, REPLY_KEYS);
+	
+	fibril_mutex_unlock(&reply_lock);
+	
+	free(reply);
+	
 	return rc;
 }
 
-static int icmp_destination_unreachable_msg_local(int icmp_phone,
-    icmp_code_t code, icmp_param_t mtu, packet_t *packet)
-{
-	icmp_header_t *header;
-
-	header = icmp_prepare_packet(packet);
-	if (!header)
-		return icmp_release_and_return(packet, ENOMEM);
-
+static int icmp_destination_unreachable(icmp_code_t code, icmp_param_t mtu,
+    packet_t *packet)
+{
+	icmp_header_t *header = icmp_prepare_packet(packet);
+	if (!header) {
+		icmp_release(packet);
+		return ENOMEM;
+	}
+	
 	if (mtu)
 		header->un.frag.mtu = mtu;
-
+	
 	return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header,
-	    SERVICE_ICMP, 0, 0, 0);
-}
-
-static int icmp_source_quench_msg_local(int icmp_phone, packet_t *packet)
-{
-	icmp_header_t *header;
-
-	header = icmp_prepare_packet(packet);
-	if (!header)
-		return icmp_release_and_return(packet, ENOMEM);
-
+	    SERVICE_ICMP, 0, 0, false);
+}
+
+static int icmp_source_quench(packet_t *packet)
+{
+	icmp_header_t *header = icmp_prepare_packet(packet);
+	if (!header) {
+		icmp_release(packet);
+		return ENOMEM;
+	}
+	
 	return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header,
-	    SERVICE_ICMP, 0, 0, 0);
-}
-
-static int icmp_time_exceeded_msg_local(int icmp_phone, icmp_code_t code,
+	    SERVICE_ICMP, 0, 0, false);
+}
+
+static int icmp_time_exceeded(icmp_code_t code, packet_t *packet)
+{
+	icmp_header_t *header = icmp_prepare_packet(packet);
+	if (!header) {
+		icmp_release(packet);
+		return ENOMEM;
+	}
+	
+	return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
+	    SERVICE_ICMP, 0, 0, false);
+}
+
+static int icmp_parameter_problem(icmp_code_t code, icmp_param_t pointer,
     packet_t *packet)
 {
-	icmp_header_t *header;
-
-	header = icmp_prepare_packet(packet);
-	if (!header)
-		return icmp_release_and_return(packet, ENOMEM);
-
-	return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
-	    SERVICE_ICMP, 0, 0, 0);
-}
-
-static int icmp_parameter_problem_msg_local(int icmp_phone, icmp_code_t code,
-    icmp_param_t pointer, packet_t *packet)
-{
-	icmp_header_t *header;
-
-	header = icmp_prepare_packet(packet);
-	if (!header)
-		return icmp_release_and_return(packet, ENOMEM);
-
+	icmp_header_t *header = icmp_prepare_packet(packet);
+	if (!header) {
+		icmp_release(packet);
+		return ENOMEM;
+	}
+	
 	header->un.param.pointer = pointer;
 	return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header,
-	    SERVICE_ICMP, 0, 0, 0);
-}
-
-/** Tries to set the pending reply result as the received message type.
+	    SERVICE_ICMP, 0, 0, false);
+}
+
+/** Try to set the pending reply result as the received message type.
  *
  * If the reply data is not present, the reply timed out and the other fibril
- * is already awake.
- * Releases the packet.
- *
- * @param[in] packet	The received reply message.
- * @param[in] header	The ICMP message header.
- * @param[in] type	The received reply message type.
- * @param[in] code	The received reply message code.
- */
-static void  icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
+ * is already awake. The packet is released.
+ *
+ * @param[in] packet The received reply message.
+ * @param[in] header The ICMP message header.
+ * @param[in] type   The received reply message type.
+ * @param[in] code   The received reply message code.
+ *
+ */
+static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
     icmp_type_t type, icmp_code_t code)
 {
-	int reply_key;
-	icmp_reply_t *reply;
-
-	/* Compute the reply key */
-	reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier,
-	    header->un.echo.sequence_number);
-	pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
-
+	unsigned long key[REPLY_KEYS] =
+	    {header->un.echo.identifier, header->un.echo.sequence_number};
+	
+	/* The packet is no longer needed */
+	icmp_release(packet);
+	
 	/* Find the pending reply */
-	fibril_rwlock_write_lock(&icmp_globals.lock);
-	reply = icmp_replies_find(&icmp_globals.replies, reply_key);
-	if (reply) {
+	fibril_mutex_lock(&reply_lock);
+	
+	link_t *link = hash_table_find(&replies, key);
+	if (link != NULL) {
+		icmp_reply_t *reply =
+		   hash_table_get_instance(link, icmp_reply_t, link);
+		
 		reply->result = type;
 		fibril_condvar_signal(&reply->condvar);
 	}
-	fibril_rwlock_write_unlock(&icmp_globals.lock);
-}
-
-/** Processes the received ICMP packet.
- *
- * Notifies the destination socket application.
- *
- * @param[in,out] packet The received packet.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		EINVAL if the stored packet address is not the an_addr_t.
- * @return		EINVAL if the packet does not contain any data.
- * @return		NO_DATA if the packet content is shorter than the user
- *			datagram header.
- * @return		ENOMEM if there is not enough memory left.
- * @return		EADDRNOTAVAIL if the destination socket does not exist.
- * @return		Other error codes as defined for the
- *			ip_client_process_packet() function.
+	
+	fibril_mutex_unlock(&reply_lock);
+}
+
+/** Process the received ICMP packet.
+ *
+ * Notify the destination socket application.
+ *
+ * @param[in,out] packet Received packet.
+ * @param[in]     error  Packet error reporting service to prefix
+ *                       the received packet.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the packet is not valid.
+ * @return EINVAL if the stored packet address is not the an_addr_t.
+ * @return EINVAL if the packet does not contain any data.
+ * @return NO_DATA if the packet content is shorter than the user
+ *         datagram header.
+ * @return ENOMEM if there is not enough memory left.
+ * @return EADDRNOTAVAIL if the destination socket does not exist.
+ * @return Other error codes as defined for the
+ *         ip_client_process_packet() function.
+ *
  */
 static int icmp_process_packet(packet_t *packet, services_t error)
 {
-	size_t length;
-	uint8_t *src;
-	int addrlen;
-	int result;
-	void *data;
-	icmp_header_t *header;
 	icmp_type_t type;
 	icmp_code_t code;
@@ -460,38 +493,38 @@
 	case SERVICE_ICMP:
 		/* Process error */
-		result = icmp_client_process_packet(packet, &type, &code, NULL,
-		    NULL);
-		if (result < 0)
-			return result;
-		length = (size_t) result;
+		rc = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
+		if (rc < 0)
+			return rc;
+		
 		/* Remove the error header */
-		rc = packet_trim(packet, length, 0);
+		rc = packet_trim(packet, (size_t) rc, 0);
 		if (rc != EOK)
 			return rc;
+		
 		break;
 	default:
 		return ENOTSUP;
 	}
-
+	
 	/* Get rid of the IP header */
-	length = ip_client_header_length(packet);
+	size_t length = ip_client_header_length(packet);
 	rc = packet_trim(packet, length, 0);
 	if (rc != EOK)
 		return rc;
-
+	
 	length = packet_get_data_length(packet);
 	if (length <= 0)
 		return EINVAL;
-
+	
 	if (length < ICMP_HEADER_SIZE)
 		return EINVAL;
-
-	data = packet_get_data(packet);
+	
+	void *data = packet_get_data(packet);
 	if (!data)
 		return EINVAL;
-
+	
 	/* Get ICMP header */
-	header = (icmp_header_t *) data;
-
+	icmp_header_t *header = (icmp_header_t *) data;
+	
 	if (header->checksum) {
 		while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
@@ -507,8 +540,9 @@
 				}
 			}
+			
 			return EINVAL;
 		}
 	}
-
+	
 	switch (header->type) {
 	case ICMP_ECHOREPLY:
@@ -517,7 +551,7 @@
 		else
 			icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
-
+		
 		return EOK;
-
+	
 	case ICMP_ECHO:
 		if (error) {
@@ -527,9 +561,10 @@
 		
 		/* Do not send a reply if disabled */
-		if (icmp_globals.echo_replying) {
-			addrlen = packet_get_addr(packet, &src, NULL);
-
+		if (echo_replying) {
+			uint8_t *src;
+			int addrlen = packet_get_addr(packet, &src, NULL);
+			
 			/*
-			 * Set both addresses to the source one (avoids the
+			 * Set both addresses to the source one (avoid the
 			 * source address deletion before setting the
 			 * destination one).
@@ -542,10 +577,10 @@
 				return EOK;
 			}
-
+			
 			return EINVAL;
 		}
-
+		
 		return EPERM;
-
+	
 	case ICMP_DEST_UNREACH:
 	case ICMP_SOURCE_QUENCH:
@@ -560,8 +595,8 @@
 	case ICMP_SKIP:
 	case ICMP_PHOTURIS:
-		ip_received_error_msg(icmp_globals.ip_phone, -1, packet,
+		ip_received_error_msg(phone_ip, -1, packet,
 		    SERVICE_IP, SERVICE_ICMP);
 		return EOK;
-
+	
 	default:
 		return ENOTSUP;
@@ -569,30 +604,4 @@
 }
 
-/** Processes the received ICMP packet.
- *
- * Is used as an entry point from the underlying IP module.
- * Releases the packet on error.
- *
- * @param device_id	The device identifier. Ignored parameter.
- * @param[in,out] packet The received packet.
- * @param receiver	The target service. Ignored parameter.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- * @return		Other error codes as defined for the
- *			icmp_process_packet() function.
- */
-static int icmp_received_msg_local(device_id_t device_id, packet_t *packet,
-    services_t receiver, services_t error)
-{
-	int rc;
-
-	rc = icmp_process_packet(packet, error);
-	if (rc != EOK)
-		return icmp_release_and_return(packet, rc);
-
-	return EOK;
-}
-
 /** Process IPC messages from the IP module
  *
@@ -603,20 +612,26 @@
 static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall)
 {
+	bool loop = true;
 	packet_t *packet;
 	int rc;
 	
-	while (true) {
+	while (loop) {
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(icmp_globals.net_phone, &packet,
+			rc = packet_translate_remote(phone_net, &packet,
 			    IPC_GET_PACKET(*icall));
-			if (rc == EOK)
-				rc = icmp_received_msg_local(IPC_GET_DEVICE(*icall), packet,
-				    SERVICE_ICMP, IPC_GET_ERROR(*icall));
+			if (rc == EOK) {
+				rc = icmp_process_packet(packet, IPC_GET_ERROR(*icall));
+				if (rc != EOK)
+					icmp_release(packet);
+			}
 			
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
+		case IPC_M_PHONE_HUNGUP:
+			loop = false;
+			continue;
 		default:
-			ipc_answer_0(iid, (sysarg_t) ENOTSUP);
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
 		}
 		
@@ -649,288 +664,135 @@
 	uint8_t *data;
 	
-	fibril_rwlock_initialize(&icmp_globals.lock);
-	fibril_rwlock_write_lock(&icmp_globals.lock);
-	icmp_replies_initialize(&icmp_globals.replies);
-	icmp_echo_data_initialize(&icmp_globals.echo_data);
-	
-	icmp_globals.net_phone = net_phone;
-	
-	icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP,
-	    SERVICE_ICMP, icmp_receiver);
-	if (icmp_globals.ip_phone < 0) {
-		fibril_rwlock_write_unlock(&icmp_globals.lock);
-		return icmp_globals.ip_phone;
-	}
-	
-	int rc = ip_packet_size_req(icmp_globals.ip_phone, -1,
-	    &icmp_globals.packet_dimension);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&icmp_globals.lock);
+	if (!hash_table_create(&replies, REPLY_BUCKETS, REPLY_KEYS, &reply_ops))
+		return ENOMEM;
+	
+	fibril_mutex_initialize(&reply_lock);
+	atomic_set(&icmp_client, 0);
+	
+	phone_net = net_phone;
+	phone_ip = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
+	    icmp_receiver);
+	if (phone_ip < 0)
+		return phone_ip;
+	
+	int rc = ip_packet_size_req(phone_ip, -1, &icmp_dimension);
+	if (rc != EOK)
 		return rc;
-	}
-	
-	icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
-	icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
-	
-	icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
-	icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
+	
+	icmp_dimension.prefix += ICMP_HEADER_SIZE;
+	icmp_dimension.content -= ICMP_HEADER_SIZE;
 	
 	/* Get configuration */
 	configuration = &names[0];
-	rc = net_get_conf_req(icmp_globals.net_phone, &configuration, count,
-	    &data);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&icmp_globals.lock);
+	rc = net_get_conf_req(phone_net, &configuration, count, &data);
+	if (rc != EOK)
 		return rc;
-	}
 	
 	if (configuration) {
-		if (configuration[0].value) {
-			icmp_globals.error_reporting =
-			    (configuration[0].value[0] == 'y');
-		}
-		if (configuration[1].value) {
-			icmp_globals.echo_replying =
-			    (configuration[1].value[0] == 'y');
-		}
+		if (configuration[0].value)
+			error_reporting = (configuration[0].value[0] == 'y');
+		
+		if (configuration[1].value)
+			echo_replying = (configuration[1].value[0] == 'y');
+		
 		net_free_settings(configuration, data);
 	}
 	
-	fibril_rwlock_write_unlock(&icmp_globals.lock);
 	return EOK;
 }
 
-/** Processes the generic client messages.
- *
- * @param[in] call	The message parameters.
- * @return		EOK on success.
- * @return		ENOTSUP if the message is not known.
- * @return		Other error codes as defined for the packet_translate()
- *			function.
- * @return		Other error codes as defined for the
- *			icmp_destination_unreachable_msg_local() function.
- * @return		Other error codes as defined for the
- *			icmp_source_quench_msg_local() function.
- * @return		Other error codes as defined for the
- *			icmp_time_exceeded_msg_local() function.
- * @return		Other error codes as defined for the
- *			icmp_parameter_problem_msg_local() function.
- *
- * @see icmp_interface.h
- */
-static int icmp_process_message(ipc_call_t *call)
-{
+/** Per-connection initialization
+ *
+ * Initialize client-specific global variables.
+ *
+ */
+void tl_connection(void)
+{
+	icmp_id = (icmp_param_t) atomic_postinc(&icmp_client);
+	icmp_seq = 1;
+}
+
+/** Process the ICMP message.
+ *
+ * @param[in]  callid Message identifier.
+ * @param[in]  call   Message parameters.
+ * @param[out] answer Answer.
+ * @param[out] count  Number of arguments of the answer.
+ *
+ * @return EOK on success.
+ * @return ENOTSUP if the message is not known.
+ * @return Other error codes as defined for the packet_translate()
+ *         function.
+ * @return Other error codes as defined for the
+ *         icmp_destination_unreachable() function.
+ * @return Other error codes as defined for the
+ *         icmp_source_quench() function.
+ * @return Other error codes as defined for the
+ *         icmp_time_exceeded() function.
+ * @return Other error codes as defined for the
+ *         icmp_parameter_problem() function.
+ *
+ * @see icmp_remote.h
+ * @see IS_NET_ICMP_MESSAGE()
+ *
+ */
+int tl_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, size_t *count)
+{
+	struct sockaddr *addr;
+	size_t size;
 	packet_t *packet;
 	int rc;
-
+	
+	*count = 0;
+	
 	switch (IPC_GET_IMETHOD(*call)) {
+	case NET_ICMP_ECHO:
+		rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &size);
+		if (rc != EOK)
+			return rc;
+		
+		rc = icmp_echo(icmp_id, icmp_seq, ICMP_GET_SIZE(*call),	
+		    ICMP_GET_TIMEOUT(*call), ICMP_GET_TTL(*call),
+		    ICMP_GET_TOS(*call), ICMP_GET_DONT_FRAGMENT(*call),
+		    addr, (socklen_t) size);
+		
+		free(addr);
+		icmp_seq++;
+		return rc;
+	
 	case NET_ICMP_DEST_UNREACH:
-		rc = packet_translate_remote(icmp_globals.net_phone, &packet,
+		rc = packet_translate_remote(phone_net, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
-		return icmp_destination_unreachable_msg_local(0,
-		    ICMP_GET_CODE(*call), ICMP_GET_MTU(*call), packet);
+		
+		return icmp_destination_unreachable(ICMP_GET_CODE(*call),
+		    ICMP_GET_MTU(*call), packet);
+	
 	case NET_ICMP_SOURCE_QUENCH:
-		rc = packet_translate_remote(icmp_globals.net_phone, &packet,
+		rc = packet_translate_remote(phone_net, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
-		return icmp_source_quench_msg_local(0, packet);
+		
+		return icmp_source_quench(packet);
+	
 	case NET_ICMP_TIME_EXCEEDED:
-		rc = packet_translate_remote(icmp_globals.net_phone, &packet,
+		rc = packet_translate_remote(phone_net, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
-		return icmp_time_exceeded_msg_local(0, ICMP_GET_CODE(*call),
-		    packet);
+		
+		return icmp_time_exceeded(ICMP_GET_CODE(*call), packet);
+	
 	case NET_ICMP_PARAMETERPROB:
-		rc = packet_translate_remote(icmp_globals.net_phone, &packet,
+		rc = packet_translate_remote(phone_net, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
-		return icmp_parameter_problem_msg_local(0, ICMP_GET_CODE(*call),
+		
+		return icmp_parameter_problem(ICMP_GET_CODE(*call),
 		    ICMP_GET_POINTER(*call), packet);
-	default:
-		return ENOTSUP;
-	}
-}
-
-/** Assigns a new identifier for the connection.
- *
- * Fills the echo data parameter with the assigned values.
- *
- * @param[in,out] echo_data The echo data to be bound.
- * @return		Index of the inserted echo data.
- * @return		EBADMEM if the echo_data parameter is NULL.
- * @return		ENOTCONN if no free identifier have been found.
- */
-static int icmp_bind_free_id(icmp_echo_t *echo_data)
-{
-	icmp_param_t index;
-
-	if (!echo_data)
-		return EBADMEM;
-
-	/* From the last used one */
-	index = icmp_globals.last_used_id;
-	do {
-		index++;
-		/* til the range end */
-		if (index >= ICMP_FREE_IDS_END) {
-			/* start from the range beginning */
-			index = ICMP_FREE_IDS_START - 1;
-			do {
-				index++;
-				/* til the last used one */
-				if (index >= icmp_globals.last_used_id) {
-					/* none found */
-					return ENOTCONN;
-				}
-			} while(icmp_echo_data_find(&icmp_globals.echo_data,
-			    index) != NULL);
-
-			/* Found, break immediately */
-			break;
-		}
-	} while (icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
-
-	echo_data->identifier = index;
-	echo_data->sequence_number = 0;
-
-	return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
-}
-
-/** Processes the client messages.
- *
- * Remembers the assigned identifier and sequence numbers.
- * Runs until the client module disconnects.
- *
- * @param[in] callid	The message identifier.
- * @param[in] call	The message parameters.
- * @return EOK.
- *
- * @see icmp_interface.h
- * @see icmp_api.h
- */
-static int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
-{
-	bool keep_on_going = true;
-	ipc_call_t answer;
-	size_t answer_count;
-	size_t length;
-	struct sockaddr *addr;
-	ipc_callid_t data_callid;
-	icmp_echo_t *echo_data;
-	int rc = EOK;
-
-	/*
-	 * Accept the connection
-	 *  - Answer the first NET_ICMP_INIT call.
-	 */
-	answer_count = 0;
-
-	echo_data = (icmp_echo_t *) malloc(sizeof(*echo_data));
-	if (!echo_data)
-		return ENOMEM;
-
-	/* Assign a new identifier */
-	fibril_rwlock_write_lock(&icmp_globals.lock);
-	rc = icmp_bind_free_id(echo_data);
-	fibril_rwlock_write_unlock(&icmp_globals.lock);
-	if (rc < 0) {
-		free(echo_data);
-		return rc;
-	}
-
-	while (keep_on_going) {
-		/* Answer the call */
-		answer_call(callid, rc, &answer, answer_count);
-
-		/* Refresh data */
-		refresh_answer(&answer, &answer_count);
-
-		/* Get the next call */
-		callid = async_get_call(&call);
-
-		/* Process the call */
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			keep_on_going = false;
-			rc = EHANGUP;
-			break;
-		
-		case NET_ICMP_ECHO:
-			if (!async_data_write_receive(&data_callid, &length)) {
-				rc = EINVAL;
-				break;
-			}
-			
-			addr = malloc(length);
-			if (!addr) {
-				rc = ENOMEM;
-				break;
-			}
-			
-			rc = async_data_write_finalize(data_callid, addr,
-			    length);
-			if (rc != EOK) {
-				free(addr);
-				break;
-			}
-
-			fibril_rwlock_write_lock(&icmp_globals.lock);
-			rc = icmp_echo(echo_data->identifier,
-			    echo_data->sequence_number, ICMP_GET_SIZE(call),
-			    ICMP_GET_TIMEOUT(call), ICMP_GET_TTL(call),
-			    ICMP_GET_TOS(call), ICMP_GET_DONT_FRAGMENT(call),
-			    addr, (socklen_t) length);
-			fibril_rwlock_write_unlock(&icmp_globals.lock);
-
-			free(addr);
-
-			if (echo_data->sequence_number < UINT16_MAX)
-				echo_data->sequence_number++;
-			else
-				echo_data->sequence_number = 0;
-
-			break;
-
-		default:
-			rc = icmp_process_message(&call);
-		}
-
-	}
-
-	/* Release the identifier */
-	fibril_rwlock_write_lock(&icmp_globals.lock);
-	icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier);
-	fibril_rwlock_write_unlock(&icmp_globals.lock);
-
-	return rc;
-}
-
-/** Processes the ICMP message.
- *
- * @param[in] callid	The message identifier.
- * @param[in] call	The message parameters.
- * @param[out] answer	The message answer parameters.
- * @param[out] answer_count The last parameter for the actual answer in the
- *			answer parameter.
- * @return		EOK on success.
- * @return		ENOTSUP if the message is not known.
- *
- * @see icmp_interface.h
- * @see IS_NET_ICMP_MESSAGE()
- */
-int tl_module_message	(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *answer_count)
-{
-	*answer_count = 0;
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_ICMP_INIT:
-		return icmp_process_client_messages(callid, *call);
-	default:
-		return icmp_process_message(call);
 	}
 	
Index: pace/srv/net/tl/icmp/icmp.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,108 +1,0 @@
-/*
- * Copyright (c) 2008 Lukas Mejdrech
- * 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 icmp
- * @{
- */
-
-/** @file
- * ICMP module.
- */
-
-#ifndef NET_ICMP_H_
-#define NET_ICMP_H_
-
-#include <fibril_synch.h>
-
-#include <net/icmp_codes.h>
-#include <net/packet.h>
-#include <adt/int_map.h>
-#include <icmp_header.h>
-
-/** Type definition of the ICMP reply data.
- * @see icmp_reply
- */
-typedef struct icmp_reply icmp_reply_t;
-
-/** Type definition of the ICMP global data.
- * @see icmp_globals
- */
-typedef struct icmp_globals icmp_globals_t;
-
-/** Pending replies map.
- *
- * Maps message identifiers to the pending replies.
- * Sending fibril waits for its associated reply event.
- * Receiving fibril sets the associated reply with the return value and signals
- * the event.
- */
-INT_MAP_DECLARE(icmp_replies, icmp_reply_t);
-
-/** Echo specific data map.
- *
- * The identifier is used in the future semi-remote calls instead of the ICMP
- * phone.
- */
-INT_MAP_DECLARE(icmp_echo_data, icmp_echo_t);
-
-/** ICMP reply data. */
-struct icmp_reply {
-	/** Reply result. */
-	int result;
-	/** Safety lock. */
-	fibril_mutex_t mutex;
-	/** Received or timeouted reply signaling. */
-	fibril_condvar_t condvar;
-};
-
-/** ICMP global data. */
-struct icmp_globals {
-	/** IP module phone. */
-	int ip_phone;
-	/** Packet dimension. */
-	packet_dimension_t packet_dimension;
-	/** Networking module phone. */
-	int net_phone;
-	/** Indicates whether ICMP error reporting is enabled. */
-	int error_reporting;
-	/** Indicates whether ICMP echo replying (ping) is enabled. */
-	int echo_replying;
-	/** The last used identifier number. */
-	icmp_param_t last_used_id;
-	/** The budled modules assigned echo specific data. */
-	icmp_echo_data_t echo_data;
-	/** Echo timeout locks. */
-	icmp_replies_t replies;
-	/** Safety lock. */
-	fibril_rwlock_t lock;
-};
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -44,5 +44,4 @@
 #include <errno.h>
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -64,5 +63,5 @@
 #include <ip_interface.h>
 #include <icmp_client.h>
-#include <icmp_interface.h>
+#include <icmp_remote.h>
 #include <net_interface.h>
 #include <socket_core.h>
@@ -1204,4 +1203,11 @@
 }
 
+/** Per-connection initialization
+ *
+ */
+void tl_connection(void)
+{
+}
+
 /** Processes the TCP message.
  *
@@ -1217,5 +1223,5 @@
  * @see IS_NET_TCP_MESSAGE()
  */
-int tl_module_message(ipc_callid_t callid, ipc_call_t *call,
+int tl_message(ipc_callid_t callid, ipc_call_t *call,
     ipc_call_t *answer, size_t *answer_count)
 {
@@ -1499,5 +1505,5 @@
 
 	/* Release the application phone */
-	ipc_hangup(app_phone);
+	async_hangup(app_phone);
 
 	printf("release\n");
@@ -2447,8 +2453,8 @@
 				    SERVICE_TCP, IPC_GET_ERROR(*icall));
 			
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		default:
-			ipc_answer_0(iid, (sysarg_t) ENOTSUP);
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
 		}
 		
@@ -2472,6 +2478,5 @@
 	tcp_globals.net_phone = net_phone;
 	
-	tcp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
-	    ICMP_CONNECT_TIMEOUT);
+	tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
 	tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
 	    SERVICE_TCP, tcp_receiver);
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/net/tl/udp/udp.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -40,5 +40,4 @@
 #include <malloc.h>
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -61,5 +60,5 @@
 #include <ip_interface.h>
 #include <icmp_client.h>
-#include <icmp_interface.h>
+#include <icmp_remote.h>
 #include <net_interface.h>
 #include <socket_core.h>
@@ -354,8 +353,8 @@
 				    SERVICE_UDP, IPC_GET_ERROR(*icall));
 			
-			ipc_answer_0(iid, (sysarg_t) rc);
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		default:
-			ipc_answer_0(iid, (sysarg_t) ENOTSUP);
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
 		}
 		
@@ -393,6 +392,5 @@
 	udp_globals.net_phone = net_phone;
 	
-	udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
-	    ICMP_CONNECT_TIMEOUT);
+	udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
 	
 	udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
@@ -869,5 +867,5 @@
 
 	/* Release the application phone */
-	ipc_hangup(app_phone);
+	async_hangup(app_phone);
 
 	/* Release all local sockets */
@@ -876,4 +874,11 @@
 
 	return res;
+}
+
+/** Per-connection initialization
+ *
+ */
+void tl_connection(void)
+{
 }
 
@@ -891,5 +896,5 @@
  * @see IS_NET_UDP_MESSAGE()
  */
-int tl_module_message(ipc_callid_t callid, ipc_call_t *call,
+int tl_message(ipc_callid_t callid, ipc_call_t *call,
     ipc_call_t *answer, size_t *answer_count)
 {
Index: uspace/srv/ns/clonable.c
===================================================================
--- uspace/srv/ns/clonable.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/ns/clonable.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -92,5 +92,5 @@
 	
 	ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call),
-		IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE);
+	    IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE);
 	
 	free(csr);
@@ -127,4 +127,5 @@
 	}
 	
+	link_initialize(&csr->link);
 	csr->service = service;
 	csr->call = *call;
Index: uspace/srv/ns/clonable.h
===================================================================
--- uspace/srv/ns/clonable.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/ns/clonable.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,14 +34,13 @@
 #define NS_CLONABLE_H__
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
+#include <sys/types.h>
 #include <bool.h>
 
 extern int clonable_init(void);
 
-extern bool service_clonable(int service);
-extern void register_clonable(sysarg_t service, sysarg_t phone,
-    ipc_call_t *call, ipc_callid_t callid);
-extern void connect_to_clonable(sysarg_t service, ipc_call_t *call,
-    ipc_callid_t callid);
+extern bool service_clonable(int);
+extern void register_clonable(sysarg_t, sysarg_t, ipc_call_t *, ipc_callid_t);
+extern void connect_to_clonable(sysarg_t, ipc_call_t *, ipc_callid_t);
 
 #endif
Index: uspace/srv/ns/ns.c
===================================================================
--- uspace/srv/ns/ns.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/ns/ns.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,75 +37,12 @@
 
 #include <ipc/ipc.h>
-#include <ipc/services.h>
 #include <ipc/ns.h>
-#include <unistd.h>
 #include <stdio.h>
 #include <errno.h>
-#include <as.h>
-#include <ddi.h>
-#include <event.h>
 #include <macros.h>
-#include <sysinfo.h>
 #include "ns.h"
 #include "service.h"
 #include "clonable.h"
 #include "task.h"
-
-static void *clockaddr = NULL;
-static void *klogaddr = NULL;
-
-static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *faddr,
-    size_t pages, void **addr)
-{
-	if ((faddr == NULL) || (pages == 0)) {
-		ipc_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	if (*addr == NULL) {
-		*addr = as_get_mappable_page(pages * PAGE_SIZE);
-		
-		if (*addr == NULL) {
-			ipc_answer_0(callid, ENOENT);
-			return;
-		}
-		
-		if (physmem_map(faddr, *addr, pages,
-		    AS_AREA_READ | AS_AREA_CACHEABLE) != 0) {
-			ipc_answer_0(callid, ENOENT);
-			return;
-		}
-	}
-	
-	ipc_answer_2(callid, EOK, (sysarg_t) *addr, AS_AREA_READ);
-}
-
-static void setup_clock_area(ipc_callid_t callid, ipc_call_t *call, void **addr)
-{
-	uintptr_t faddr;
-	int err = sysinfo_get_value("clock.faddr", &faddr);
-	
-	if (err != EOK)
-		ipc_answer_0(callid, err);
-	
-	get_as_area(callid, call, (void *) faddr, 1, addr);
-}
-
-static void setup_klog_area(ipc_callid_t callid, ipc_call_t *call, void **addr)
-{
-	uintptr_t faddr;
-	int err = sysinfo_get_value("klog.faddr", &faddr);
-	
-	if (err != EOK)
-		ipc_answer_0(callid, err);
-	
-	size_t pages;
-	err = sysinfo_get_value("klog.pages", &pages);
-	
-	if (err != EOK)
-		ipc_answer_0(callid, err);
-	
-	get_as_area(callid, call, (void *) faddr, pages, addr);
-}
 
 int main(int argc, char **argv)
@@ -138,16 +75,4 @@
 		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_SHARE_IN:
-			switch (IPC_GET_ARG3(call)) {
-			case SERVICE_MEM_REALTIME:
-				setup_clock_area(callid, &call, &clockaddr);
-				break;
-			case SERVICE_MEM_KLOG:
-				setup_klog_area(callid, &call, &klogaddr);
-				break;
-			default:
-				ipc_answer_0(callid, ENOENT);
-			}
-			continue;
 		case IPC_M_PHONE_HUNGUP:
 			retval = ns_task_disconnect(&call);
Index: uspace/srv/ns/service.c
===================================================================
--- uspace/srv/ns/service.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/ns/service.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -43,5 +43,5 @@
 typedef struct {
 	link_t link;
-	sysarg_t service;        /**< Number of the service. */
+	sysarg_t service;        /**< Service ID. */
 	sysarg_t phone;          /**< Phone registered with the service. */
 	sysarg_t in_phone_hash;  /**< Incoming phone hash. */
@@ -56,8 +56,8 @@
  *
  */
-static hash_index_t service_hash(unsigned long *key)
+static hash_index_t service_hash(unsigned long key[])
 {
 	assert(key);
-	return (*key % SERVICE_HASH_TABLE_CHAINS);
+	return (key[0] % SERVICE_HASH_TABLE_CHAINS);
 }
 
@@ -86,5 +86,5 @@
 	
 	if (keys == 2)
-		return (key[1] == hs->in_phone_hash);
+		return ((key[0] == hs->service) && (key[1] == hs->in_phone_hash));
 	else
 		return (key[0] == hs->service);
@@ -195,5 +195,5 @@
 	hash_table_insert(&service_hash_table, keys, &hs->link);
 	
-	return 0;
+	return EOK;
 }
 
@@ -227,4 +227,5 @@
 			}
 			
+			link_initialize(&pr->link);
 			pr->service = service;
 			pr->callid = callid;
Index: uspace/srv/ns/service.h
===================================================================
--- uspace/srv/ns/service.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/ns/service.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,12 +34,12 @@
 #define NS_SERVICE_H__
 
-#include <ipc/ipc.h>
+#include <sys/types.h>
+#include <ipc/common.h>
 
 extern int service_init(void);
 extern void process_pending_conn(void);
 
-extern int register_service(sysarg_t service, sysarg_t phone, ipc_call_t *call);
-extern void connect_to_service(sysarg_t service, ipc_call_t *call,
-     ipc_callid_t callid);
+extern int register_service(sysarg_t, sysarg_t, ipc_call_t *);
+extern void connect_to_service(sysarg_t, ipc_call_t *, ipc_callid_t);
 
 #endif
Index: uspace/srv/ns/task.c
===================================================================
--- uspace/srv/ns/task.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/ns/task.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -43,7 +43,5 @@
 
 #define TASK_HASH_TABLE_CHAINS  256
-#define P2I_HASH_TABLE_CHAINS  256
-
-static int get_id_by_phone(sysarg_t phone_hash, task_id_t *id);
+#define P2I_HASH_TABLE_CHAINS   256
 
 /* TODO:
@@ -57,8 +55,9 @@
 typedef struct {
 	link_t link;
-	task_id_t id;	/**< Task ID. */
-	bool finished;	/**< Task is done. */
-	bool have_rval;	/**< Task returned a value. */
-	int retval;	/**< The return value. */
+	
+	task_id_t id;    /**< Task ID. */
+	bool finished;   /**< Task is done. */
+	bool have_rval;  /**< Task returned a value. */
+	int retval;      /**< The return value. */
 } hashed_task_t;
 
@@ -71,8 +70,8 @@
  *
  */
-static hash_index_t task_hash(unsigned long *key)
+static hash_index_t task_hash(unsigned long key[])
 {
 	assert(key);
-	return (LOWER32(*key) % TASK_HASH_TABLE_CHAINS);
+	return (LOWER32(key[0]) % TASK_HASH_TABLE_CHAINS);
 }
 
@@ -124,6 +123,6 @@
 typedef struct {
 	link_t link;
-	sysarg_t phash;    /**< Task ID. */
-	task_id_t id;    /**< Task ID. */
+	sysarg_t in_phone_hash;  /**< Incoming phone hash. */
+	task_id_t id;            /**< Task ID. */
 } p2i_entry_t;
 
@@ -131,11 +130,12 @@
  *
  * @param key Array of keys.
+ *
  * @return Hash index corresponding to key[0].
  *
  */
-static hash_index_t p2i_hash(unsigned long *key)
+static hash_index_t p2i_hash(unsigned long key[])
 {
 	assert(key);
-	return (*key % TASK_HASH_TABLE_CHAINS);
+	return (key[0] % TASK_HASH_TABLE_CHAINS);
 }
 
@@ -154,8 +154,8 @@
 	assert(keys == 1);
 	assert(item);
-
-	p2i_entry_t *e = hash_table_get_instance(item, p2i_entry_t, link);
-
-	return (key[0] == e->phash);
+	
+	p2i_entry_t *entry = hash_table_get_instance(item, p2i_entry_t, link);
+	
+	return (key[0] == entry->in_phone_hash);
 }
 
@@ -197,5 +197,5 @@
 		return ENOMEM;
 	}
-
+	
 	if (!hash_table_create(&phone_to_id, P2I_HASH_TABLE_CHAINS,
 	    1, &p2i_ops)) {
@@ -205,5 +205,4 @@
 	
 	list_initialize(&pending_wait);
-	
 	return EOK;
 }
@@ -238,5 +237,5 @@
 			    ht->retval);
 		}
-
+		
 		hash_table_remove(&task_hash_table, keys, 2);
 		list_remove(cur);
@@ -250,14 +249,14 @@
 	sysarg_t retval;
 	task_exit_t texit;
-
+	
 	unsigned long keys[2] = {
 		LOWER32(id),
 		UPPER32(id)
 	};
-
+	
 	link_t *link = hash_table_find(&task_hash_table, keys);
 	hashed_task_t *ht = (link != NULL) ?
 	    hash_table_get_instance(link, hashed_task_t, link) : NULL;
-
+	
 	if (ht == NULL) {
 		/* No such task exists. */
@@ -265,5 +264,5 @@
 		return;
 	}
-
+	
 	if (!ht->finished) {
 		/* Add to pending list */
@@ -275,4 +274,5 @@
 		}
 		
+		link_initialize(&pr->link);
 		pr->id = id;
 		pr->callid = callid;
@@ -293,38 +293,37 @@
 int ns_task_id_intro(ipc_call_t *call)
 {
-	task_id_t id;
 	unsigned long keys[2];
-	link_t *link;
-	p2i_entry_t *e;
-	hashed_task_t *ht;
-
-	id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
-
+	
+	task_id_t id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
 	keys[0] = call->in_phone_hash;
-
-	link = hash_table_find(&phone_to_id, keys);
+	
+	link_t *link = hash_table_find(&phone_to_id, keys);
 	if (link != NULL)
 		return EEXISTS;
-
-	e = (p2i_entry_t *) malloc(sizeof(p2i_entry_t));
-	if (e == NULL)
+	
+	p2i_entry_t *entry = (p2i_entry_t *) malloc(sizeof(p2i_entry_t));
+	if (entry == NULL)
 		return ENOMEM;
-
-	ht = (hashed_task_t *) malloc(sizeof(hashed_task_t));
+	
+	hashed_task_t *ht = (hashed_task_t *) malloc(sizeof(hashed_task_t));
 	if (ht == NULL)
 		return ENOMEM;
-
-	/* Insert to phone-to-id map. */
-
-	link_initialize(&e->link);
-	e->phash = call->in_phone_hash;
-	e->id = id;
-	hash_table_insert(&phone_to_id, keys, &e->link);
-
-	/* Insert to main table. */
-
+	
+	/*
+	 * Insert into the phone-to-id map.
+	 */
+	
+	link_initialize(&entry->link);
+	entry->in_phone_hash = call->in_phone_hash;
+	entry->id = id;
+	hash_table_insert(&phone_to_id, keys, &entry->link);
+	
+	/*
+	 * Insert into the main table.
+	 */
+	
 	keys[0] = LOWER32(id);
 	keys[1] = UPPER32(id);
-
+	
 	link_initialize(&ht->link);
 	ht->id = id;
@@ -333,20 +332,33 @@
 	ht->retval = -1;
 	hash_table_insert(&task_hash_table, keys, &ht->link);
-
+	
 	return EOK;
 }
 
+static int get_id_by_phone(sysarg_t phone_hash, task_id_t *id)
+{
+	unsigned long keys[1] = {phone_hash};
+	
+	link_t *link = hash_table_find(&phone_to_id, keys);
+	if (link == NULL)
+		return ENOENT;
+	
+	p2i_entry_t *entry = hash_table_get_instance(link, p2i_entry_t, link);
+	*id = entry->id;
+	
+	return EOK;
+}
+
 int ns_task_retval(ipc_call_t *call)
 {
 	task_id_t id;
-	unsigned long keys[2];
-	int rc;
-
-	rc = get_id_by_phone(call->in_phone_hash, &id);
+	int rc = get_id_by_phone(call->in_phone_hash, &id);
 	if (rc != EOK)
 		return rc;
-
-	keys[0] = LOWER32(id);
-	keys[1] = UPPER32(id);
+	
+	unsigned long keys[2] = {
+		LOWER32(id),
+		UPPER32(id)
+	};
 	
 	link_t *link = hash_table_find(&task_hash_table, keys);
@@ -354,11 +366,11 @@
 	    hash_table_get_instance(link, hashed_task_t, link) : NULL;
 	
-	if ((ht == NULL) || ht->finished)
+	if ((ht == NULL) || (ht->finished))
 		return EINVAL;
-
+	
 	ht->finished = true;
 	ht->have_rval = true;
 	ht->retval = IPC_GET_ARG1(*call);
-
+	
 	return EOK;
 }
@@ -367,19 +379,18 @@
 {
 	unsigned long keys[2];
+	
 	task_id_t id;
-	int rc;
-
-	rc = get_id_by_phone(call->in_phone_hash, &id);
+	int rc = get_id_by_phone(call->in_phone_hash, &id);
 	if (rc != EOK)
 		return rc;
-
+	
 	/* Delete from phone-to-id map. */
 	keys[0] = call->in_phone_hash;
 	hash_table_remove(&phone_to_id, keys, 1);
-
+	
 	/* Mark task as finished. */
 	keys[0] = LOWER32(id);
 	keys[1] = UPPER32(id);
-
+	
 	link_t *link = hash_table_find(&task_hash_table, keys);
 	hashed_task_t *ht =
@@ -387,24 +398,7 @@
 	if (ht == NULL)
 		return EOK;
-
+	
 	ht->finished = true;
-
-	return EOK;
-}
-
-static int get_id_by_phone(sysarg_t phone_hash, task_id_t *id)
-{
-	unsigned long keys[1];
-	link_t *link;
-	p2i_entry_t *e;
-
-	keys[0] = phone_hash;
-	link = hash_table_find(&phone_to_id, keys);
-	if (link == NULL)
-		return ENOENT;
-
-	e = hash_table_get_instance(link, p2i_entry_t, link);
-	*id = e->id;
-
+	
 	return EOK;
 }
Index: uspace/srv/ns/task.h
===================================================================
--- uspace/srv/ns/task.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/ns/task.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -34,14 +34,15 @@
 #define NS_TASK_H__
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
+#include <task.h>
 
 extern int task_init(void);
 extern void process_pending_wait(void);
 
-extern void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid);
+extern void wait_for_task(task_id_t, ipc_call_t *, ipc_callid_t);
 
-extern int ns_task_id_intro(ipc_call_t *call);
-extern int ns_task_disconnect(ipc_call_t *call);
-extern int ns_task_retval(ipc_call_t *call);
+extern int ns_task_id_intro(ipc_call_t *);
+extern int ns_task_disconnect(ipc_call_t *);
+extern int ns_task_retval(ipc_call_t *);
 
 
Index: uspace/srv/taskmon/taskmon.c
===================================================================
--- uspace/srv/taskmon/taskmon.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/taskmon/taskmon.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
 
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <async.h>
 #include <ipc/services.h>
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/vfs/vfs.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,6 +36,6 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
+#include <ipc/ns.h>
 #include <async.h>
 #include <errno.h>
@@ -47,5 +47,5 @@
 #include "vfs.h"
 
-#define NAME "vfs"
+#define NAME  "vfs"
 
 static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
@@ -57,16 +57,6 @@
 	 * This call needs to be answered.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
-	/*
-	 * Here we enter the main connection fibril loop.
-	 * The logic behind this loop and the protocol is that we'd like to keep
-	 * each connection open until the client hangs up. When the client hangs
-	 * up, we will free its VFS state. The act of hanging up the connection
-	 * by the client is equivalent to client termination because we cannot
-	 * distinguish one from the other. On the other hand, the client can
-	 * hang up arbitrarily if it has no open files and reestablish the
-	 * connection later.
-	 */
 	while (keep_on_going) {
 		ipc_call_t call;
@@ -129,10 +119,13 @@
 			vfs_dup(callid, &call);
 		default:
-			ipc_answer_0(callid, ENOTSUP);
+			async_answer_0(callid, ENOTSUP);
 			break;
 		}
 	}
-	
-	vfs_files_done();
+
+	/*
+	 * Open files for this client will be cleaned up when its last
+	 * connection fibril terminates.
+	 */
 }
 
@@ -166,4 +159,10 @@
 	
 	/*
+	 * Set client data constructor and destructor.
+	 */
+	async_set_client_data_constructor(vfs_client_data_create);
+	async_set_client_data_destructor(vfs_client_data_destroy);
+
+	/*
 	 * Set a connection handling function/fibril.
 	 */
@@ -173,6 +172,8 @@
 	 * Register at the naming service.
 	 */
-	sysarg_t phonead;
-	ipc_connect_to_me(PHONE_NS, SERVICE_VFS, 0, 0, &phonead);
+	if (service_register(SERVICE_VFS) != EOK) {
+		printf("%s: Cannot register VFS service\n", NAME);
+		return EINVAL;
+	}
 	
 	/*
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/vfs/vfs.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,5 +35,4 @@
 
 #include <async.h>
-#include <ipc/ipc.h>
 #include <adt/list.h>
 #include <fibril_synch.h>
@@ -188,13 +187,12 @@
 #define MAX_OPEN_FILES	128
 
-extern bool vfs_files_init(void);
-extern void vfs_files_done(void);
+extern void *vfs_client_data_create(void);
+extern void vfs_client_data_destroy(void *);
+
 extern vfs_file_t *vfs_file_get(int);
-extern int vfs_fd_assign(vfs_file_t *file, int fd);
+extern void vfs_file_put(vfs_file_t *);
+extern int vfs_fd_assign(vfs_file_t *, int);
 extern int vfs_fd_alloc(bool desc);
 extern int vfs_fd_free(int);
-
-extern void vfs_file_addref(vfs_file_t *);
-extern void vfs_file_delref(vfs_file_t *);
 
 extern void vfs_node_addref(vfs_node_t *);
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/vfs/vfs_file.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,50 +45,98 @@
 #include "vfs.h"
 
-/**
- * This is a per-connection table of open files.
- * Our assumption is that each client opens only one connection and therefore
- * there is one table of open files per task. However, this may not be the case
- * and the client can open more connections to VFS. In that case, there will be
- * several tables and several file handle name spaces per task. Besides of this,
- * the functionality will stay unchanged. So unless the client knows what it is
- * doing, it should open one connection to VFS only.
- *
- * Allocation of the open files table is deferred until the client makes the
- * first VFS_OPEN operation.
- *
- * This resource being per-connection and, in the first place, per-fibril, we
- * don't need to protect it by a mutex.
- */
-fibril_local vfs_file_t **files = NULL;
+#define VFS_DATA	((vfs_client_data_t *) async_client_data_get())
+#define FILES		(VFS_DATA->files)
+
+typedef struct {
+	fibril_mutex_t lock;
+	vfs_file_t **files;
+} vfs_client_data_t;
 
 /** Initialize the table of open files. */
-bool vfs_files_init(void)
-{
-	if (!files) {
-		files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
-		if (!files)
+static bool vfs_files_init(void)
+{
+	fibril_mutex_lock(&VFS_DATA->lock);
+	if (!FILES) {
+		FILES = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
+		if (!FILES) {
+			fibril_mutex_unlock(&VFS_DATA->lock);
 			return false;
-		memset(files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
-	}
+		}
+		memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
+	}
+	fibril_mutex_unlock(&VFS_DATA->lock);
 	return true;
 }
 
 /** Cleanup the table of open files. */
-void vfs_files_done(void)
+static void vfs_files_done(void)
 {
 	int i;
 
-	if (!files)
+	if (!FILES)
 		return;
 
 	for (i = 0; i < MAX_OPEN_FILES; i++) {
-		if (files[i]) {
-			(void) vfs_close_internal(files[i]);
+		if (FILES[i]) {
+			(void) vfs_close_internal(FILES[i]);
 			(void) vfs_fd_free(i);
 		}
 	}
 	
-	free(files);
-}
+	free(FILES);
+}
+
+void *vfs_client_data_create(void)
+{
+	vfs_client_data_t *vfs_data;
+
+	vfs_data = malloc(sizeof(vfs_client_data_t));
+	if (vfs_data) {
+		fibril_mutex_initialize(&vfs_data->lock);
+		vfs_data->files = NULL;
+	}
+	
+	return vfs_data;
+}
+
+void vfs_client_data_destroy(void *data)
+{
+	vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
+
+	vfs_files_done();
+	free(vfs_data);
+}
+
+/** Increment reference count of VFS file structure.
+ *
+ * @param file		File structure that will have reference count
+ *			incremented.
+ */
+static void vfs_file_addref(vfs_file_t *file)
+{
+	assert(fibril_mutex_is_locked(&VFS_DATA->lock));
+
+	file->refcnt++;
+}
+
+/** Decrement reference count of VFS file structure.
+ *
+ * @param file		File structure that will have reference count
+ *			decremented.
+ */
+static void vfs_file_delref(vfs_file_t *file)
+{
+	assert(fibril_mutex_is_locked(&VFS_DATA->lock));
+
+	if (file->refcnt-- == 1) {
+		/*
+		 * Lost the last reference to a file, need to drop our reference
+		 * to the underlying VFS node.
+		 */
+		vfs_node_delref(file->node);
+		free(file);
+	}
+}
+
 
 /** Allocate a file descriptor.
@@ -111,13 +159,17 @@
 		i = 0;
 	
+	fibril_mutex_lock(&VFS_DATA->lock);
 	while (true) {
-		if (!files[i]) {
-			files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
-			if (!files[i])
+		if (!FILES[i]) {
+			FILES[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
+			if (!FILES[i]) {
+				fibril_mutex_unlock(&VFS_DATA->lock);
 				return ENOMEM;
+			}
 			
-			memset(files[i], 0, sizeof(vfs_file_t));
-			fibril_mutex_initialize(&files[i]->lock);
-			vfs_file_addref(files[i]);
+			memset(FILES[i], 0, sizeof(vfs_file_t));
+			fibril_mutex_initialize(&FILES[i]->lock);
+			vfs_file_addref(FILES[i]);
+			fibril_mutex_unlock(&VFS_DATA->lock);
 			return (int) i;
 		}
@@ -135,4 +187,5 @@
 		}
 	}
+	fibril_mutex_unlock(&VFS_DATA->lock);
 	
 	return EMFILE;
@@ -150,10 +203,14 @@
 	if (!vfs_files_init())
 		return ENOMEM;
-	
-	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL))
+
+	fibril_mutex_lock(&VFS_DATA->lock);	
+	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] == NULL)) {
+		fibril_mutex_unlock(&VFS_DATA->lock);
 		return EBADF;
-	
-	vfs_file_delref(files[fd]);
-	files[fd] = NULL;
+	}
+	
+	vfs_file_delref(FILES[fd]);
+	FILES[fd] = NULL;
+	fibril_mutex_unlock(&VFS_DATA->lock);
 	
 	return EOK;
@@ -173,46 +230,18 @@
 	if (!vfs_files_init())
 		return ENOMEM;
-	
-	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] != NULL))
+
+	fibril_mutex_lock(&VFS_DATA->lock);	
+	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] != NULL)) {
+		fibril_mutex_unlock(&VFS_DATA->lock);
 		return EINVAL;
-	
-	files[fd] = file;
-	vfs_file_addref(files[fd]);
+	}
+	
+	FILES[fd] = file;
+	vfs_file_addref(FILES[fd]);
+	fibril_mutex_unlock(&VFS_DATA->lock);
 	
 	return EOK;
 }
 
-/** Increment reference count of VFS file structure.
- *
- * @param file		File structure that will have reference count
- *			incremented.
- */
-void vfs_file_addref(vfs_file_t *file)
-{
-	/*
-	 * File structures are per-connection, so no-one, except the current
-	 * fibril, should have a reference to them. This is the reason we don't
-	 * do any synchronization here.
-	 */
-	file->refcnt++;
-}
-
-/** Decrement reference count of VFS file structure.
- *
- * @param file		File structure that will have reference count
- *			decremented.
- */
-void vfs_file_delref(vfs_file_t *file)
-{
-	if (file->refcnt-- == 1) {
-		/*
-		 * Lost the last reference to a file, need to drop our reference
-		 * to the underlying VFS node.
-		 */
-		vfs_node_delref(file->node);
-		free(file);
-	}
-}
-
 /** Find VFS file structure for a given file descriptor.
  *
@@ -226,8 +255,25 @@
 		return NULL;
 	
-	if ((fd >= 0) && (fd < MAX_OPEN_FILES))
-		return files[fd];
+	fibril_mutex_lock(&VFS_DATA->lock);
+	if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
+		vfs_file_t *file = FILES[fd];
+		vfs_file_addref(file);
+		fibril_mutex_unlock(&VFS_DATA->lock);
+		return file;
+	}
+	fibril_mutex_unlock(&VFS_DATA->lock);
 	
 	return NULL;
+}
+
+/** Stop using a file structure.
+ *
+ * @param file		VFS file structure.
+ */
+void vfs_file_put(vfs_file_t *file)
+{
+	fibril_mutex_lock(&VFS_DATA->lock);
+	vfs_file_delref(file);
+	fibril_mutex_unlock(&VFS_DATA->lock);
 }
 
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/vfs/vfs_lookup.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,5 +37,4 @@
 
 #include "vfs.h"
-#include <ipc/ipc.h>
 #include <macros.h>
 #include <async.h>
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/vfs/vfs_ops.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,5 +37,4 @@
 
 #include "vfs.h"
-#include <ipc/ipc.h>
 #include <macros.h>
 #include <stdint.h>
@@ -91,5 +90,5 @@
 			/* Trying to mount root FS over root FS */
 			fibril_rwlock_write_unlock(&namespace_rwlock);
-			ipc_answer_0(rid, EBUSY);
+			async_answer_0(rid, EBUSY);
 			return;
 		}
@@ -99,5 +98,5 @@
 			/* The lookup failed for some reason. */
 			fibril_rwlock_write_unlock(&namespace_rwlock);
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -106,5 +105,5 @@
 		if (!mp_node) {
 			fibril_rwlock_write_unlock(&namespace_rwlock);
-			ipc_answer_0(rid, ENOMEM);
+			async_answer_0(rid, ENOMEM);
 			return;
 		}
@@ -134,5 +133,5 @@
 				vfs_release_phone(fs_handle, phone);
 				fibril_rwlock_write_unlock(&namespace_rwlock);
-				ipc_answer_0(rid, rc);
+				async_answer_0(rid, rc);
 				return;
 			}
@@ -142,5 +141,5 @@
 			if (rc != EOK) {
 				fibril_rwlock_write_unlock(&namespace_rwlock);
-				ipc_answer_0(rid, rc);
+				async_answer_0(rid, rc);
 				return;
 			}
@@ -165,5 +164,5 @@
 			
 			fibril_rwlock_write_unlock(&namespace_rwlock);
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 			return;
 		} else {
@@ -173,5 +172,5 @@
 			 */
 			fibril_rwlock_write_unlock(&namespace_rwlock);
-			ipc_answer_0(rid, ENOENT);
+			async_answer_0(rid, ENOENT);
 			return;
 		}
@@ -202,5 +201,5 @@
 		if (mp_node)
 			vfs_node_put(mp_node);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		fibril_rwlock_write_unlock(&namespace_rwlock);
 		return;
@@ -218,5 +217,5 @@
 			vfs_node_put(mp_node);
 		fibril_rwlock_write_unlock(&namespace_rwlock);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -245,5 +244,5 @@
 	}
 
-	ipc_answer_0(rid, rc);
+	async_answer_0(rid, rc);
 	fibril_rwlock_write_unlock(&namespace_rwlock);
 }
@@ -275,5 +274,5 @@
 	    0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -285,5 +284,5 @@
 	if (rc != EOK) {
 		free(mp);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -299,5 +298,5 @@
 		free(mp);
 		free(opts);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -310,6 +309,6 @@
 	ipc_callid_t callid = async_get_call(&data);
 	if (IPC_GET_IMETHOD(data) != IPC_M_PING) {
-		ipc_answer_0(callid, ENOTSUP);
-		ipc_answer_0(rid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
+		async_answer_0(rid, ENOTSUP);
 		free(mp);
 		free(opts);
@@ -333,6 +332,6 @@
 		
 		fibril_mutex_unlock(&fs_head_lock);
-		ipc_answer_0(callid, ENOENT);
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		free(mp);
 		free(fs_name);
@@ -343,5 +342,5 @@
 	
 	/* Acknowledge that we know fs_name. */
-	ipc_answer_0(callid, EOK);
+	async_answer_0(callid, EOK);
 	
 	/* Do the mount */
@@ -367,5 +366,5 @@
 	    0, NULL);
 	if (rc != EOK)
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 
 	/*
@@ -386,5 +385,5 @@
 		fibril_rwlock_write_unlock(&namespace_rwlock);
 		free(mp);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -393,5 +392,5 @@
 		fibril_rwlock_write_unlock(&namespace_rwlock);
 		free(mp);
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		return;
 	}
@@ -409,5 +408,5 @@
 		vfs_node_put(mr_node);
 		free(mp);
-		ipc_answer_0(rid, EBUSY);
+		async_answer_0(rid, EBUSY);
 		return;
 	}
@@ -430,5 +429,5 @@
 			fibril_rwlock_write_unlock(&namespace_rwlock);
 			vfs_node_put(mr_node);
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -449,5 +448,5 @@
 			fibril_rwlock_write_unlock(&namespace_rwlock);
 			vfs_node_put(mr_node);
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -456,5 +455,5 @@
 			fibril_rwlock_write_unlock(&namespace_rwlock);
 			vfs_node_put(mr_node);
-			ipc_answer_0(rid, ENOMEM);
+			async_answer_0(rid, ENOMEM);
 			return;
 		}
@@ -468,5 +467,5 @@
 			vfs_node_put(mp_node);
 			vfs_node_put(mr_node);
-			ipc_answer_0(rid, rc);
+			async_answer_0(rid, rc);
 			return;
 		}
@@ -486,14 +485,9 @@
 
 	fibril_rwlock_write_unlock(&namespace_rwlock);
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
 void vfs_open(ipc_callid_t rid, ipc_call_t *request)
 {
-	if (!vfs_files_init()) {
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
 	/*
 	 * The POSIX interface is open(path, oflag, mode).
@@ -519,5 +513,5 @@
 	    ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
 	    (lflag & (L_OPEN | L_ROOT | L_MP))) {
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -531,5 +525,5 @@
 	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -553,5 +547,5 @@
 		else
 			fibril_rwlock_read_unlock(&namespace_rwlock);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		free(path);
 		return;
@@ -576,5 +570,5 @@
 				fibril_rwlock_write_unlock(&node->contents_rwlock);
 				vfs_node_put(node);
-				ipc_answer_0(rid, rc);
+				async_answer_0(rid, rc);
 				return;
 			}
@@ -591,5 +585,5 @@
 	if (fd < 0) {
 		vfs_node_put(node);
-		ipc_answer_0(rid, fd);
+		async_answer_0(rid, fd);
 		return;
 	}
@@ -609,7 +603,8 @@
 	vfs_node_addref(node);
 	vfs_node_put(node);
+	vfs_file_put(file);
 	
 	/* Success! Return the new file descriptor to the client. */
-	ipc_answer_1(rid, EOK, fd);
+	async_answer_1(rid, EOK, fd);
 }
 
@@ -617,9 +612,4 @@
 {
 	// FIXME: check for sanity of the supplied fs, dev and index
-	
-	if (!vfs_files_init()) {
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
 	
 	/*
@@ -638,5 +628,5 @@
 	if (rc != EOK) {
 		fibril_rwlock_read_unlock(&namespace_rwlock);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -654,5 +644,5 @@
 				fibril_rwlock_write_unlock(&node->contents_rwlock);
 				vfs_node_put(node);
-				ipc_answer_0(rid, rc);
+				async_answer_0(rid, rc);
 				return;
 			}
@@ -669,5 +659,5 @@
 	if (fd < 0) {
 		vfs_node_put(node);
-		ipc_answer_0(rid, fd);
+		async_answer_0(rid, fd);
 		return;
 	}
@@ -686,7 +676,8 @@
 	vfs_node_addref(node);
 	vfs_node_put(node);
+	vfs_file_put(file);
 	
 	/* Success! Return the new file descriptor to the client. */
-	ipc_answer_1(rid, EOK, fd);
+	async_answer_1(rid, EOK, fd);
 }
 
@@ -698,5 +689,5 @@
 	vfs_file_t *file = vfs_file_get(fd);
 	if (!file) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -721,6 +712,7 @@
 	vfs_release_phone(file->node->fs_handle, fs_phone);
 	fibril_mutex_unlock(&file->lock);
-	
-	ipc_answer_0(rid, rc);
+
+	vfs_file_put(file);
+	async_answer_0(rid, rc);
 }
 
@@ -767,5 +759,5 @@
 	vfs_file_t *file = vfs_file_get(fd);
 	if (!file) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -773,8 +765,9 @@
 	int ret = vfs_close_internal(file);
 	if (ret != EOK)
-		ipc_answer_0(rid, ret);
-	
+		async_answer_0(rid, ret);
+	
+	vfs_file_put(file);
 	ret = vfs_fd_free(fd);
-	ipc_answer_0(rid, ret);
+	async_answer_0(rid, ret);
 }
 
@@ -798,5 +791,5 @@
 	vfs_file_t *file = vfs_file_get(fd);
 	if (!file) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -875,10 +868,11 @@
 		file->pos += bytes;
 	fibril_mutex_unlock(&file->lock);
-	
+	vfs_file_put(file);	
+
 	/*
 	 * FS server's reply is the final result of the whole operation we
 	 * return to the client.
 	 */
-	ipc_answer_1(rid, rc, bytes);
+	async_answer_1(rid, rc, bytes);
 }
 
@@ -903,5 +897,5 @@
 	vfs_file_t *file = vfs_file_get(fd);
 	if (!file) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -915,5 +909,6 @@
 			file->pos = (aoff64_t) off;
 			fibril_mutex_unlock(&file->lock);
-			ipc_answer_1(rid, EOK, off);
+			vfs_file_put(file);
+			async_answer_1(rid, EOK, off);
 			return;
 		}
@@ -922,5 +917,6 @@
 		if ((off >= 0) && (file->pos + off < file->pos)) {
 			fibril_mutex_unlock(&file->lock);
-			ipc_answer_0(rid, EOVERFLOW);
+			vfs_file_put(file);
+			async_answer_0(rid, EOVERFLOW);
 			return;
 		}
@@ -928,5 +924,6 @@
 		if ((off < 0) && (file->pos < (aoff64_t) -off)) {
 			fibril_mutex_unlock(&file->lock);
-			ipc_answer_0(rid, EOVERFLOW);
+			vfs_file_put(file);
+			async_answer_0(rid, EOVERFLOW);
 			return;
 		}
@@ -936,5 +933,6 @@
 		
 		fibril_mutex_unlock(&file->lock);
-		ipc_answer_2(rid, EOK, LOWER32(newoff),
+		vfs_file_put(file);
+		async_answer_2(rid, EOK, LOWER32(newoff),
 		    UPPER32(newoff));
 		return;
@@ -946,5 +944,6 @@
 			fibril_rwlock_read_unlock(&file->node->contents_rwlock);
 			fibril_mutex_unlock(&file->lock);
-			ipc_answer_0(rid, EOVERFLOW);
+			vfs_file_put(file);
+			async_answer_0(rid, EOVERFLOW);
 			return;
 		}
@@ -953,5 +952,6 @@
 			fibril_rwlock_read_unlock(&file->node->contents_rwlock);
 			fibril_mutex_unlock(&file->lock);
-			ipc_answer_0(rid, EOVERFLOW);
+			vfs_file_put(file);
+			async_answer_0(rid, EOVERFLOW);
 			return;
 		}
@@ -962,10 +962,12 @@
 		fibril_rwlock_read_unlock(&file->node->contents_rwlock);
 		fibril_mutex_unlock(&file->lock);
-		ipc_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff));
+		vfs_file_put(file);
+		async_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff));
 		return;
 	}
 	
 	fibril_mutex_unlock(&file->lock);
-	ipc_answer_0(rid, EINVAL);
+	vfs_file_put(file);
+	async_answer_0(rid, EINVAL);
 }
 
@@ -992,5 +994,5 @@
 	vfs_file_t *file = vfs_file_get(fd);
 	if (!file) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -1005,5 +1007,6 @@
 
 	fibril_mutex_unlock(&file->lock);
-	ipc_answer_0(rid, (sysarg_t)rc);
+	vfs_file_put(file);
+	async_answer_0(rid, (sysarg_t)rc);
 }
 
@@ -1015,5 +1018,5 @@
 	vfs_file_t *file = vfs_file_get(fd);
 	if (!file) {
-		ipc_answer_0(rid, ENOENT);
+		async_answer_0(rid, ENOENT);
 		return;
 	}
@@ -1021,6 +1024,7 @@
 	ipc_callid_t callid;
 	if (!async_data_read_receive(&callid, NULL)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		vfs_file_put(file);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -1033,10 +1037,11 @@
 	msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->devmap_handle,
 	    file->node->index, true, NULL);
-	ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 	async_wait_for(msg, &rc);
 	vfs_release_phone(file->node->fs_handle, fs_phone);
 
 	fibril_mutex_unlock(&file->lock);
-	ipc_answer_0(rid, rc);
+	vfs_file_put(file);
+	async_answer_0(rid, rc);
 }
 
@@ -1046,5 +1051,5 @@
 	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1053,6 +1058,6 @@
 	if (!async_data_read_receive(&callid, NULL)) {
 		free(path);
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -1064,6 +1069,6 @@
 	if (rc != EOK) {
 		fibril_rwlock_read_unlock(&namespace_rwlock);
-		ipc_answer_0(callid, rc);
-		ipc_answer_0(rid, rc);
+		async_answer_0(callid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1071,6 +1076,6 @@
 	if (!node) {
 		fibril_rwlock_read_unlock(&namespace_rwlock);
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		return;
 	}
@@ -1082,5 +1087,5 @@
 	msg = async_send_3(fs_phone, VFS_OUT_STAT, node->devmap_handle,
 	    node->index, false, NULL);
-	ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 	
 	sysarg_t rv;
@@ -1088,5 +1093,5 @@
 	vfs_release_phone(node->fs_handle, fs_phone);
 
-	ipc_answer_0(rid, rv);
+	async_answer_0(rid, rv);
 
 	vfs_node_put(node);
@@ -1100,5 +1105,5 @@
 	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1112,5 +1117,5 @@
 	fibril_rwlock_write_unlock(&namespace_rwlock);
 	free(path);
-	ipc_answer_0(rid, rc);
+	async_answer_0(rid, rc);
 }
 
@@ -1122,5 +1127,5 @@
 	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1133,5 +1138,5 @@
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1148,5 +1153,5 @@
 	fibril_rwlock_write_unlock(&namespace_rwlock);
 	vfs_node_put(node);
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
@@ -1157,5 +1162,5 @@
 	int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1166,5 +1171,5 @@
 	if (rc != EOK) {
 		free(old);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -1176,5 +1181,5 @@
 	
 	if ((!oldc) || (!newc)) {
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		free(old);
 		free(new);
@@ -1195,5 +1200,5 @@
 		 * - oldc and newc are equal.
 		 */
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		free(old);
 		free(new);
@@ -1210,5 +1215,5 @@
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		free(old);
 		free(new);
@@ -1219,5 +1224,5 @@
 	if (!old_node) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		free(old);
 		free(new);
@@ -1229,5 +1234,5 @@
 	if (!parentc) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		free(old);
 		free(new);
@@ -1246,5 +1251,5 @@
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		free(old);
 		free(new);
@@ -1256,5 +1261,5 @@
 	    (old_node->devmap_handle != new_par_lr.triplet.devmap_handle)) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
-		ipc_answer_0(rid, EXDEV);	/* different file systems */
+		async_answer_0(rid, EXDEV);	/* different file systems */
 		free(old);
 		free(new);
@@ -1274,5 +1279,5 @@
 		if (!new_node) {
 			fibril_rwlock_write_unlock(&namespace_rwlock);
-			ipc_answer_0(rid, ENOMEM);
+			async_answer_0(rid, ENOMEM);
 			free(old);
 			free(new);
@@ -1285,5 +1290,5 @@
 	default:
 		fibril_rwlock_write_unlock(&namespace_rwlock);
-		ipc_answer_0(rid, ENOTEMPTY);
+		async_answer_0(rid, ENOTEMPTY);
 		free(old);
 		free(new);
@@ -1297,5 +1302,5 @@
 		if (new_node)
 			vfs_node_put(new_node);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		free(old);
 		free(new);
@@ -1314,5 +1319,5 @@
 		if (new_node)
 			vfs_node_put(new_node);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		free(old);
 		free(new);
@@ -1331,5 +1336,5 @@
 	free(old);
 	free(new);
-	ipc_answer_0(rid, EOK);
+	async_answer_0(rid, EOK);
 }
 
@@ -1338,15 +1343,15 @@
 	int oldfd = IPC_GET_ARG1(*request);
 	int newfd = IPC_GET_ARG2(*request);
+	
+	/* If the file descriptors are the same, do nothing. */
+	if (oldfd == newfd) {
+		async_answer_1(rid, EOK, newfd);
+		return;
+	}
 	
 	/* Lookup the file structure corresponding to oldfd. */
 	vfs_file_t *oldfile = vfs_file_get(oldfd);
 	if (!oldfile) {
-		ipc_answer_0(rid, EBADF);
-		return;
-	}
-	
-	/* If the file descriptors are the same, do nothing. */
-	if (oldfd == newfd) {
-		ipc_answer_1(rid, EOK, newfd);
+		async_answer_0(rid, EBADF);
 		return;
 	}
@@ -1365,5 +1370,7 @@
 		if (ret != EOK) {
 			fibril_mutex_unlock(&oldfile->lock);
-			ipc_answer_0(rid, ret);
+			vfs_file_put(oldfile);
+			vfs_file_put(newfile);
+			async_answer_0(rid, ret);
 			return;
 		}
@@ -1372,7 +1379,10 @@
 		if (ret != EOK) {
 			fibril_mutex_unlock(&oldfile->lock);
-			ipc_answer_0(rid, ret);
-			return;
-		}
+			vfs_file_put(oldfile);
+			vfs_file_put(newfile);
+			async_answer_0(rid, ret);
+			return;
+		}
+		vfs_file_put(newfile);
 	}
 	
@@ -1380,9 +1390,10 @@
 	int ret = vfs_fd_assign(oldfile, newfd);
 	fibril_mutex_unlock(&oldfile->lock);
+	vfs_file_put(oldfile);
 	
 	if (ret != EOK)
-		ipc_answer_0(rid, ret);
+		async_answer_0(rid, ret);
 	else
-		ipc_answer_1(rid, EOK, newfd);
+		async_answer_1(rid, EOK, newfd);
 }
 
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/srv/vfs/vfs_register.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -36,5 +36,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <async.h>
@@ -122,5 +121,5 @@
 		dprintf("Failed to deliver the VFS info into our AS, rc=%d.\n",
 		    rc);
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -132,5 +131,5 @@
 	if (!fs_info) {
 		dprintf("Could not allocate memory for FS info.\n");
-		ipc_answer_0(rid, ENOMEM);
+		async_answer_0(rid, ENOMEM);
 		return;
 	}
@@ -144,5 +143,5 @@
 	if (!vfs_info_sane(&fs_info->vfs_info)) {
 		free(fs_info);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -160,5 +159,5 @@
 		fibril_mutex_unlock(&fs_head_lock);
 		free(fs_info);
-		ipc_answer_0(rid, EEXISTS);
+		async_answer_0(rid, EEXISTS);
 		return;
 	}
@@ -182,6 +181,6 @@
 		fibril_mutex_unlock(&fs_head_lock);
 		free(fs_info);
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -189,5 +188,5 @@
 	phone = IPC_GET_ARG5(call);
 	async_session_create(&fs_info->session, phone, 0);
-	ipc_answer_0(callid, EOK);
+	async_answer_0(callid, EOK);
 	
 	dprintf("Callback connection to FS created.\n");
@@ -203,8 +202,8 @@
 		fibril_mutex_unlock(&fs_head_lock);
 		async_session_destroy(&fs_info->session);
-		ipc_hangup(phone);
-		free(fs_info);
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_hangup(phone);
+		free(fs_info);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -218,8 +217,8 @@
 		fibril_mutex_unlock(&fs_head_lock);
 		async_session_destroy(&fs_info->session);
-		ipc_hangup(phone);
-		free(fs_info);
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+		async_hangup(phone);
+		free(fs_info);
+		async_answer_0(callid, EINVAL);
+		async_answer_0(rid, EINVAL);
 		return;
 	}
@@ -239,5 +238,5 @@
 	 */
 	fs_info->fs_handle = (fs_handle_t) atomic_postinc(&fs_handle_next);
-	ipc_answer_1(rid, EOK, (sysarg_t) fs_info->fs_handle);
+	async_answer_1(rid, EOK, (sysarg_t) fs_info->fs_handle);
 	
 	fibril_condvar_broadcast(&fs_head_cv);
