Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ boot/Makefile.common	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -98,5 +98,5 @@
 	$(USPACE_PATH)/srv/fs/fat/fat \
 	$(USPACE_PATH)/srv/taskmon/taskmon \
-	$(USPACE_PATH)/srv/hw/netif/dp8390/dp8390 \
+	$(USPACE_PATH)/srv/hw/netif/ne2000/ne2000 \
 	$(USPACE_PATH)/srv/net/netif/lo/lo \
 	$(USPACE_PATH)/srv/net/nil/eth/eth \
@@ -132,8 +132,6 @@
 	$(USPACE_PATH)/app/taskdump/taskdump \
 	$(USPACE_PATH)/app/tester/tester \
-	$(USPACE_PATH)/app/test_serial/test_serial \
 	$(USPACE_PATH)/app/tetris/tetris \
 	$(USPACE_PATH)/app/trace/trace \
-	$(USPACE_PATH)/app/netstart/netstart \
 	$(USPACE_PATH)/app/nettest1/nettest1 \
 	$(USPACE_PATH)/app/nettest2/nettest2 \
@@ -141,5 +139,4 @@
 	$(USPACE_PATH)/app/ping/ping \
 	$(USPACE_PATH)/app/stats/stats \
-	$(USPACE_PATH)/app/tasks/tasks \
 	$(USPACE_PATH)/app/top/top \
 	$(USPACE_PATH)/app/sysinfo/sysinfo \
Index: contrib/arch/kernel/kernel.adl
===================================================================
--- contrib/arch/kernel/kernel.adl	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ contrib/arch/kernel/kernel.adl	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ contrib/arch/uspace/lib/libc/protocol	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/amd64/include/interrupt.h
===================================================================
--- kernel/arch/amd64/include/interrupt.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/arch/amd64/include/interrupt.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -55,5 +55,5 @@
 #define IRQ_PIC_SPUR  7
 #define IRQ_MOUSE     12
-#define IRQ_DP8390    9
+#define IRQ_NE2000    9
 
 /* This one must have four least significant bits set to ones */
Index: kernel/arch/amd64/src/amd64.c
===================================================================
--- kernel/arch/amd64/src/amd64.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/arch/amd64/src/amd64.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -238,5 +238,5 @@
 		sysinfo_set_item_val(irqs_info, NULL, true);
 	
-	sysinfo_set_item_val("netif.dp8390.inr", NULL, IRQ_DP8390);
+	sysinfo_set_item_val("netif.ne2000.inr", NULL, IRQ_NE2000);
 }
 
Index: kernel/arch/arm32/src/mach/gta02/gta02.c
===================================================================
--- kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/arch/ia32/_link.ld.in	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/ia32/include/interrupt.h
===================================================================
--- kernel/arch/ia32/include/interrupt.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/arch/ia32/include/interrupt.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -55,5 +55,5 @@
 #define IRQ_PIC_SPUR  7
 #define IRQ_MOUSE     12
-#define IRQ_DP8390    5
+#define IRQ_NE2000    5
 
 /* This one must have four least significant bits set to ones */
Index: kernel/arch/ia32/src/ia32.c
===================================================================
--- kernel/arch/ia32/src/ia32.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/arch/ia32/src/ia32.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -196,5 +196,5 @@
 		sysinfo_set_item_val(irqs_info, NULL, true);
 	
-	sysinfo_set_item_val("netif.dp8390.inr", NULL, IRQ_DP8390);
+	sysinfo_set_item_val("netif.ne2000.inr", NULL, IRQ_NE2000);
 }
 
Index: kernel/arch/ia64/include/interrupt.h
===================================================================
--- kernel/arch/ia64/include/interrupt.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/arch/ia64/include/interrupt.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -61,5 +61,5 @@
 #define IRQ_KBD    (0x01 + LEGACY_INTERRUPT_BASE)
 #define IRQ_MOUSE  (0x0c + LEGACY_INTERRUPT_BASE)
-#define IRQ_DP8390 (0x09 + LEGACY_INTERRUPT_BASE)
+#define IRQ_NE2000 (0x09 + LEGACY_INTERRUPT_BASE)
 
 /** General Exception codes. */
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/arch/ia64/src/ia64.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -222,5 +222,5 @@
 #endif
 
-	sysinfo_set_item_val("netif.dp8390.inr", NULL, IRQ_DP8390);
+	sysinfo_set_item_val("netif.ne2000.inr", NULL, IRQ_NE2000);
 
 	sysinfo_set_item_val("ia64_iospace", NULL, true);
Index: kernel/arch/sparc64/src/drivers/niagara.c
===================================================================
--- kernel/arch/sparc64/src/drivers/niagara.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/arch/sparc64/src/drivers/niagara.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/ddi/ddi.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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;
 
@@ -54,5 +55,4 @@
 extern sysarg_t sys_physmem_map(sysarg_t, sysarg_t, sysarg_t, sysarg_t);
 extern sysarg_t sys_iospace_enable(ddi_ioarg_t *);
-extern sysarg_t sys_interrupt_enable(int irq, int enable);
 
 /*
@@ -61,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/debug.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/ipc/event_types.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/ipc/ipc.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/ipc/sysipc.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/proc/task.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/proc/thread.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/syscall/syscall.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -48,4 +48,5 @@
 	SYS_TASK_SET_NAME,
 	SYS_TASK_KILL,
+	SYS_TASK_EXIT,
 	SYS_PROGRAM_SPAWN_LOADER,
 	
@@ -70,6 +71,4 @@
 	SYS_IPC_POKE,
 	SYS_IPC_HANGUP,
-	SYS_IPC_REGISTER_IRQ,
-	SYS_IPC_UNREGISTER_IRQ,
 	SYS_IPC_CONNECT_KBOX,
 	
@@ -82,5 +81,6 @@
 	SYS_PHYSMEM_MAP,
 	SYS_IOSPACE_ENABLE,
-	SYS_INTERRUPT_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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/sysinfo/abi.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/sysinfo/sysinfo.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/include/udebug/udebug.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/adt/avl.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/console/cmd.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/console/console.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/ddi/ddi.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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;
 	
@@ -258,34 +280,4 @@
 }
 
-/** Disable or enable specified interrupts.
- * 
- * @param irq the interrupt to be enabled/disabled.
- * @param enable if true enable the interrupt, disable otherwise.
- * 
- * @retutn Zero on success, error code otherwise.
- */
-sysarg_t sys_interrupt_enable(int irq, int enable)
-{
-/* FIXME: this needs to be generic code, or better not be in kernel at all. */
-#if 0
-	cap_t task_cap = cap_get(TASK);
-	if (!(task_cap & CAP_IRQ_REG))
-		return EPERM;
-		
-	if (irq < 0 || irq > 16) {
-		return EINVAL;
-	}
-	
-	uint16_t irq_mask = (uint16_t)(1 << irq);
-	if (enable) {
-		trap_virtual_enable_irqs(irq_mask);
-	} else {
-		trap_virtual_disable_irqs(irq_mask);
-	}
-	
-#endif
-	return 0;
-}
-
 /** @}
  */
Index: kernel/generic/src/interrupt/interrupt.c
===================================================================
--- kernel/generic/src/interrupt/interrupt.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/interrupt/interrupt.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/ipc/ipc.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/ipc/irq.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/ipc/sysipc.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/lib/elf.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/lib/rd.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/backend_phys.c
===================================================================
--- kernel/generic/src/mm/backend_phys.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/mm/backend_phys.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/slab.c
===================================================================
--- kernel/generic/src/mm/slab.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/mm/slab.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -806,13 +806,8 @@
 }
 
-/** Go through all caches and reclaim what is possible
- *
- * Interrupts must be disabled before calling this function,
- * otherwise  memory allocation from interrupts can deadlock.
- *
- */
+/** Go through all caches and reclaim what is possible */
 size_t slab_reclaim(unsigned int flags)
 {
-	irq_spinlock_lock(&slab_cache_lock, false);
+	irq_spinlock_lock(&slab_cache_lock, true);
 	
 	size_t frames = 0;
@@ -824,5 +819,5 @@
 	}
 	
-	irq_spinlock_unlock(&slab_cache_lock, false);
+	irq_spinlock_unlock(&slab_cache_lock, true);
 	
 	return frames;
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/proc/scheduler.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/proc/task.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/proc/thread.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/synch/waitq.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/syscall/syscall.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -86,6 +86,5 @@
 	} else {
 		printf("Task %" PRIu64": Unknown syscall %#" PRIxn, TASK->taskid, id);
-		task_kill(TASK->taskid);
-		thread_exit();
+		task_kill_self(true);
 	}
 	
@@ -131,4 +130,5 @@
 	(syshandler_t) sys_task_set_name,
 	(syshandler_t) sys_task_kill,
+	(syshandler_t) sys_task_exit,
 	(syshandler_t) sys_program_spawn_loader,
 	
@@ -156,6 +156,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,5 +169,6 @@
 	(syshandler_t) sys_physmem_map,
 	(syshandler_t) sys_iospace_enable,
-	(syshandler_t) sys_interrupt_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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/sysinfo/stats.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -170,5 +170,5 @@
 	 * 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.
+	 * having them calculated over and over again here.
 	 */
 
@@ -199,4 +199,64 @@
 }
 
+/** 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)
+{
+	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 over and over again here.
+	 */
+	
+	if (SYNCH_FAILED(mutex_trylock(&as->lock)))
+		return result * PAGE_SIZE;
+	
+	/* Walk the B+ tree of AS areas */
+	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;
+			
+			/* Walk the B+ tree of resident pages */
+			link_t *rcur;
+			for (rcur = area->used_space.leaf_head.next;
+			    rcur != &area->used_space.leaf_head; rcur = rcur->next) {
+				btree_node_t *rnode =
+				    list_get_instance(rcur, btree_node_t, leaf_link);
+				
+				unsigned int j;
+				for (j = 0; j < rnode->keys; j++)
+					result += (size_t) rnode->value[i];
+			}
+			
+			mutex_unlock(&area->lock);
+		}
+	}
+	
+	mutex_unlock(&as->lock);
+	
+	return result * PAGE_SIZE;
+}
+
 /* Produce task statistics
  *
@@ -215,4 +275,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/sysinfo/sysinfo.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ kernel/generic/src/time/clock.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -46,5 +46,4 @@
 	app/stats \
 	app/taskdump \
-	app/tasks \
 	app/tester \
 	app/tetris \
@@ -80,5 +79,5 @@
 	srv/hw/char/i8042 \
 	srv/hw/char/s3c24xx_uart \
-	srv/hw/netif/dp8390 \
+	srv/hw/netif/ne2000 \
 	srv/net/netif/lo \
 	srv/net/il/arp \
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/Makefile.common	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -135,4 +135,11 @@
 endif
 
+ifeq ($(CONFIG_LINE_DEBUG),y)
+	GCC_CFLAGS += -g
+	ICC_CFLAGS += -g
+	SUNCC_CFLAGS += -g
+	CLANG_CFLAGS += -g
+endif
+
 ## Setup platform configuration
 #
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/init/init.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/klog/klog.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/ping/ping.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/stats/stats.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/taskdump/taskdump.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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;
 	}
Index: pace/app/tasks/Makefile
===================================================================
--- uspace/app/tasks/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(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/hw/misc/virtchar1.c
===================================================================
--- uspace/app/tester/hw/misc/virtchar1.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/tester/hw/misc/virtchar1.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/tester/hw/serial/serial1.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -39,5 +39,4 @@
 #include <stdlib.h>
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <sys/types.h>
 #include <async.h>
@@ -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/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/tester/tester.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -38,5 +38,4 @@
 #include <sys/types.h>
 #include <bool.h>
-#include <ipc/ipc.h>
 
 #define IPC_TEST_SERVICE  10240
Index: uspace/app/tetris/screen.h
===================================================================
--- uspace/app/tetris/screen.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/tetris/screen.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/top/screen.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/top/top.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/top/top.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/trace/ipc_desc.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/trace/ipcp.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/trace/proto.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/trace/proto.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/trace/syscalls.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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,10 +71,11 @@
     [SYS_PHYSMEM_MAP] = { "physmem_map",		4,	V_ERRNO },
     [SYS_IOSPACE_ENABLE] = { "iospace_enable",		1,	V_ERRNO },
-    [SYS_INTERRUPT_ENABLE] = { "interrupt_enable",	2,	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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/app/trace/trace.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/doc/doxygroups.h
===================================================================
--- uspace/doc/doxygroups.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/doc/doxygroups.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -43,12 +43,7 @@
 
 			/**
-			 * @defgroup dp8390 Generic DP8390 network interface family service
+			 * @defgroup ne2000 NE2000 network interface service
 			 * @ingroup netif
 			 */
-
-				/**
-				 * @defgroup ne2k NE2000 network interface family
-				 * @ingroup dp8390
-				 */
 
 		/**
Index: uspace/drv/ns8250/ns8250.c
===================================================================
--- uspace/drv/ns8250/ns8250.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/drv/ns8250/ns8250.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -256,5 +256,5 @@
 	
 	if (dev->parent_phone > 0) {
-		ipc_hangup(dev->parent_phone);
+		async_hangup(dev->parent_phone);
 		dev->parent_phone = 0;
 	}
@@ -431,10 +431,4 @@
 {
 	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	int res;
-	
-	/* Enable interrupt globally. */
-	res = interrupt_enable(data->irq);
-	if (res != EOK)
-		return res;
 	
 	/* Enable interrupt on the serial port. */
@@ -894,5 +888,5 @@
 		ns8250_get_props(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;
@@ -905,9 +899,9 @@
 		ret = ns8250_set_props(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);
 	}
 }
Index: uspace/drv/pciintel/pci.c
===================================================================
--- uspace/drv/pciintel/pci.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/drv/pciintel/pci.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -478,5 +478,5 @@
 		    "the device.\n");
 		delete_pci_bus_data(bus_data);
-		ipc_hangup(dev->parent_phone);
+		async_hangup(dev->parent_phone);
 		return rc;
 	}	
@@ -496,5 +496,5 @@
 		printf(NAME ": failed to enable configuration ports.\n");
 		delete_pci_bus_data(bus_data);
-		ipc_hangup(dev->parent_phone);
+		async_hangup(dev->parent_phone);
 		hw_res_clean_resource_list(&hw_resources);
 		return EADDRNOTAVAIL;
Index: uspace/drv/test2/test2.c
===================================================================
--- uspace/drv/test2/test2.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/drv/test2/test2.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -103,4 +103,8 @@
 	if (dev->parent == NULL) {
 		fid_t postpone = fibril_create(postponed_birth, dev);
+		if (postpone == 0) {
+			printf(NAME ": fibril_create() error\n");
+			return ENOMEM;
+		}
 		fibril_add_ready(postpone);
 	} else {
Index: uspace/lib/block/libblock.c
===================================================================
--- uspace/lib/block/libblock.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/block/libblock.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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);	
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -83,4 +83,5 @@
 	generic/io/console.c \
 	generic/io/screenbuffer.c \
+	generic/ipc/ns.c \
 	generic/malloc.c \
 	generic/sysinfo.c \
@@ -96,5 +97,4 @@
 	generic/adt/char_map.c \
 	generic/time.c \
-	generic/err.c \
 	generic/stdlib.c \
 	generic/mman.c \
Index: uspace/lib/c/arch/abs32le/src/entry.c
===================================================================
--- uspace/lib/c/arch/abs32le/src/entry.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/abs32le/src/entry.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/abs32le/src/thread_entry.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/amd64/_link.ld.in	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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,12 +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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/amd64/src/entry.s	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -47,4 +47,2 @@
 	# Pass PCB pointer to __main (no operation)
 	call __main
-
-	call __exit
Index: uspace/lib/c/arch/arm32/src/entry.s
===================================================================
--- uspace/lib/c/arch/arm32/src/entry.s	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/arm32/src/entry.s	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/ia32/_link.ld.in	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -5,4 +5,5 @@
 	text PT_LOAD FLAGS(5);
 	data PT_LOAD FLAGS(6);
+	debug PT_NOTE;
 }
 
@@ -43,6 +44,18 @@
 	
 	. = ALIGN(0x1000);
+	_heap = .;
 	
-	_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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/ia32/src/entry.s	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/src/entry.s
===================================================================
--- uspace/lib/c/arch/ia64/src/entry.s	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/ia64/src/entry.s	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/src/entry.s
===================================================================
--- uspace/lib/c/arch/mips32/src/entry.s	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/mips32/src/entry.s	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -56,7 +56,4 @@
 	jal __main
 	nop
-	
-	jal __exit
-	nop
 .end
 
Index: uspace/lib/c/arch/ppc32/src/entry.s
===================================================================
--- uspace/lib/c/arch/ppc32/src/entry.s	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/ppc32/src/entry.s	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/src/entry.s
===================================================================
--- uspace/lib/c/arch/sparc64/src/entry.s	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/arch/sparc64/src/entry.s	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/async.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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,6 +290,6 @@
 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_t *conn = hash_table_get_instance(item, connection_t, link);
+	return (key[0] == conn->in_phone_hash);
 }
 
@@ -219,5 +306,4 @@
 	free(hash_table_get_instance(item, connection_t, link));
 }
-
 
 /** Operations for the connection hash table. */
@@ -240,9 +326,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 +348,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 +439,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 +491,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 +498,5 @@
 			return conn->close_callid;
 		}
-
+		
 		if (usecs)
 			async_insert_timeout(&conn->wdata);
@@ -443,29 +536,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 +549,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,4 +640,8 @@
 	}
 	
+	/*
+	 * 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);
@@ -517,4 +656,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 +669,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 +677,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 +695,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 +727,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 +736,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 +760,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 +794,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 +817,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 +830,5 @@
 		
 		atomic_dec(&threads_in_ipc_wait);
-
+		
 		if (!callid) {
 			handle_expired_timeouts();
@@ -729,5 +869,6 @@
 {
 	fid_t fid = fibril_create(async_manager_fibril, NULL);
-	fibril_add_manager(fid);
+	if (fid != 0)
+		fibril_add_manager(fid);
 }
 
@@ -740,17 +881,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 +903,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 +951,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 +960,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 +995,5 @@
     ipc_call_t *dataptr)
 {
-	amsg_t *msg = malloc(sizeof(*msg));
+	amsg_t *msg = malloc(sizeof(amsg_t));
 	
 	if (!msg)
@@ -861,5 +1004,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 +1107,5 @@
 void async_usleep(suseconds_t timeout)
 {
-	amsg_t *msg = malloc(sizeof(*msg));
+	amsg_t *msg = malloc(sizeof(amsg_t));
 	
 	if (!msg)
@@ -1103,78 +1250,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 +1466,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 +1528,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 +1575,12 @@
 }
 
-
-/** 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.
+/** 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 +1592,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 +1640,4 @@
 
 /** Wrapper for forwarding any read request
- *
  *
  */
@@ -1377,5 +1672,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 +1689,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 +1817,5 @@
  *
  */
-void async_data_write_void(const int retval)
+void async_data_write_void(sysarg_t retval)
 {
 	ipc_callid_t callid;
@@ -1530,5 +1825,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/async_sess.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -99,5 +99,4 @@
 
 #include <async_sess.h>
-#include <ipc/ipc.h>
 #include <fibril_synch.h>
 #include <adt/list.h>
@@ -106,14 +105,16 @@
 #include <errno.h>
 #include <assert.h>
+#include "private/async_sess.h"
 
 /** An inactive open connection. */
 typedef struct {
 	link_t sess_link;	/**< Link for the session list of inactive connections. */
-	link_t global_link;	/**< Link for the global list of inactive connectinos. */
+	link_t global_link;	/**< Link for the global list of inactive connections. */
 	int data_phone;		/**< Connected data phone. */
 } conn_node_t;
 
 /**
- * Mutex protecting the inactive_conn_head list and the session list.
+ * Mutex protecting the inactive_conn_head list, the session list and the
+ * avail_phone condition variable.
  */
 static fibril_mutex_t async_sess_mutex;
@@ -129,9 +130,15 @@
 static LIST_INITIALIZE(session_list_head);
 
+/**
+ * Condition variable used to wait for a phone to become available.
+ */
+static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);
+
 /** Initialize the async_sess subsystem.
  *
  * 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);
@@ -194,7 +201,9 @@
 		list_remove(&conn->global_link);
 		
-		ipc_hangup(conn->data_phone);
+		async_hangup(conn->data_phone);
 		free(conn);
 	}
+	
+	fibril_condvar_broadcast(&avail_phone_cv);
 }
 
@@ -252,14 +261,12 @@
 			data_phone = conn->data_phone;
 			free(conn);
-			ipc_hangup(data_phone);
+			async_hangup(data_phone);
 			goto retry;
 		} else {
 			/*
-			 * This is unfortunate. We failed both to find a cached
-			 * connection or to create a new one even after cleaning up
-			 * the cache. This is most likely due to too many
-			 * open sessions (connected session phones).
+			 * Wait for a phone to become available.
 			 */
-			data_phone = ELIMIT;
+			fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex);
+			goto retry;
 		}
 	}
@@ -279,4 +286,5 @@
 
 	fibril_mutex_lock(&async_sess_mutex);
+	fibril_condvar_signal(&avail_phone_cv);
 	conn = (conn_node_t *) malloc(sizeof(conn_node_t));
 	if (!conn) {
@@ -285,6 +293,6 @@
 		 * means that we simply hang up.
 		 */
+		async_hangup(data_phone);
 		fibril_mutex_unlock(&async_sess_mutex);
-		ipc_hangup(data_phone);
 		return;
 	}
Index: uspace/lib/c/generic/clipboard.c
===================================================================
--- uspace/lib/c/generic/clipboard.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/clipboard.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/ddi.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -96,26 +96,4 @@
 }
 
-/** Enable an interrupt.
- * 
- * @param irq the interrupt.
- * 
- * @return Zero on success, negative error code otherwise. 
- */
-int interrupt_enable(int irq) 
-{
-	return __SYSCALL2(SYS_INTERRUPT_ENABLE, (sysarg_t) irq, 1);
-}
-
-/** Disable an interrupt.
- * 
- * @param irq the interrupt.
- * 
- * @return Zero on success, negative error code otherwise. 
- */
-int interrupt_disable(int irq) 
-{
-	return __SYSCALL2(SYS_INTERRUPT_ENABLE, (sysarg_t) irq, 0);
-}
-
 /** Enable PIO for specified I/O range.
  *
@@ -149,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/devman.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -28,6 +28,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
- 
- /** @addtogroup libc
+
+/** @addtogroup libc
  * @{
  */
@@ -37,9 +37,9 @@
 #include <str.h>
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/devman.h>
 #include <devman.h>
 #include <async.h>
+#include <fibril_synch.h>
 #include <errno.h>
 #include <malloc.h>
@@ -50,10 +50,15 @@
 static int devman_phone_client = -1;
 
+static FIBRIL_MUTEX_INITIALIZE(devman_phone_mutex);
+
 int devman_get_phone(devman_interface_t iface, unsigned int flags)
 {
 	switch (iface) {
 	case DEVMAN_DRIVER:
-		if (devman_phone_driver >= 0)
+		fibril_mutex_lock(&devman_phone_mutex);
+		if (devman_phone_driver >= 0) {
+			fibril_mutex_unlock(&devman_phone_mutex);
 			return devman_phone_driver;
+		}
 		
 		if (flags & IPC_FLAG_BLOCKING)
@@ -64,16 +69,22 @@
 			    SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
 		
+		fibril_mutex_unlock(&devman_phone_mutex);
 		return devman_phone_driver;
 	case DEVMAN_CLIENT:
-		if (devman_phone_client >= 0)
+		fibril_mutex_lock(&devman_phone_mutex);
+		if (devman_phone_client >= 0) {
+			fibril_mutex_unlock(&devman_phone_mutex);
 			return devman_phone_client;
-		
-		if (flags & IPC_FLAG_BLOCKING)
+		}
+		
+		if (flags & IPC_FLAG_BLOCKING) {
 			devman_phone_client = async_connect_me_to_blocking(
 			    PHONE_NS, SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
-		else
+		} else {
 			devman_phone_client = async_connect_me_to(PHONE_NS,
 			    SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
-		
+		}
+		
+		fibril_mutex_unlock(&devman_phone_mutex);
 		return devman_phone_client;
 	default:
@@ -104,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);
 	
@@ -210,5 +220,5 @@
 	case DEVMAN_DRIVER:
 		if (devman_phone_driver >= 0) {
-			ipc_hangup(devman_phone_driver);
+			async_hangup(devman_phone_driver);
 			devman_phone_driver = -1;
 		}
@@ -216,5 +226,5 @@
 	case DEVMAN_CLIENT:
 		if (devman_phone_client >= 0) {
-			ipc_hangup(devman_phone_client);
+			async_hangup(devman_phone_client);
 			devman_phone_client = -1;
 		}
Index: uspace/lib/c/generic/devmap.c
===================================================================
--- uspace/lib/c/generic/devmap.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/devmap.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/event.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/fibril_synch.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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();
 }
 
@@ -103,4 +103,7 @@
 {
 	fibril_t *f = (fibril_t *) fibril_get_id();
+
+	if (fibril_get_sercount() != 0)
+		abort();
 
 	futex_down(&async_futex);
@@ -194,4 +197,7 @@
 	fibril_t *f = (fibril_t *) fibril_get_id();
 	
+	if (fibril_get_sercount() != 0)
+		abort();
+
 	futex_down(&async_futex);
 	if (frw->writers) {
@@ -219,4 +225,7 @@
 	fibril_t *f = (fibril_t *) fibril_get_id();
 	
+	if (fibril_get_sercount() != 0)
+		abort();
+
 	futex_down(&async_futex);
 	if (frw->writers || frw->readers) {
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/io/io.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/ipc.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/c/generic/ipc/ns.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/libc.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/loader.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/malloc.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -45,4 +45,5 @@
 #include <futex.h>
 #include <adt/gcdlcm.h>
+#include "private/malloc.h"
 
 /* Magic used in heap headers. */
@@ -215,25 +216,22 @@
 /** 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);
+ * 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 (!as_area_create((void *) &_heap, PAGE_SIZE,
+	    AS_AREA_WRITE | AS_AREA_READ))
+		abort();
+	
+	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);
 }
 
Index: uspace/lib/c/generic/net/icmp_api.c
===================================================================
--- uspace/lib/c/generic/net/icmp_api.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/net/icmp_api.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/net/icmp_common.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/net/modules.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -32,5 +32,5 @@
 
 /** @file
- * Generic module functions implementation. 
+ * Generic module functions implementation.
  *
  * @todo MAKE IT POSSIBLE TO REMOVE THIS FILE VIA EITHER REPLACING PART OF ITS
@@ -43,8 +43,5 @@
 #include <errno.h>
 #include <sys/time.h>
-
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <net/modules.h>
 
@@ -52,36 +49,36 @@
 #define MODULE_WAIT_TIME	(10 * 1000)
 
-/** Answers the call.
- *
- * @param[in] callid	The call identifier.
- * @param[in] result	The message processing result.
- * @param[in] answer	The message processing answer.
- * @param[in] answer_count The number of answer parameters.
- */
-void
-answer_call(ipc_callid_t callid, int result, ipc_call_t *answer,
-    int answer_count)
-{
-	/* Choose the most efficient answer function */
-	if (answer || (!answer_count)) {
-		switch (answer_count) {
+/** Answer a call.
+ *
+ * @param[in] callid Call identifier.
+ * @param[in] result Message processing result.
+ * @param[in] answer Message processing answer.
+ * @param[in] count  Number of answer parameters.
+ *
+ */
+void answer_call(ipc_callid_t callid, int result, ipc_call_t *answer,
+    size_t count)
+{
+	/* Choose the most efficient function */
+	if ((answer != NULL) || (count == 0)) {
+		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);
 	}
 	
@@ -228,19 +220,19 @@
 }
 
-/** Refreshes answer structure and parameters count.
- *
- * Erases all attributes.
- *
- * @param[in,out] answer The message processing answer structure.
- * @param[in,out] answer_count The number of answer parameters.
- */
-void refresh_answer(ipc_call_t *answer, int *answer_count)
-{
-	if (answer_count)
-		*answer_count = 0;
-
-	if (answer) {
+/** Refresh answer structure and argument count.
+ *
+ * Erase all arguments.
+ *
+ * @param[in,out] answer Message processing answer structure.
+ * @param[in,out] count  Number of answer arguments.
+ *
+ */
+void refresh_answer(ipc_call_t *answer, size_t *count)
+{
+	if (count != NULL)
+		*count = 0;
+	
+	if (answer != NULL) {
 		IPC_SET_RETVAL(*answer, 0);
-		/* Just to be precise */
 		IPC_SET_IMETHOD(*answer, 0);
 		IPC_SET_ARG1(*answer, 0);
Index: uspace/lib/c/generic/net/socket_client.c
===================================================================
--- uspace/lib/c/generic/net/socket_client.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/net/socket_client.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/c/generic/private/async.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/c/generic/private/async_sess.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/c/generic/private/io.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/c/generic/private/libc.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,44 @@
+/*
+ * 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 int main(int, char *[]);
+extern void __main(void *) __attribute__((noreturn));
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/malloc.h
===================================================================
--- uspace/lib/c/generic/private/malloc.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/c/generic/private/malloc.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/c/generic/private/thread.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/stats.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/sysinfo.c
===================================================================
--- uspace/lib/c/generic/sysinfo.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/sysinfo.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/thread.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/time.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/udebug.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/adt/hash_table.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/async.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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)
@@ -312,5 +341,5 @@
 
 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 +350,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 +380,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/async_sess.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/byteorder.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ddi.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -36,4 +36,6 @@
 #define LIBC_DDI_H_
 
+#include <sys/types.h>
+#include <kernel/ddi/irq.h>
 #include <task.h>
 
@@ -42,6 +44,6 @@
 extern int iospace_enable(task_id_t, void *, unsigned long);
 extern int pio_enable(void *, size_t, void **);
-extern int interrupt_enable(int);
-extern int interrupt_disable(int);
+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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/devman.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -41,5 +41,4 @@
 #include <bool.h>
 
-
 extern int devman_get_phone(devman_interface_t, unsigned int);
 extern void devman_hangup_phone(devman_interface_t);
Index: uspace/lib/c/include/err.h
===================================================================
--- uspace/lib/c/include/err.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/err.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/errno.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -39,7 +39,7 @@
 #include <fibril.h>
 
+#define errno _errno
+
 extern int _errno;
-
-#define errno _errno
 
 #define EMFILE        (-18)
@@ -57,36 +57,35 @@
 
 /** 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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/event.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/io/console.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/io/screenbuffer.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/adb.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/arp.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -39,5 +39,4 @@
 #define LIBC_ARP_MESSAGES_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
@@ -69,12 +68,10 @@
 /*@{*/
 
-/** Returns the protocol service message parameter.
- * @param[in] call The message call structure.
+/** Return the protocol service message parameter.
+ *
+ * @param[in] call Message call structure.
+ *
  */
-#define ARP_GET_NETIF(call) \
-	({ \
-		services_t service = (services_t) IPC_GET_ARG2(*call); \
-		service; \
-	})
+#define ARP_GET_NETIF(call) ((services_t) IPC_GET_ARG2(call))
 
 /*@}*/
Index: uspace/lib/c/include/ipc/bd.h
===================================================================
--- uspace/lib/c/include/ipc/bd.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/bd.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/char.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/clipboard.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/c/include/ipc/common.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/console.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/devman.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -30,15 +30,14 @@
  * @{
  */
- 
+
 #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;
@@ -67,6 +66,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 +83,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 +96,5 @@
 	}
 	
-	list_insert_before(&id->link, link);	
+	list_insert_before(&id->link, link);
 }
 
Index: uspace/lib/c/include/ipc/devmap.h
===================================================================
--- uspace/lib/c/include/ipc/devmap.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/devmap.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/fb.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/icmp.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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,95 +68,67 @@
 	
 	/**
-	 * 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 */
 /*@{*/
 
-/** Returns the ICMP code message parameter.
+/** Return the ICMP code message parameter.
  *
- * @param[in] call	The message call structure.
+ * @param[in] call Message call structure.
+ *
  */
-#define ICMP_GET_CODE(call) \
-	({ \
-		icmp_code_t code = (icmp_code_t) IPC_GET_ARG1(*call); \
-		code; \
-	})
+#define ICMP_GET_CODE(call)  ((icmp_code_t) IPC_GET_ARG1(call))
 
-/** Returns the ICMP link MTU message parameter.
+/** Return the ICMP link MTU message parameter.
  *
- * @param[in] call	The message call structure.
+ * @param[in] call Message call structure.
+ *
  */
-#define ICMP_GET_MTU(call) \
-	({ \
-		icmp_param_t mtu = (icmp_param_t) IPC_GET_ARG3(*call); \
-		mtu; \
-	})
+#define ICMP_GET_MTU(call)  ((icmp_param_t) IPC_GET_ARG3(call))
 
-/** Returns the pointer message parameter.
+/** Return the pointer message parameter.
  *
- * @param[in] call	The message call structure.
+ * @param[in] call Message call structure.
+ *
  */
-#define ICMP_GET_POINTER(call) \
-	({ \
-		icmp_param_t pointer = (icmp_param_t) IPC_GET_ARG3(*call); \
-		pointer; \
-	})
+#define ICMP_GET_POINTER(call)  ((icmp_param_t) IPC_GET_ARG3(call))
 
-/** Returns the size message parameter.
+/** Return the size message parameter.
  *
- * @param[in] call	The message call structure.
+ * @param[in] call Message call structure.
+ *
  */
-#define ICMP_GET_SIZE(call) \
-	({ \
-		size_t size = (size_t) IPC_GET_ARG1(call); \
-		size; \
-	})
+#define ICMP_GET_SIZE(call)  ((size_t) IPC_GET_ARG1(call))
 
-/** Returns the timeout message parameter.
+/** Return the timeout message parameter.
  *
- * @param[in] call	The message call structure.
+ * @param[in] call Message call structure.
+ *
  */
-#define ICMP_GET_TIMEOUT(call) \
-	({ \
-		suseconds_t timeout = (suseconds_t) IPC_GET_ARG2(call); \
-		timeout; \
-	})
+#define ICMP_GET_TIMEOUT(call)  ((suseconds_t) IPC_GET_ARG2(call))
 
-/** Returns the time to live message parameter.
+/** Return the time to live message parameter.
  *
- * @param[in] call	The message call structure.
+ * @param[in] call Message call structure.
+ *
  */
-#define ICMP_GET_TTL(call) \
-	({ \
-		ip_ttl_t ttl = (ip_ttl_t) IPC_GET_ARG3(call); \
-		ttl; \
-	})
+#define ICMP_GET_TTL(call)  ((ip_ttl_t) IPC_GET_ARG3(call))
 
-/** Returns the type of service message parameter.
+/** Return the type of service message parameter.
  *
- * @param[in] call	The message call structure.
+ * @param[in] call Message call structure.
+ *
  */
-#define ICMP_GET_TOS(call) \
-	({ \
-		ip_tos_t tos = (ip_tos_t) IPC_GET_ARG4(call); \
-		tos; \
-	})
+#define ICMP_GET_TOS(call)  ((ip_tos_t) IPC_GET_ARG4(call))
 
-/** Returns the dont fragment message parameter.
+/** Return the dont fragment message parameter.
  *
- * @param[in] call	The message call structure.
+ * @param[in] call Message call structure.
  */
-#define ICMP_GET_DONT_FRAGMENT(call) \
-	({ \
-		int dont_fragment = (int) IPC_GET_ARG5(call); \
-		dont_fragment; \
-	})
+#define ICMP_GET_DONT_FRAGMENT(call)  ((int) IPC_GET_ARG5(call))
 
 /*@}*/
Index: uspace/lib/c/include/ipc/il.h
===================================================================
--- uspace/lib/c/include/ipc/il.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/il.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -33,5 +33,5 @@
 /** @file
  * Internetwork layer modules messages.
- * @see il_interface.h
+ * @see il_remote.h
  * @see ip_interface.h
  */
@@ -40,33 +40,22 @@
 #define LIBC_IL_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
 /** Internet layer modules messages. */
 typedef enum {
-	/** New device message.
-	 * @see ip_device_req()
-	 */
-	NET_IL_DEVICE = NET_IL_FIRST,
 	/** Device state changed message.
 	 * @see il_device_state_msg()
 	 */
-	NET_IL_DEVICE_STATE,
+	NET_IL_DEVICE_STATE = NET_IL_FIRST,
+	
 	/** Device MTU changed message.
 	 * @see il_mtu_changed_msg()
 	 */
 	NET_IL_MTU_CHANGED,
-	/** Packet size message.
-	 * @see il_packet_size_req()
-	 */
-	NET_IL_PACKET_SPACE,
+	
 	/** Packet received message.
 	 * @see il_received_msg()
 	 */
-	NET_IL_RECEIVED,
-	/** Packet send message.
-	 * @see il_send_msg()
-	 */
-	NET_IL_SEND
+	NET_IL_RECEIVED
 } il_messages;
 
@@ -75,12 +64,16 @@
 
 /** Return the protocol number message parameter.
- * @param[in] call The message call structure.
+ *
+ * @param[in] call Message call structure.
+ *
  */
-#define IL_GET_PROTO(call)	(int) IPC_GET_ARG1(*call)
+#define IL_GET_PROTO(call)  ((int) IPC_GET_ARG1(call))
 
 /** Return the registering service message parameter.
- * @param[in] call The message call structure.
+ *
+ * @param[in] call Message call structure.
+ *
  */
-#define IL_GET_SERVICE(call)	(services_t) IPC_GET_ARG2(*call)
+#define IL_GET_SERVICE(call)  ((services_t) IPC_GET_ARG2(call))
 
 /*@}*/
Index: uspace/lib/c/include/ipc/ip.h
===================================================================
--- uspace/lib/c/include/ipc/ip.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/ip.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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>
@@ -47,20 +45,38 @@
 /** IP module messages. */
 typedef enum {
+	/** New device message.
+	 * @see ip_device_req()
+	 */
+	NET_IP_DEVICE = NET_IP_FIRST,
+	
 	/** Adds the routing entry.
 	 * @see ip_add_route()
 	 */
-	NET_IP_ADD_ROUTE = NET_IP_FIRST,
+	NET_IP_ADD_ROUTE,
+	
 	/** Gets the actual route information.
 	 * @see ip_get_route()
 	 */
 	NET_IP_GET_ROUTE,
+	
 	/** Processes the received error notification.
 	 * @see ip_received_error_msg()
 	 */
 	NET_IP_RECEIVED_ERROR,
+	
 	/** Sets the default gateway.
 	 * @see ip_set_default_gateway()
 	 */
-	NET_IP_SET_GATEWAY
+	NET_IP_SET_GATEWAY,
+	
+	/** Packet size message.
+	 * @see ip_packet_size_req()
+	 */
+	NET_IP_PACKET_SPACE,
+	
+	/** Packet send message.
+	 * @see ip_send_msg()
+	 */
+	NET_IP_SEND
 } ip_messages;
 
@@ -68,51 +84,53 @@
 /*@{*/
 
-/** Returns the address message parameter.
- * @param[in] call The message call structure.
+/** Return the address message parameter.
+ *
+ * @param[in] call Message call structure.
+ *
  */
 #define IP_GET_ADDRESS(call) \
 	({ \
 		in_addr_t addr; \
-		addr.s_addr = IPC_GET_ARG3(*call); \
+		addr.s_addr = IPC_GET_ARG3(call); \
 		addr; \
 	})
 
-/** Returns the gateway message parameter.
- * @param[in] call The message call structure.
+/** Return the gateway message parameter.
+ *
+ * @param[in] call Message call structure.
+ *
  */
 #define IP_GET_GATEWAY(call) \
 	({ \
 		in_addr_t addr; \
-		addr.s_addr = IPC_GET_ARG2(*call); \
+		addr.s_addr = IPC_GET_ARG2(call); \
 		addr; \
 	})
 
-/** Sets the header length in the message answer.
- * @param[out] answer The message answer structure.
+/** Set the header length in the message answer.
+ *
+ * @param[out] answer Message answer structure.
+ *
  */
-#define IP_SET_HEADERLEN(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG2(*answer, argument); \
-	} while (0)
+#define IP_SET_HEADERLEN(answer, value)  IPC_SET_ARG2(answer, (sysarg_t) (value))
 
-/** Returns the network mask message parameter.
- * @param[in] call The message call structure.
+/** Return the network mask message parameter.
+ *
+ * @param[in] call Message call structure.
+ *
  */
 #define IP_GET_NETMASK(call) \
 	({ \
 		in_addr_t addr; \
-		addr.s_addr = IPC_GET_ARG4(*call); \
+		addr.s_addr = IPC_GET_ARG4(call); \
 		addr; \
 	})
 
-/** Returns the protocol message parameter.
- * @param[in] call The message call structure.
+/** Return the protocol message parameter.
+ *
+ * @param[in] call Message call structure.
+ *
  */
-#define IP_GET_PROTOCOL(call) \
-	({ \
-		ip_protocol_t protocol = (ip_protocol_t) IPC_GET_ARG1(*call); \
-		protocol; \
-	})
+#define IP_GET_PROTOCOL(call)  ((ip_protocol_t) IPC_GET_ARG1(call))
 
 /*@}*/
Index: uspace/lib/c/include/ipc/ipc.h
===================================================================
--- uspace/lib/c/include/ipc/ipc.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/ipc.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/irc.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/kbd.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -38,5 +38,5 @@
 #define LIBC_IPC_KBD_H_
 
-#include <ipc/ipc.h>
+#include <ipc/common.h>
 
 typedef enum {
Index: uspace/lib/c/include/ipc/loader.h
===================================================================
--- uspace/lib/c/include/ipc/loader.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/loader.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/mouse.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/net.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -38,14 +38,14 @@
 #define LIBC_NET_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <net/packet.h>
 
-/** Returns a value indicating whether the value is in the interval.
- * @param[in] item	The value to be checked.
- * @param[in] first_inclusive The first value in the interval inclusive.
- * @param[in] last_exclusive The first value after the interval.
+/** Return a value indicating whether the value is in the interval.
+ *
+ * @param[in] item            Value to be checked.
+ * @param[in] first_inclusive First value in the interval inclusive.
+ * @param[in] last_exclusive  First value after the interval.
+ *
  */
 #define IS_IN_INTERVAL(item, first_inclusive, last_exclusive) \
@@ -55,42 +55,17 @@
 /*@{*/
 
-/** The number of ARP messages. */
-#define NET_ARP_COUNT		5
-
-/** The number of Ethernet messages. */
-#define NET_ETH_COUNT		0
-
-/** The number of ICMP messages. */
-#define NET_ICMP_COUNT		6
-
-/** The number of inter-network messages. */
-#define NET_IL_COUNT		6
-
-/** The number of IP messages. */
-#define NET_IP_COUNT		4
-
-/** The number of general networking messages. */
-#define NET_NET_COUNT		3
-
-/** The number of network interface driver messages. */
-#define NET_NETIF_COUNT		6
-
-/** The number of network interface layer messages. */
-#define NET_NIL_COUNT		7
-
-/** The number of packet management system messages. */
-#define NET_PACKET_COUNT	5
-
-/** The number of socket messages. */
-#define NET_SOCKET_COUNT	14
-
-/** The number of TCP messages. */
-#define NET_TCP_COUNT		0
-
-/** The number of transport layer messages. */
-#define NET_TL_COUNT		1
-
-/** The number of UDP messages. */
-#define NET_UDP_COUNT		0
+#define NET_ARP_COUNT     5   /**< Number of ARP messages. */
+#define NET_ETH_COUNT     0   /**< Number of Ethernet messages. */
+#define NET_ICMP_COUNT    6   /**< Number of ICMP messages. */
+#define NET_IL_COUNT      6   /**< Number of inter-network messages. */
+#define NET_IP_COUNT      4   /**< Number of IP messages. */
+#define NET_NET_COUNT     3   /**< Number of general networking messages. */
+#define NET_NETIF_COUNT   6   /**< Number of network interface driver messages. */
+#define NET_NIL_COUNT     7   /**< Number of network interface layer messages. */
+#define NET_PACKET_COUNT  5   /**< Number of packet management system messages. */
+#define NET_SOCKET_COUNT  14  /**< Number of socket messages. */
+#define NET_TCP_COUNT     0   /**< Number of TCP messages. */
+#define NET_TL_COUNT      1   /**< Number of transport layer messages. */
+#define NET_UDP_COUNT     0   /**< Number of UDP messages. */
 
 /*@}*/
@@ -100,173 +75,195 @@
 /*@{*/
 
-/** The first networking message. */
-#define NET_FIRST		2000
-
-/** The first network interface layer message. */
-#define NET_NETIF_FIRST		NET_FIRST
-
-/** The last network interface layer message. */
-#define NET_NETIF_LAST		(NET_NETIF_FIRST + NET_NETIF_COUNT)
-
-/** The first general networking message. */
-#define NET_NET_FIRST		(NET_NETIF_LAST + 0)
-
-/** The last general networking message. */
-#define NET_NET_LAST		(NET_NET_FIRST + NET_NET_COUNT)
-
-/** The first network interface layer message. */
-#define NET_NIL_FIRST		(NET_NET_LAST + 0)
-
-/** The last network interface layer message. */
-#define NET_NIL_LAST		(NET_NIL_FIRST + NET_NIL_COUNT)
-
-/** The first Ethernet message. */
-#define NET_ETH_FIRST		(NET_NIL_LAST + 0)
-
-/** The last Ethernet message. */
-#define NET_ETH_LAST		(NET_ETH_FIRST + NET_ETH_COUNT)
-
-/** The first inter-network message. */
-#define NET_IL_FIRST		(NET_ETH_LAST + 0)
-
-/** The last inter-network message. */
-#define NET_IL_LAST		(NET_IL_FIRST + NET_IL_COUNT)
-
-/** The first IP message. */
-#define NET_IP_FIRST		(NET_IL_LAST + 0)
-
-/** The last IP message. */
-#define NET_IP_LAST		(NET_IP_FIRST + NET_IP_COUNT)
-
-/** The first ARP message. */
-#define NET_ARP_FIRST		(NET_IP_LAST + 0)
-
-/** The last ARP message. */
-#define NET_ARP_LAST		(NET_ARP_FIRST + NET_ARP_COUNT)
-
-/** The first ICMP message. */
-#define NET_ICMP_FIRST		(NET_ARP_LAST + 0)
-
-/** The last ICMP message. */
-#define NET_ICMP_LAST		(NET_ICMP_FIRST + NET_ICMP_COUNT)
-
-/** The first ICMP message. */
-#define NET_TL_FIRST		(NET_ICMP_LAST + 0)
-
-/** The last ICMP message. */
-#define NET_TL_LAST		(NET_TL_FIRST + NET_TL_COUNT)
-
-/** The first UDP message. */
-#define NET_UDP_FIRST		(NET_TL_LAST + 0)
-
-/** The last UDP message. */
-#define NET_UDP_LAST		(NET_UDP_FIRST + NET_UDP_COUNT)
-
-/** The first TCP message. */
-#define NET_TCP_FIRST		(NET_UDP_LAST + 0)
-
-/** The last TCP message. */
-#define NET_TCP_LAST		(NET_TCP_FIRST + NET_TCP_COUNT)
-
-/** The first socket message. */
-#define NET_SOCKET_FIRST	(NET_TCP_LAST + 0)
-
-/** The last socket message. */
-#define NET_SOCKET_LAST		(NET_SOCKET_FIRST + NET_SOCKET_COUNT)
-
-/** The first packet management system message. */
-#define NET_PACKET_FIRST	(NET_SOCKET_LAST + 0)
-
-/** The last packet management system message. */
-#define NET_PACKET_LAST		(NET_PACKET_FIRST + NET_PACKET_COUNT)
-
-/** The last networking message. */
-#define NET_LAST		NET_PACKET_LAST
-
-/** The number of networking messages. */
-#define NET_COUNT		(NET_LAST - NET_FIRST)
-
-/** Returns a value indicating whether the IPC call is a generic networking
- * message.
- * @param[in] call The IPC call to be checked.
+
+/** First networking message. */
+#define NET_FIRST  2000
+
+/** First network interface layer message. */
+#define NET_NETIF_FIRST  NET_FIRST
+
+/** Last network interface layer message. */
+#define NET_NETIF_LAST  (NET_NETIF_FIRST + NET_NETIF_COUNT)
+
+/** First general networking message. */
+#define NET_NET_FIRST  (NET_NETIF_LAST + 0)
+
+/** Last general networking message. */
+#define NET_NET_LAST  (NET_NET_FIRST + NET_NET_COUNT)
+
+/** First network interface layer message. */
+#define NET_NIL_FIRST  (NET_NET_LAST + 0)
+
+/** Last network interface layer message. */
+#define NET_NIL_LAST  (NET_NIL_FIRST + NET_NIL_COUNT)
+
+/** First Ethernet message. */
+#define NET_ETH_FIRST  (NET_NIL_LAST + 0)
+
+/** Last Ethernet message. */
+#define NET_ETH_LAST  (NET_ETH_FIRST + NET_ETH_COUNT)
+
+/** First inter-network message. */
+#define NET_IL_FIRST  (NET_ETH_LAST + 0)
+
+/** Last inter-network message. */
+#define NET_IL_LAST  (NET_IL_FIRST + NET_IL_COUNT)
+
+/** First IP message. */
+#define NET_IP_FIRST  (NET_IL_LAST + 0)
+
+/** Last IP message. */
+#define NET_IP_LAST  (NET_IP_FIRST + NET_IP_COUNT)
+
+/** First ARP message. */
+#define NET_ARP_FIRST  (NET_IP_LAST + 0)
+
+/** Last ARP message. */
+#define NET_ARP_LAST  (NET_ARP_FIRST + NET_ARP_COUNT)
+
+/** First ICMP message. */
+#define NET_ICMP_FIRST  (NET_ARP_LAST + 0)
+
+/** Last ICMP message. */
+#define NET_ICMP_LAST  (NET_ICMP_FIRST + NET_ICMP_COUNT)
+
+/** First ICMP message. */
+#define NET_TL_FIRST  (NET_ICMP_LAST + 0)
+
+/** Last ICMP message. */
+#define NET_TL_LAST  (NET_TL_FIRST + NET_TL_COUNT)
+
+/** First UDP message. */
+#define NET_UDP_FIRST  (NET_TL_LAST + 0)
+
+/** Last UDP message. */
+#define NET_UDP_LAST  (NET_UDP_FIRST + NET_UDP_COUNT)
+
+/** First TCP message. */
+#define NET_TCP_FIRST  (NET_UDP_LAST + 0)
+
+/** Last TCP message. */
+#define NET_TCP_LAST  (NET_TCP_FIRST + NET_TCP_COUNT)
+
+/** First socket message. */
+#define NET_SOCKET_FIRST  (NET_TCP_LAST + 0)
+
+/** Last socket message. */
+#define NET_SOCKET_LAST  (NET_SOCKET_FIRST + NET_SOCKET_COUNT)
+
+/** First packet management system message. */
+#define NET_PACKET_FIRST  (NET_SOCKET_LAST + 0)
+
+/** Last packet management system message. */
+#define NET_PACKET_LAST  (NET_PACKET_FIRST + NET_PACKET_COUNT)
+
+/** Last networking message. */
+#define NET_LAST  NET_PACKET_LAST
+
+/** Number of networking messages. */
+#define NET_COUNT  (NET_LAST - NET_FIRST)
+
+/** Check if the IPC call is a generic networking message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_FIRST, NET_LAST)
-
-/** Returns a value indicating whether the IPC call is an ARP message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_FIRST, NET_LAST)
+
+/** Check if the IPC call is an ARP message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_ARP_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_ARP_FIRST, NET_ARP_LAST)
-
-/** Returns a value indicating whether the IPC call is an Ethernet message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_ARP_FIRST, NET_ARP_LAST)
+
+/** Check if the IPC call is an Ethernet message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_ETH_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_ETH_FIRST, NET_ETH_LAST)
-
-/** Returns a value indicating whether the IPC call is an ICMP message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_ETH_FIRST, NET_ETH_LAST)
+
+/** Check if the IPC call is an ICMP message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_ICMP_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_ICMP_FIRST, NET_ICMP_LAST)
-
-/** Returns a value indicating whether the IPC call is an inter-network layer
- * message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_ICMP_FIRST, NET_ICMP_LAST)
+
+/** Check if the IPC call is an inter-network layer message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_IL_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_IL_FIRST, NET_IL_LAST)
-
-/** Returns a value indicating whether the IPC call is an IP message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_IL_FIRST, NET_IL_LAST)
+
+/** Check if the IPC call is an IP message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_IP_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_IP_FIRST, NET_IP_LAST)
-
-/** Returns a value indicating whether the IPC call is a generic networking
- * message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_IP_FIRST, NET_IP_LAST)
+
+/** Check if the IPC call is a generic networking message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_NET_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_NET_FIRST, NET_NET_LAST)
-
-/** Returns a value indicating whether the IPC call is a network interface layer
- * message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_NET_FIRST, NET_NET_LAST)
+
+/** Check if the IPC call is a network interface layer message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_NIL_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_NIL_FIRST, NET_NIL_LAST)
-
-/** Returns a value indicating whether the IPC call is a packet manaagement
- * system message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_NIL_FIRST, NET_NIL_LAST)
+
+/** Check if the IPC call is a packet manaagement system message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_PACKET_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_PACKET_FIRST, NET_PACKET_LAST)
-
-/** Returns a value indicating whether the IPC call is a socket message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_PACKET_FIRST, NET_PACKET_LAST)
+
+/** Check if the IPC call is a socket message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_SOCKET_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_SOCKET_FIRST, NET_SOCKET_LAST)
-
-/** Returns a value indicating whether the IPC call is a TCP message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_SOCKET_FIRST, NET_SOCKET_LAST)
+
+/** Check if the IPC call is a TCP message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_TCP_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_TCP_FIRST, NET_TCP_LAST)
-
-/** Returns a value indicating whether the IPC call is a transport layer message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_TCP_FIRST, NET_TCP_LAST)
+
+/** Check if the IPC call is a transport layer message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_TL_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_TL_FIRST, NET_TL_LAST)
-
-/** Returns a value indicating whether the IPC call is a UDP message.
- * @param[in] call The IPC call to be checked.
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_TL_FIRST, NET_TL_LAST)
+
+/** Check if the IPC call is a UDP message.
+ *
+ * @param[in] call IPC call to be checked.
+ *
  */
 #define IS_NET_UDP_MESSAGE(call) \
-	IS_IN_INTERVAL(IPC_GET_IMETHOD(*call), NET_UDP_FIRST, NET_UDP_LAST)
+	IS_IN_INTERVAL(IPC_GET_IMETHOD(call), NET_UDP_FIRST, NET_UDP_LAST)
 
 /*@}*/
@@ -275,138 +272,113 @@
 /*@{*/
 
-/** Returns the device identifier message argument.
- * @param[in] call The message call structure.
- */
-#define IPC_GET_DEVICE(call) \
-	({ \
-		device_id_t device_id = (device_id_t) IPC_GET_ARG1(*call); \
-		device_id; \
-	})
-
-/** Returns the packet identifier message argument.
- * @param[in] call The message call structure.
- */
-#define IPC_GET_PACKET(call) \
-	({ \
-		packet_id_t packet_id = (packet_id_t) IPC_GET_ARG2(*call); \
-		packet_id; \
-	})
-
-/** Returns the count message argument.
- * @param[in] call The message call structure.
- */
-#define IPC_GET_COUNT(call) \
-	({ \
-		size_t size = (size_t) IPC_GET_ARG2(*call); \
-		size; \
-	})
-
-/** Returns the device state message argument.
- * @param[in] call The message call structure.
- */
-#define IPC_GET_STATE(call) \
-	({ \
-		device_state_t state = (device_state_t) IPC_GET_ARG2(*call); \
-		state; \
-	})
-
-/** Returns the maximum transmission unit message argument.
- * @param[in] call The message call structure.
- */
-#define IPC_GET_MTU(call) \
-	({ \
-		size_t size = (size_t) IPC_GET_ARG2(*call); \
-		size; \
-	})
-
-/** Returns the device driver service message argument.
- * @param[in] call The message call structure.
- */
-#define IPC_GET_SERVICE(call) \
-	({ \
-		services_t service = (services_t) IPC_GET_ARG3(*call); \
-		service; \
-	})
-
-/** Returns the target service message argument.
- * @param[in] call The message call structure.
- */
-#define IPC_GET_TARGET(call) \
-	({ \
-		services_t service = (services_t) IPC_GET_ARG3(*call); \
-		service; \
-	})
-
-/** Returns the sender service message argument.
- * @param[in] call The message call structure.
- */
-#define IPC_GET_SENDER(call) \
-	({ \
-		services_t service = (services_t) IPC_GET_ARG3(*call); \
-		service; \
-	})
-
-/** Returns the error service message argument.
- * @param[in] call The message call structure.
- */
-#define IPC_GET_ERROR(call) \
-	({ \
-		services_t service = (services_t) IPC_GET_ARG4(*call); \
-		service; \
-	})
-
-/** Returns the phone message argument.
- * @param[in] call The message call structure.
- */
-#define IPC_GET_PHONE(call) \
-	({ \
-		int phone = (int) IPC_GET_ARG5(*call); \
-		phone; \
-	})
-
-/** Sets the device identifier in the message answer.
- * @param[out] answer The message answer structure.
- */
-#define IPC_SET_DEVICE(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG1(*answer, argument); \
-	} while (0)
-
-/** Sets the minimum address length in the message answer.
- * @param[out] answer The message answer structure.
- */
-#define IPC_SET_ADDR(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG1(*answer, argument); \
-	} while (0)
-
-/** Sets the minimum prefix size in the message answer.
- * @param[out] answer The message answer structure.
- */
-#define IPC_SET_PREFIX(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG2(*answer, argument); \
-	} while (0)
-
-/** Sets the maximum content size in the message answer.
- * @param[out] answer The message answer structure.
- */
-#define IPC_SET_CONTENT(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG3(*answer, argument); \
-	} while (0)
-
-/** Sets the minimum suffix size in the message answer.
- * @param[out] answer The message answer structure.
- */
-#define IPC_SET_SUFFIX(answer, value) \
-	do { \
-		sysarg_t argument = (sysarg_t) (value); \
-		IPC_SET_ARG4(*answer, argument); \
-	} while (0)
+/** Return the device identifier message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_DEVICE(call)  ((device_id_t) IPC_GET_ARG1(call))
+
+/** Return the packet identifier message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_PACKET(call)  ((packet_id_t) IPC_GET_ARG2(call))
+
+/** Return the count message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_COUNT(call)  ((size_t) IPC_GET_ARG2(call))
+
+/** Return the device state message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_STATE(call)  ((device_state_t) IPC_GET_ARG2(call))
+
+/** Return the maximum transmission unit message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_MTU(call)  ((size_t) IPC_GET_ARG2(call))
+
+/** Return the device driver service message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_SERVICE(call)  ((services_t) IPC_GET_ARG3(call))
+
+/** Return the target service message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_TARGET(call)  ((services_t) IPC_GET_ARG3(call))
+
+/** Return the sender service message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_SENDER(call)  ((services_t) IPC_GET_ARG3(call))
+
+/** Return the error service message argument.
+ &
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_ERROR(call)  ((services_t) IPC_GET_ARG4(call))
+
+/** Return the phone message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_PHONE(call)  ((int) IPC_GET_ARG5(call))
+
+/** Set the device identifier in the message answer.
+ *
+ * @param[out] answer Message answer structure.
+ * @param[in]  value  Value to set.
+ *
+ */
+#define IPC_SET_DEVICE(answer, value)  IPC_SET_ARG1(answer, (sysarg_t) (value))
+
+/** Set the minimum address length in the message answer.
+ *
+ * @param[out] answer Message answer structure.
+ * @param[in]  value  Value to set.
+ *
+ */
+#define IPC_SET_ADDR(answer, value)  IPC_SET_ARG1(answer, (sysarg_t) (value))
+
+/** Set the minimum prefix size in the message answer.
+ *
+ * @param[out] answer Message answer structure.
+ * @param[in]  value  Value to set.
+ *
+ */
+#define IPC_SET_PREFIX(answer, value)  IPC_SET_ARG2(answer, (sysarg_t) (value))
+
+/** Set the maximum content size in the message answer.
+ *
+ * @param[out] answer Message answer structure.
+ * @param[in]  value  Value to set.
+ *
+ */
+#define IPC_SET_CONTENT(answer, value)  IPC_SET_ARG3(answer, (sysarg_t) (value))
+
+/** Set the minimum suffix size in the message answer.
+ *
+ * @param[out] answer Message answer structure.
+ * @param[in]  value  Value to set.
+ *
+ */
+#define IPC_SET_SUFFIX(answer, value)  IPC_SET_ARG4(answer, (sysarg_t) (value))
 
 /*@}*/
Index: uspace/lib/c/include/ipc/net_net.h
===================================================================
--- uspace/lib/c/include/ipc/net_net.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/net_net.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/netif.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -38,5 +38,4 @@
 #define LIBC_NETIF_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
@@ -47,20 +46,25 @@
 	 */
 	NET_NETIF_PROBE = NET_NETIF_FIRST,
+	
 	/** Send packet message.
 	 * @see netif_send_msg()
 	 */
 	NET_NETIF_SEND,
+	
 	/** Start device message.
 	 * @see netif_start_req()
 	 */
 	NET_NETIF_START,
+	
 	/** Get device usage statistics message.
 	 * @see netif_stats_req()
 	 */
 	NET_NETIF_STATS,
+	
 	/** Stop device message.
 	 * @see netif_stop_req()
 	 */
 	NET_NETIF_STOP,
+	
 	/** Get device address message.
 	 * @see netif_get_addr_req()
@@ -73,20 +77,16 @@
 
 /** Return the interrupt number message parameter.
- * @param[in] call The message call structure.
+ *
+ * @param[in] call Mmessage call structure.
+ *
  */
-#define NETIF_GET_IRQ(call) \
-	({ \
-		int irq = (int) IPC_GET_ARG2(*call); \
-		irq; \
-	})
+#define NETIF_GET_IRQ(call) ((int) IPC_GET_ARG2(call))
 
 /** Return the input/output address message parameter.
- * @param[in] call The message call structure.
+ *
+ * @param[in] call Message call structure.
+ *
  */
-#define NETIF_GET_IO(call) \
-	({ \
-		int io = (int) IPC_GET_ARG3(*call); \
-		io; \
-	})
+#define NETIF_GET_IO(call) ((void *) IPC_GET_ARG3(call))
 
 /*@}*/
Index: uspace/lib/c/include/ipc/nil.h
===================================================================
--- uspace/lib/c/include/ipc/nil.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/nil.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -38,5 +38,4 @@
 #define LIBC_NIL_MESSAGES_H_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
@@ -77,9 +76,5 @@
 
 /** Return the protocol service message parameter. */
-#define NIL_GET_PROTO(call) \
-	({ \
-		services_t service = (services_t) IPC_GET_ARG2(*call); \
-		service; \
-	})
+#define NIL_GET_PROTO(call)  ((services_t) IPC_GET_ARG2(call))
 
 /*@}*/
Index: uspace/lib/c/include/ipc/ns.h
===================================================================
--- uspace/lib/c/include/ipc/ns.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/ns.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/packet.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -38,5 +38,4 @@
 #define LIBC_PACKET_MESSAGES_
 
-#include <ipc/ipc.h>
 #include <ipc/net.h>
 
@@ -70,21 +69,21 @@
 } packet_messages;
 
-/** Returns the protocol service message parameter. */
-#define ARP_GET_PROTO(call)	(services_t) IPC_GET_ARG2(*call)
+/** Return the protocol service message parameter. */
+#define ARP_GET_PROTO(call)  ((services_t) IPC_GET_ARG2(call))
 
-/** Returns the packet identifier message parameter. */
-#define IPC_GET_ID(call)	(packet_id_t) IPC_GET_ARG1(*call)
+/** Return the packet identifier message parameter. */
+#define IPC_GET_ID(call)  ((packet_id_t) IPC_GET_ARG1(call))
 
-/** Returns the maximal content length message parameter. */
-#define IPC_GET_CONTENT(call)	(size_t) IPC_GET_ARG1(*call)
+/** Return the maximal content length message parameter. */
+#define IPC_GET_CONTENT(call)  ((size_t) IPC_GET_ARG1(call))
 
-/** Returns the maximal address length message parameter. */
-#define IPC_GET_ADDR_LEN(call)	(size_t) IPC_GET_ARG2(*call)
+/** Return the maximal address length message parameter. */
+#define IPC_GET_ADDR_LEN(call)  ((size_t) IPC_GET_ARG2(call))
 
-/** Returns the maximal prefix length message parameter. */
-#define IPC_GET_PREFIX(call)	(size_t) IPC_GET_ARG3(*call)
+/** Return the maximal prefix length message parameter. */
+#define IPC_GET_PREFIX(call)  ((size_t) IPC_GET_ARG3(call))
 
-/** Returns the maximal suffix length message parameter. */
-#define IPC_GET_SUFFIX(call)	(size_t) IPC_GET_ARG4(*call)
+/** Return the maximal suffix length message parameter. */
+#define IPC_GET_SUFFIX(call)  ((size_t) IPC_GET_ARG4(call))
 
 #endif
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/services.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -35,6 +35,6 @@
  */
 
-#ifndef LIBIPC_SERVICES_H_
-#define LIBIPC_SERVICES_H_
+#ifndef LIBC_SERVICES_H_
+#define LIBC_SERVICES_H_
 
 typedef enum {
@@ -54,5 +54,5 @@
 	SERVICE_NETWORKING,
 	SERVICE_LO,
-	SERVICE_DP8390,
+	SERVICE_NE2000,
 	SERVICE_ETHERNET,
 	SERVICE_NILDUMMY,
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/socket.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/tl.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/ipc/vfs.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/libc.h
===================================================================
--- uspace/lib/c/include/libc.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/libc.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/loader/pcb.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/malloc.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -38,5 +38,4 @@
 #include <sys/types.h>
 
-extern void __heap_init(void);
 extern uintptr_t get_max_heap_addr(void);
 
Index: uspace/lib/c/include/net/icmp_common.h
===================================================================
--- uspace/lib/c/include/net/icmp_common.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/net/icmp_common.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/in.h
===================================================================
--- uspace/lib/c/include/net/in.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/net/in.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -43,10 +43,10 @@
 
 /** INET string address maximum length. */
-#define INET_ADDRSTRLEN		(4 * 3 + 3 + 1)
+#define INET_ADDRSTRLEN  (4 * 3 + 3 + 1)
 
 /** Type definition of the INET address.
  * @see in_addr
  */
-typedef struct in_addr		in_addr_t;
+typedef struct in_addr in_addr_t;
 
 /** Type definition of the INET socket address.
Index: uspace/lib/c/include/net/modules.h
===================================================================
--- uspace/lib/c/include/net/modules.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/net/modules.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -43,18 +43,17 @@
 
 #include <async.h>
-
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <sys/time.h>
 
 /** Connect to the needed module function type definition.
  *
- * @param[in] need	The needed module service.
- * @return		The phone of the needed service.
+ * @param[in] need The needed module service.
+ *
+ * @return The phone of the needed service.
+ *
  */
 typedef int connect_module_t(services_t need);
 
-extern void answer_call(ipc_callid_t, int, ipc_call_t *, int);
+extern void answer_call(ipc_callid_t, int, ipc_call_t *, size_t);
 extern int bind_service(services_t, sysarg_t, sysarg_t, sysarg_t,
     async_client_conn_t);
@@ -64,5 +63,5 @@
 extern int connect_to_service_timeout(services_t, suseconds_t);
 extern int data_reply(void *, size_t);
-extern void refresh_answer(ipc_call_t *, int *);
+extern void refresh_answer(ipc_call_t *, size_t *);
 
 #endif
Index: uspace/lib/c/include/setjmp.h
===================================================================
--- uspace/lib/c/include/setjmp.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/setjmp.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/stdlib.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/syscall.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/thread.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/tls.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/udebug.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/unistd.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -41,5 +41,5 @@
 
 #ifndef NULL
-	#define NULL	((void *) 0)
+	#define NULL  ((void *) 0)
 #endif
 
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/c/include/vfs/vfs.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/clui/tinput.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/drv/generic/driver.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -186,5 +186,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);
@@ -199,5 +199,5 @@
 	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) {
@@ -272,5 +272,5 @@
 	}
 	
-	ipc_answer_0(iid, res);
+	async_answer_0(iid, res);
 }
 
@@ -278,5 +278,5 @@
 {
 	/* Accept connection */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	bool cont = true;
@@ -293,5 +293,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOENT);
+			async_answer_0(callid, ENOENT);
 		}
 	}
@@ -316,5 +316,5 @@
 		printf("%s: driver_connection_gen error - no device with handle"
 		    " %" PRIun " was found.\n", driver->name, handle);
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
@@ -331,5 +331,5 @@
 		ret = (*dev->ops->open)(dev);
 	
-	ipc_answer_0(iid, ret);
+	async_answer_0(iid, ret);
 	if (ret != EOK)
 		return;
@@ -347,5 +347,5 @@
 			if (dev->ops != NULL && dev->ops->close != NULL)
 				(*dev->ops->close)(dev);
-			ipc_answer_0(callid, EOK);
+			async_answer_0(callid, EOK);
 			return;
 		default:
@@ -368,5 +368,5 @@
 				    "invalid interface id %d.",
 				    driver->name, iface_idx);
-				ipc_answer_0(callid, ENOTSUP);
+				async_answer_0(callid, ENOTSUP);
 				break;
 			}
@@ -381,5 +381,5 @@
 				printf("device 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 +400,5 @@
 				printf("%s: driver_connection_gen error - "
 				    "invalid interface method.", driver->name);
-				ipc_answer_0(callid, ENOTSUP);
+				async_answer_0(callid, ENOTSUP);
 				break;
 			}
@@ -446,5 +446,5 @@
 	default:
 		/* No such interface */
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 	}
 }
Index: uspace/lib/drv/generic/remote_char_dev.c
===================================================================
--- uspace/lib/drv/generic/remote_char_dev.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/drv/generic/remote_char_dev.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -33,5 +33,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <async.h>
 #include <errno.h>
@@ -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;
 	}
@@ -100,5 +99,5 @@
 		/* 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);
 }
 
@@ -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;
 	}
@@ -148,5 +147,5 @@
 	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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/drv/generic/remote_hw_res.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -33,5 +33,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <async.h>
 #include <errno.h>
@@ -62,9 +61,9 @@
 	
 	if (hw_res_ops->enable_interrupt == NULL)
-		ipc_answer_0(callid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 	else if (hw_res_ops->enable_interrupt(dev))
-		ipc_answer_0(callid, EOK);
+		async_answer_0(callid, EOK);
 	else
-		ipc_answer_0(callid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
 }
 
@@ -75,5 +74,5 @@
 
 	if (hw_res_ops->get_resource_list == NULL) {
-		ipc_answer_0(callid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 		return;
 	}
@@ -81,9 +80,9 @@
 	hw_resource_list_t *hw_resources = hw_res_ops->get_resource_list(dev);
 	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/include/dev_iface.h
===================================================================
--- uspace/lib/drv/include/dev_iface.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/drv/include/dev_iface.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -36,4 +36,5 @@
 #define LIBDRV_DEV_IFACE_H_
 
+#include <ipc/common.h>
 #include <ipc/dev_iface.h>
 
Index: uspace/lib/drv/include/driver.h
===================================================================
--- uspace/lib/drv/include/driver.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/drv/include/driver.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -36,6 +36,6 @@
 #define LIBDRV_DRIVER_H_
 
+#include <kernel/ddi/irq.h>
 #include <adt/list.h>
-#include <ipc/ipc.h>
 #include <devman.h>
 #include <ipc/devman.h>
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/fs/libfs.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/fs/libfs.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/Makefile
===================================================================
--- uspace/lib/net/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -40,8 +40,10 @@
 	generic/protocol_map.c \
 	adt/module_map.c \
-	netif/netif_local.c \
 	netif/netif_remote.c \
+	netif/netif_skel.c \
 	nil/nil_remote.c \
-	il/il_interface.c \
+	nil/nil_skel.c \
+	il/il_remote.c \
+	il/il_skel.c \
 	il/ip_remote.c \
 	il/ip_client.c \
@@ -50,6 +52,7 @@
 	tl/icmp_client.c \
 	tl/socket_core.c \
-	tl/tl_interface.c \
-	tl/tl_common.c
+	tl/tl_common.c \
+	tl/tl_remote.c \
+	tl/tl_skel.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/net/generic/generic.c
===================================================================
--- uspace/lib/net/generic/generic.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/generic/generic.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/generic/packet_remote.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/generic/protocol_map.c
===================================================================
--- uspace/lib/net/generic/protocol_map.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/generic/protocol_map.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -50,5 +50,5 @@
 	switch (nil) {
 	case SERVICE_ETHERNET:
-	case SERVICE_DP8390:
+	case SERVICE_NE2000:
 		switch (il) {
 		case SERVICE_IP:
@@ -76,5 +76,5 @@
 	switch (nil) {
 	case SERVICE_ETHERNET:
-	case SERVICE_DP8390:
+	case SERVICE_NE2000:
 		switch (protocol) {
 		case ETH_P_IP:
@@ -139,5 +139,5 @@
 	switch (nil) {
 	case SERVICE_ETHERNET:
-	case SERVICE_DP8390:
+	case SERVICE_NE2000:
 		return HW_ETHER;
 	default:
Index: uspace/lib/net/il/arp_remote.c
===================================================================
--- uspace/lib/net/il/arp_remote.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/il/arp_remote.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -41,5 +41,4 @@
 #include <async.h>
 #include <errno.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/arp.h>
Index: pace/lib/net/il/il_interface.c
===================================================================
--- uspace/lib/net/il/il_interface.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,106 +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
- * @{
- */
-
-/** @file
- * Internetwork layer module interface for the underlying network interface
- * layer. This interface is always called by the remote modules.
- */
-
-#include <il_interface.h>
-#include <generic.h>
-#include <packet_client.h>
-
-#include <ipc/services.h>
-#include <ipc/il.h>
-
-#include <net/device.h>
-#include <net/packet.h>
-
-/** Notify the internetwork layer modules about the device state change.
- *
- * @param[in] il_phone  The internetwork layer module phone used for
- *                      (semi)remote calls.
- * @param[in] device_id The device identifier.
- * @param[in] state     The new device state.
- * @param[in] target    The target internetwork module service to be
- *                      delivered to.
- *
- * @return EOK on success.
- *
- */
-int il_device_state_msg(int il_phone, device_id_t device_id,
-    device_state_t state, services_t target)
-{
-	return generic_device_state_msg_remote(il_phone, NET_IL_DEVICE_STATE,
-	    device_id, state, target);
-}
-
-/** Notify the internetwork layer modules about the received packet/s.
- *
- * @param[in] il_phone  The internetwork layer module phone used for
- *                      (semi)remote calls.
- * @param[in] device_id The device identifier.
- * @param[in] packet    The received packet or the received packet queue.
- * @param[in] target    The target internetwork module service to be
- *                      delivered to.
- *
- * @return EOK on success.
- *
- */
-int il_received_msg(int il_phone, device_id_t device_id, packet_t *packet,
-    services_t target)
-{
-	return generic_received_msg_remote(il_phone, NET_IL_RECEIVED, device_id,
-	    packet_get_id(packet), target, 0);
-}
-
-/** Notify the internetwork layer modules about the mtu change.
- *
- * @param[in] il_phone  The internetwork layer module phone used for
- *                      (semi)remote calls.
- * @param[in] device_id The device identifier.
- * @param[in] mtu       The new mtu value.
- * @param[in] target    The target internetwork module service to be
- *                      delivered to.
- *
- * @return EOK on success.
- *
- */
-int il_mtu_changed_msg(int il_phone, device_id_t device_id, size_t mtu,
-    services_t target)
-{
-	return generic_device_state_msg_remote(il_phone, NET_IL_MTU_CHANGED,
-	    device_id, (int) mtu, target);
-}
-
-/** @}
- */
Index: uspace/lib/net/il/il_remote.c
===================================================================
--- uspace/lib/net/il/il_remote.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/il/il_remote.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,106 @@
+/*
+ * 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
+ * @{
+ */
+
+/** @file
+ * Internetwork layer module interface for the underlying network interface
+ * layer.
+ */
+
+#include <il_remote.h>
+#include <generic.h>
+#include <packet_client.h>
+
+#include <ipc/services.h>
+#include <ipc/il.h>
+
+#include <net/device.h>
+#include <net/packet.h>
+
+/** Notify the internetwork layer modules about the device state change.
+ *
+ * @param[in] il_phone  The internetwork layer module phone used for
+ *                      (semi)remote calls.
+ * @param[in] device_id The device identifier.
+ * @param[in] state     The new device state.
+ * @param[in] target    The target internetwork module service to be
+ *                      delivered to.
+ *
+ * @return EOK on success.
+ *
+ */
+int il_device_state_msg(int il_phone, device_id_t device_id,
+    device_state_t state, services_t target)
+{
+	return generic_device_state_msg_remote(il_phone, NET_IL_DEVICE_STATE,
+	    device_id, state, target);
+}
+
+/** Notify the internetwork layer modules about the received packet/s.
+ *
+ * @param[in] il_phone  The internetwork layer module phone used for
+ *                      (semi)remote calls.
+ * @param[in] device_id The device identifier.
+ * @param[in] packet    The received packet or the received packet queue.
+ * @param[in] target    The target internetwork module service to be
+ *                      delivered to.
+ *
+ * @return EOK on success.
+ *
+ */
+int il_received_msg(int il_phone, device_id_t device_id, packet_t *packet,
+    services_t target)
+{
+	return generic_received_msg_remote(il_phone, NET_IL_RECEIVED, device_id,
+	    packet_get_id(packet), target, 0);
+}
+
+/** Notify the internetwork layer modules about the mtu change.
+ *
+ * @param[in] il_phone  The internetwork layer module phone used for
+ *                      (semi)remote calls.
+ * @param[in] device_id The device identifier.
+ * @param[in] mtu       The new mtu value.
+ * @param[in] target    The target internetwork module service to be
+ *                      delivered to.
+ *
+ * @return EOK on success.
+ *
+ */
+int il_mtu_changed_msg(int il_phone, device_id_t device_id, size_t mtu,
+    services_t target)
+{
+	return generic_device_state_msg_remote(il_phone, NET_IL_MTU_CHANGED,
+	    device_id, (int) mtu, target);
+}
+
+/** @}
+ */
Index: uspace/lib/net/il/il_skel.c
===================================================================
--- uspace/lib/net/il/il_skel.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/il/il_skel.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,129 @@
+/*
+ * 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 libnet
+ * @{
+ */
+
+/** @file
+ * Internetworking layer module skeleton implementation.
+ * @see il_skel.h
+ */
+
+#include <bool.h>
+#include <errno.h>
+#include <il_skel.h>
+#include <net_interface.h>
+#include <net/modules.h>
+
+/** Default thread for new connections.
+ *
+ * @param[in] iid   The initial message identifier.
+ * @param[in] icall The initial message call structure.
+ *
+ */
+static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/*
+	 * Accept the connection by answering
+	 * the initial IPC_M_CONNECT_ME_TO call.
+	 */
+	async_answer_0(iid, EOK);
+	
+	while (true) {
+		ipc_call_t answer;
+		size_t count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = il_module_message(callid, &call, &answer,
+		    &count);
+		
+		/*
+		 * End if told to either by the message or the processing
+		 * result.
+		 */
+		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
+		    (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, count);
+	}
+}
+
+/** Start the internetworking layer module.
+ *
+ * Initialize the client connection serving function, initialize
+ * the module, register the module service and start the async
+ * manager, processing IPC messages in an infinite loop.
+ *
+ * @param[in] service Service identification.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the pm_init() function.
+ * @return Other error codes as defined for the il_initialize()
+ *         function.
+ * @return Other error codes as defined for the REGISTER_ME() macro
+ *         function.
+ *
+ */
+int il_module_start(int service)
+{
+	async_set_client_connection(il_client_connection);
+	int net_phone = net_connect_module();
+	if (net_phone < 0)
+		return net_phone;
+	
+	int rc = pm_init();
+	if (rc != EOK)
+		return rc;
+	
+	rc = il_initialize(net_phone);
+	if (rc != EOK)
+		goto out;
+	
+	rc = async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
+	if (rc != EOK)
+		goto out;
+	
+	async_manager();
+	
+out:
+	pm_destroy();
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/net/il/ip_remote.c
===================================================================
--- uspace/lib/net/il/ip_remote.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/il/ip_remote.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -36,5 +36,5 @@
  *
  * @see ip_interface.h
- * @see il_interface.h
+ * @see il_remote.h
  *
  */
@@ -121,5 +121,5 @@
     services_t service)
 {
-	return generic_device_req_remote(ip_phone, NET_IL_DEVICE, device_id, 0,
+	return generic_device_req_remote(ip_phone, NET_IP_DEVICE, device_id, 0,
 	    service);
 }
@@ -170,5 +170,5 @@
 		free(*header);
 	else
-		*device_id = IPC_GET_DEVICE(&answer);
+		*device_id = IPC_GET_DEVICE(answer);
 	
 	return (int) result;
@@ -188,5 +188,5 @@
     packet_dimension_t *packet_dimension)
 {
-	return generic_packet_size_req_remote(ip_phone, NET_IL_PACKET_SPACE,
+	return generic_packet_size_req_remote(ip_phone, NET_IP_PACKET_SPACE,
 	    device_id, packet_dimension);
 }
@@ -228,5 +228,5 @@
     services_t sender, services_t error)
 {
-	return generic_send_msg_remote(ip_phone, NET_IL_SEND, device_id,
+	return generic_send_msg_remote(ip_phone, NET_IP_SEND, device_id,
 	    packet_get_id(packet), sender, error);
 }
Index: uspace/lib/net/include/generic.h
===================================================================
--- uspace/lib/net/include/generic.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/include/generic.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/include/icmp_header.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(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 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/include/icmp_remote.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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: pace/lib/net/include/il_interface.h
===================================================================
--- uspace/lib/net/include/il_interface.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,61 +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
- * @{
- */
-
-/** @file
- * Internetwork layer module interface for the underlying network interface
- * layer. This interface is always called by the remote modules.
- */
-
-#ifndef LIBNET_IL_INTERFACE_H_
-#define LIBNET_IL_INTERFACE_H_
-
-#include <ipc/services.h>
-#include <sys/types.h>
-
-#include <net/device.h>
-#include <net/packet.h>
-
-/** @name Internetwork layer module interface
- * This interface is used by other modules.
- */
-/*@{*/
-
-extern int il_device_state_msg(int, device_id_t, device_state_t, services_t);
-extern int il_received_msg(int, device_id_t, packet_t *, services_t);
-extern int il_mtu_changed_msg(int, device_id_t, size_t, services_t);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/il_local.h
===================================================================
--- uspace/lib/net/include/il_local.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * 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 libnet 
- * @{
- */
-
-#ifndef LIBNET_IL_LOCAL_H_
-#define LIBNET_IL_LOCAL_H_
-
-#include <ipc/ipc.h>
-#include <async.h>
-
-/** Processes the Internet layer module 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		Other error codes as defined for the arp_message()
- *			function.
- */
-extern int il_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count);
-
-/** Starts the Internet layer module.
- *
- * Initializes the client connection servicing function, initializes the module,
- * registers the module service and starts the async manager, processing IPC
- * messages in an infinite loop.
- *
- * @param[in] client_connection The client connection processing function. The
- *			module skeleton propagates its own one.
- * @return		EOK on successful module termination.
- * @return		Other error codes as defined for the arp_initialize()
- *			function.
- * @return		Other error codes as defined for the REGISTER_ME() macro
- *			function.
- */
-extern int il_module_start_standalone(async_client_conn_t client_connection);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/net/include/il_remote.h
===================================================================
--- uspace/lib/net/include/il_remote.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/include/il_remote.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,61 @@
+/*
+ * 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
+ * @{
+ */
+
+/** @file
+ * Internetwork layer module interface for the underlying network interface
+ * layer. This interface is always called by the remote modules.
+ */
+
+#ifndef LIBNET_IL_REMOTE_H_
+#define LIBNET_IL_REMOTE_H_
+
+#include <ipc/services.h>
+#include <sys/types.h>
+
+#include <net/device.h>
+#include <net/packet.h>
+
+/** @name Internetwork layer module interface
+ * This interface is used by other modules.
+ */
+/*@{*/
+
+extern int il_device_state_msg(int, device_id_t, device_state_t, services_t);
+extern int il_received_msg(int, device_id_t, packet_t *, services_t);
+extern int il_mtu_changed_msg(int, device_id_t, size_t, services_t);
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/net/include/il_skel.h
===================================================================
--- uspace/lib/net/include/il_skel.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/include/il_skel.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,83 @@
+/*
+ * 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 libnet
+ * @{
+ */
+
+#ifndef LIBNET_IL_SKEL_H_
+#define LIBNET_IL_SKEL_H_
+
+/** @file
+ * Internetwork layer module skeleton.
+ * The skeleton has to be part of each internetwork layer module.
+ */
+
+#include <async.h>
+#include <fibril_synch.h>
+#include <ipc/services.h>
+
+#include <adt/measured_strings.h>
+#include <net/device.h>
+#include <net/packet.h>
+
+/** Module initialization.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in] net_phone Networking module phone.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for each specific module
+ *         initialize function.
+ *
+ */
+extern int il_initialize(int net_phone);
+
+/** Process the internetwork layer module message.
+ *
+ * This has to be implemented in user code.
+ *
+ * @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 Other error codes as defined for each specific module.
+ *
+ */
+extern int il_module_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, size_t *answer_count);
+
+extern int il_module_start(int);
+
+#endif
+
+/** @}
+ */
Index: pace/lib/net/include/netif_interface.h
===================================================================
--- uspace/lib/net/include/netif_interface.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,52 +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_NETIF_INTERFACE_H_
-#define LIBNET_NETIF_INTERFACE_H_
-
-#include <netif_remote.h>
-#include <packet_client.h>
-
-#define netif_module_message    netif_module_message_standalone
-#define netif_module_start      netif_module_start_standalone
-#define netif_get_addr_req      netif_get_addr_req_remote
-#define netif_probe_req         netif_probe_req_remote
-#define netif_send_msg          netif_send_msg_remote
-#define netif_start_req         netif_start_req_remote
-#define netif_stop_req          netif_stop_req_remote
-#define netif_stats_req         netif_stats_req_remote
-#define netif_bind_service      netif_bind_service_remote
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/netif_local.h
===================================================================
--- uspace/lib/net/include/netif_local.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,220 +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
- * @{
- */
-
-/** @file
- * Network interface module skeleton.
- * The skeleton has to be part of each network interface module.
- */
-
-#ifndef NET_NETIF_LOCAL_H_
-#define NET_NETIF_LOCAL_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <net/packet.h>
-
-/** Network interface device specific data. */
-typedef struct {
-	device_id_t device_id;  /**< Device identifier. */
-	int nil_phone;          /**< Receiving network interface layer phone. */
-	device_state_t state;   /**< Actual device state. */
-	void *specific;         /**< Driver specific data. */
-} netif_device_t;
-
-/** Device map.
- *
- * Maps device identifiers to the network interface device specific data.
- * @see device.h
- *
- */
-DEVICE_MAP_DECLARE(netif_device_map, netif_device_t);
-
-/** Network interface module skeleton global data. */
-typedef struct {
-	int net_phone;                  /**< Networking module phone. */
-	netif_device_map_t device_map;  /**< Device map. */
-	fibril_rwlock_t lock;           /**< Safety lock. */
-} netif_globals_t;
-
-extern netif_globals_t netif_globals;
-
-/** Initialize the specific module.
- *
- * This function has to be implemented in user code.
- */
-extern int netif_initialize(void);
-
-/** Probe the existence of the device.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] irq	The device interrupt number.
- * @param[in] io	The device input/output address.
- *
- * @return		EOK on success.
- * @return		Other error codes as defined for the find_device()
- *			function.
- * @return		Other error codes as defined for the specific module
- *			message implementation.
- */
-extern int netif_probe_message(device_id_t device_id, int irq, uintptr_t io);
-
-/** Send the packet queue.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The packet queue.
- * @param[in] sender	The sending module service.
- *
- * @return		EOK on success.
- * @return		EFORWARD if the device is not active (in the
- *			NETIF_ACTIVE state).
- * @return		Other error codes as defined for the find_device()
- *			function.
- * @return		Other error codes as defined for the specific module
- *			message implementation.
- */
-extern int netif_send_message(device_id_t device_id, packet_t *packet,
-    services_t sender);
-
-/** Start the device.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device	The device structure.
- *
- * @return		EOK on success.
- * @return		Other error codes as defined for the find_device()
- *			function.
- * @return		Other error codes as defined for the specific module
- *			message implementation.
- */
-extern int netif_start_message(netif_device_t *device);
-
-/** Stop the device.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device	The device structure.
- *
- * @return		EOK on success.
- * @return		Other error codes as defined for the find_device()
- *			function.
- * @return		Other error codes as defined for the specific module
- *			message implementation.
- */
-extern int netif_stop_message(netif_device_t *device);
-
-/** Return the device local hardware address.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device_id	The device identifier.
- * @param[out] address	The device local hardware address.
- *
- * @return		EOK on success.
- * @return		EBADMEM if the address parameter is NULL.
- * @return		ENOENT if there no such device.
- * @return		Other error codes as defined for the find_device()
- *			function.
- * @return		Other error codes as defined for the specific module
- *			message implementation.
- */
-extern int netif_get_addr_message(device_id_t device_id,
-    measured_string_t *address);
-
-/** Process the netif driver specific message.
- *
- * This function is called for uncommon messages received by the netif
- * skeleton. This has to be implemented in user code.
- *
- * @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.
- * @return		Other error codes as defined for the specific module
- *			message implementation.
- */
-extern int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count);
-
-/** Return the device usage statistics.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device_id	The device identifier.
- * @param[out] stats	The device usage statistics.
- *
- * @return		EOK on success.
- * @return		Other error codes as defined for the find_device()
- *			function.
- * @return		Other error codes as defined for the specific module
- *			message implementation.
- */
-extern int netif_get_device_stats(device_id_t device_id,
-    device_stats_t *stats);
-
-extern int netif_get_addr_req_local(int, device_id_t, measured_string_t **,
-    uint8_t **);
-extern int netif_probe_req_local(int, device_id_t, int, int);
-extern int netif_send_msg_local(int, device_id_t, packet_t *, services_t);
-extern int netif_start_req_local(int, device_id_t);
-extern int netif_stop_req_local(int, device_id_t);
-extern int netif_stats_req_local(int, device_id_t, device_stats_t *);
-extern int netif_bind_service_local(services_t, device_id_t, services_t,
-    async_client_conn_t);
-
-extern int find_device(device_id_t, netif_device_t **);
-extern void null_device_stats(device_stats_t *);
-extern void netif_pq_release(packet_id_t);
-extern packet_t *netif_packet_get_1(size_t);
-extern int netif_init_module(async_client_conn_t);
-
-extern int netif_module_message_standalone(const char *, ipc_callid_t,
-    ipc_call_t *, ipc_call_t *, int *);
-extern int netif_module_start_standalone(async_client_conn_t);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/net/include/netif_remote.h
===================================================================
--- uspace/lib/net/include/netif_remote.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/include/netif_remote.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -41,12 +41,12 @@
 #include <net/packet.h>
 
-extern int netif_get_addr_req_remote(int, device_id_t, measured_string_t **,
+extern int netif_get_addr_req(int, device_id_t, measured_string_t **,
     uint8_t **);
-extern int netif_probe_req_remote(int, device_id_t, int, int);
-extern int netif_send_msg_remote(int, device_id_t, packet_t *, services_t);
-extern int netif_start_req_remote(int, device_id_t);
-extern int netif_stop_req_remote(int, device_id_t);
-extern int netif_stats_req_remote(int, device_id_t, device_stats_t *);
-extern int netif_bind_service_remote(services_t, device_id_t, services_t,
+extern int netif_probe_req(int, device_id_t, int, void *);
+extern int netif_send_msg(int, device_id_t, packet_t *, services_t);
+extern int netif_start_req(int, device_id_t);
+extern int netif_stop_req(int, device_id_t);
+extern int netif_stats_req(int, device_id_t, device_stats_t *);
+extern int netif_bind_service(services_t, device_id_t, services_t,
     async_client_conn_t);
 
Index: uspace/lib/net/include/netif_skel.h
===================================================================
--- uspace/lib/net/include/netif_skel.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/include/netif_skel.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,214 @@
+/*
+ * 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
+ * @{
+ */
+
+/** @file
+ * Network interface module skeleton.
+ * The skeleton has to be part of each network interface module.
+ */
+
+#ifndef NET_NETIF_SKEL_H_
+#define NET_NETIF_SKEL_H_
+
+#include <async.h>
+#include <fibril_synch.h>
+#include <ipc/services.h>
+
+#include <adt/measured_strings.h>
+#include <net/device.h>
+#include <net/packet.h>
+
+/** Network interface device specific data. */
+typedef struct {
+	device_id_t device_id;  /**< Device identifier. */
+	int nil_phone;          /**< Receiving network interface layer phone. */
+	device_state_t state;   /**< Actual device state. */
+	void *specific;         /**< Driver specific data. */
+} netif_device_t;
+
+/** Device map.
+ *
+ * Maps device identifiers to the network interface device specific data.
+ * @see device.h
+ *
+ */
+DEVICE_MAP_DECLARE(netif_device_map, netif_device_t);
+
+/** Network interface module skeleton global data. */
+typedef struct {
+	int net_phone;                  /**< Networking module phone. */
+	netif_device_map_t device_map;  /**< Device map. */
+	fibril_rwlock_t lock;           /**< Safety lock. */
+} netif_globals_t;
+
+extern netif_globals_t netif_globals;
+
+/** Initialize the specific module.
+ *
+ * This function has to be implemented in user code.
+ *
+ */
+extern int netif_initialize(void);
+
+/** Probe the existence of the device.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in] device_id Device identifier.
+ * @param[in] irq       Device interrupt number.
+ * @param[in] io        Device input/output address.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the find_device()
+ *         function.
+ * @return Other error codes as defined for the specific module
+ *         message implementation.
+ *
+ */
+extern int netif_probe_message(device_id_t device_id, int irq, void *io);
+
+/** Send the packet queue.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in] device_id Device identifier.
+ * @param[in] packet    Packet queue.
+ * @param[in] sender    Sending module service.
+ *
+ * @return EOK on success.
+ * @return EFORWARD if the device is not active (in the
+ *         NETIF_ACTIVE state).
+ * @return Other error codes as defined for the find_device()
+ *         function.
+ * @return Other error codes as defined for the specific module
+ *         message implementation.
+ *
+ */
+extern int netif_send_message(device_id_t device_id, packet_t *packet,
+    services_t sender);
+
+/** Start the device.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in] device Device structure.
+ *
+ * @return New network interface state (non-negative values).
+ * @return Other error codes as defined for the find_device()
+ *         function.
+ * @return Other error codes as defined for the specific module
+ *         message implementation.
+ 
+ *
+ */
+extern int netif_start_message(netif_device_t *device);
+
+/** Stop the device.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in] device Device structure.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the find_device()
+ *         function.
+ * @return Other error codes as defined for the specific module
+ *         message implementation.
+ *
+ */
+extern int netif_stop_message(netif_device_t *device);
+
+/** Return the device local hardware address.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in] device_id Device identifier.
+ * @param[out] address  Device local hardware address.
+ *
+ * @return EOK on success.
+ * @return EBADMEM if the address parameter is NULL.
+ * @return ENOENT if there no such device.
+ * @return Other error codes as defined for the find_device()
+ *         function.
+ * @return Other error codes as defined for the specific module
+ *         message implementation.
+ *
+ */
+extern int netif_get_addr_message(device_id_t device_id,
+    measured_string_t *address);
+
+/** Process the netif driver specific message.
+ *
+ * This function is called for uncommon messages received by the netif
+ * skeleton. This has to be implemented in user code.
+ *
+ * @param[in]  callid Message identifier.
+ * @param[in]  call   Message.
+ * @param[out] answer Answer.
+ * @param[out] count  Number of answer arguments.
+ *
+ * @return EOK on success.
+ * @return ENOTSUP if the message is not known.
+ * @return Other error codes as defined for the specific module
+ *         message implementation.
+ *
+ */
+extern int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, size_t *count);
+
+/** Return the device usage statistics.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in]  device_id Device identifier.
+ * @param[out] stats     Device usage statistics.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the find_device()
+ *         function.
+ * @return Other error codes as defined for the specific module
+ *         message implementation.
+ *
+ */
+extern int netif_get_device_stats(device_id_t device_id,
+    device_stats_t *stats);
+
+extern int find_device(device_id_t, netif_device_t **);
+extern void null_device_stats(device_stats_t *);
+extern void netif_pq_release(packet_id_t);
+extern packet_t *netif_packet_get_1(size_t);
+
+extern int netif_module_start(void);
+
+#endif
+
+/** @}
+ */
Index: pace/lib/net/include/nil_interface.h
===================================================================
--- uspace/lib/net/include/nil_interface.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,73 +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_NIL_INTERFACE_H_
-#define LIBNET_NIL_INTERFACE_H_
-
-#include <async.h>
-#include <errno.h>
-
-#include <ipc/ipc.h>
-#include <ipc/nil.h>
-
-#include <generic.h>
-#include <nil_remote.h>
-
-#define nil_bind_service(service, device_id, me, receiver) \
-	bind_service(service, device_id, me, 0, receiver)
-
-#define nil_packet_size_req(nil_phone, device_id, packet_dimension) \
-	generic_packet_size_req_remote(nil_phone, NET_NIL_PACKET_SPACE, \
-	    device_id, packet_dimension)
-
-#define nil_get_addr_req(nil_phone, device_id, address, data) \
-	generic_get_addr_req(nil_phone, NET_NIL_ADDR, device_id, address, data)
-
-#define nil_get_broadcast_addr_req(nil_phone, device_id, address, data) \
-	generic_get_addr_req(nil_phone, NET_NIL_BROADCAST_ADDR, device_id, \
-	    address, data)
-
-#define nil_send_msg(nil_phone, device_id, packet, sender) \
-	generic_send_msg_remote(nil_phone, NET_NIL_SEND, device_id, \
-	    packet_get_id(packet), sender, 0)
-
-#define nil_device_req(nil_phone, device_id, mtu, netif_service) \
-	generic_device_req_remote(nil_phone, NET_NIL_DEVICE, device_id, mtu, \
-	    netif_service)
-
-#define nil_device_state_msg  nil_device_state_msg_remote
-#define nil_received_msg      nil_received_msg_remote
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/nil_local.h
===================================================================
--- uspace/lib/net/include/nil_local.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,136 +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
- * @{
- */
-
-/** @file
- * Network interface layer modules common skeleton.
- * All network interface layer modules have to implement this interface.
- */
-
-#ifndef LIBNET_NIL_LOCAL_H_
-#define LIBNET_NIL_LOCAL_H_
-
-#include <ipc/ipc.h>
-
-/** Module initialization.
- *
- * Is called by the module_start() function.
- *
- * @param[in] net_phone	The networking moduel phone.
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- *			initialize function.
- */
-extern int nil_initialize(int);
-
-/** Notify the network interface layer about the device state change.
- *
- * @param[in] nil_phone	The network interface layer phone.
- * @param[in] device_id	The device identifier.
- * @param[in] state	The new device state.
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- *			device state function.
- */
-extern int nil_device_state_msg_local(int, device_id_t, int);
-
-
-/** Pass the packet queue to the network interface layer.
- *
- * Process and redistribute the received packet queue to the registered
- * upper layers.
- *
- * @param[in] nil_phone	The network interface layer phone.
- * @param[in] device_id	The source device identifier.
- * @param[in] packet	The received packet or the received packet queue.
- * @param target	The target service. Ignored parameter.
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- * 			received function.
- */
-extern int nil_received_msg_local(int, device_id_t, packet_t *, services_t);
-
-/** Message processing function.
- *
- * @param[in] name	Module name.
- * @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.
- * @return		Other error codes as defined for each specific module
- *			message function.
- *
- * @see nil_interface.h
- * @see IS_NET_NIL_MESSAGE()
- */
-extern int nil_message_standalone(const char *, ipc_callid_t, ipc_call_t *,
-    ipc_call_t *, int *);
-
-/** Pass the parameters to the module specific nil_message() function.
- *
- * @param[in] name	Module name.
- * @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.
- * @return		Other error codes as defined for each specific module
- *			message function.
- */
-extern int nil_module_message_standalone(const char *, ipc_callid_t,
-    ipc_call_t *, ipc_call_t *, int *);
-
-/** Start the standalone nil layer module.
- *
- * Initialize the client connection serving function, initialize
- * the module, register the module service and start the async
- * manager, processing IPC messages in an infinite loop.
- *
- * @param[in] client_connection The client connection processing function.
- *			The module skeleton propagates its own one.
- * @return		EOK on success.
- * @return		Other error codes as defined for the pm_init() function.
- * @return		Other error codes as defined for the nil_initialize()
- *			function.
- * @return		Other error codes as defined for the REGISTER_ME() macro
- *			function.
- */
-extern int nil_module_start_standalone(async_client_conn_t);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/net/include/nil_remote.h
===================================================================
--- uspace/lib/net/include/nil_remote.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/include/nil_remote.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -37,7 +37,30 @@
 #include <net/device.h>
 #include <net/packet.h>
+#include <generic.h>
 
-extern int nil_device_state_msg_remote(int, device_id_t, int);
-extern int nil_received_msg_remote(int, device_id_t, packet_t *, services_t);
+#define nil_bind_service(service, device_id, me, receiver) \
+	bind_service(service, device_id, me, 0, receiver)
+
+#define nil_packet_size_req(nil_phone, device_id, packet_dimension) \
+	generic_packet_size_req_remote(nil_phone, NET_NIL_PACKET_SPACE, \
+	    device_id, packet_dimension)
+
+#define nil_get_addr_req(nil_phone, device_id, address, data) \
+	generic_get_addr_req(nil_phone, NET_NIL_ADDR, device_id, address, data)
+
+#define nil_get_broadcast_addr_req(nil_phone, device_id, address, data) \
+	generic_get_addr_req(nil_phone, NET_NIL_BROADCAST_ADDR, device_id, \
+	    address, data)
+
+#define nil_send_msg(nil_phone, device_id, packet, sender) \
+	generic_send_msg_remote(nil_phone, NET_NIL_SEND, device_id, \
+	    packet_get_id(packet), sender, 0)
+
+#define nil_device_req(nil_phone, device_id, mtu, netif_service) \
+	generic_device_req_remote(nil_phone, NET_NIL_DEVICE, device_id, mtu, \
+	    netif_service)
+
+extern int nil_device_state_msg(int, device_id_t, int);
+extern int nil_received_msg(int, device_id_t, packet_t *, services_t);
 
 #endif
Index: uspace/lib/net/include/nil_skel.h
===================================================================
--- uspace/lib/net/include/nil_skel.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/include/nil_skel.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,122 @@
+/*
+ * 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
+ * @{
+ */
+
+/** @file
+ * Network interface layer modules common skeleton.
+ * All network interface layer modules have to implement this interface.
+ */
+
+#ifndef LIBNET_NIL_SKEL_H_
+#define LIBNET_NIL_SKEL_H_
+
+#include <async.h>
+#include <fibril_synch.h>
+#include <ipc/services.h>
+
+#include <adt/measured_strings.h>
+#include <net/device.h>
+#include <net/packet.h>
+
+/** Module initialization.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in] net_phone Networking module phone.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for each specific module
+ *         initialize function.
+ *
+ */
+extern int nil_initialize(int net_phone);
+
+/** Notify the network interface layer about the device state change.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in] nil_phone Network interface layer phone.
+ * @param[in] device_id Device identifier.
+ * @param[in] state     New device state.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for each specific module
+ *         device state function.
+ *
+ */
+extern int nil_device_state_msg_local(int, device_id_t, int);
+
+/** Pass the packet queue to the network interface layer.
+ *
+ * Process and redistribute the received packet queue to the registered
+ * upper layers.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in] nil_phone Network interface layer phone.
+ * @param[in] device_id Source device identifier.
+ * @param[in] packet    Received packet or the received packet queue.
+ * @param[in] target    Target service. Ignored parameter.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for each specific module
+ *         received function.
+ *
+ */
+extern int nil_received_msg_local(int, device_id_t, packet_t *, services_t);
+
+/** Message processing function.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in]  name   Module name.
+ * @param[in]  callid Message identifier.
+ * @param[in]  call   Message parameters.
+ * @param[out] answer Message answer parameters.
+ * @param[out] count  Message answer arguments.
+ *
+ * @return EOK on success.
+ * @return ENOTSUP if the message is not known.
+ * @return Other error codes as defined for each specific module
+ *         message function.
+ *
+ * @see IS_NET_NIL_MESSAGE()
+ *
+ */
+extern int nil_module_message(ipc_callid_t, ipc_call_t *, ipc_call_t *,
+    size_t *);
+
+extern int nil_module_start(int);
+
+#endif
+
+/** @}
+ */
Index: pace/lib/net/include/tl_interface.h
===================================================================
--- uspace/lib/net/include/tl_interface.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,61 +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
- * @{
- */
-
-/** @file
- * Transport layer module interface for the underlying internetwork layer.
- */
-
-#ifndef LIBNET_TL_INTERFACE_H_
-#define LIBNET_TL_INTERFACE_H_
-
-#include <async.h>
-#include <ipc/services.h>
-#include <ipc/tl.h>
-
-#include <generic.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <packet_client.h>
-
-/** @name Transport layer module interface
- * This interface is used by other modules.
- */
-/*@{*/
-
-extern int tl_received_msg(int, device_id_t, packet_t *, services_t, services_t);
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/tl_local.h
===================================================================
--- uspace/lib/net/include/tl_local.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,73 +1,0 @@
-/*
- * 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 libnet
- * @{
- */
-
-#ifndef LIBNET_TL_LOCAL_H_
-#define LIBNET_TL_LOCAL_H_
-
-#include <ipc/ipc.h>
-#include <async.h>
-
-/** Starts the TL module.
- *
- * Initializes the client connection serving function, initializes the module,
- * registers the module service and starts the async manager, processing IPC
- * messages in an infinite loop.
- *
- * @param[in] client_connection The client connection processing function. The
- *			module skeleton propagates its own one.
- * @return		EOK on successful module termination.
- * @return		Other error codes as defined for the module initialize
- *			function.
- * @return		Other error codes as defined for the REGISTER_ME() macro
- *			function.
- */
-extern int tl_module_message_standalone(ipc_callid_t, ipc_call_t *,
-    ipc_call_t *, int *);
-
-
-/** Processes the TL module 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		Other error codes as defined for the module's message
- *			standalone function.
- */
-extern int tl_module_start_standalone(async_client_conn_t);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/net/include/tl_remote.h
===================================================================
--- uspace/lib/net/include/tl_remote.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/include/tl_remote.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,62 @@
+/*
+ * 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
+ * @{
+ */
+
+/** @file
+ * Transport layer module interface for the underlying internetwork layer.
+ */
+
+#ifndef LIBNET_TL_REMOTE_H_
+#define LIBNET_TL_REMOTE_H_
+
+#include <async.h>
+#include <ipc/services.h>
+#include <ipc/tl.h>
+
+#include <generic.h>
+#include <net/device.h>
+#include <net/packet.h>
+#include <packet_client.h>
+
+/** @name Transport layer module interface
+ * This interface is used by other modules.
+ */
+/*@{*/
+
+extern int tl_received_msg(int, device_id_t, packet_t *, services_t,
+    services_t);
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/net/include/tl_skel.h
===================================================================
--- uspace/lib/net/include/tl_skel.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/include/tl_skel.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,90 @@
+/*
+ * 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 libnet
+ * @{
+ */
+
+#ifndef LIBNET_TL_SKEL_H_
+#define LIBNET_TL_SKEL_H_
+
+/** @file
+ * Transport layer module skeleton.
+ * The skeleton has to be part of each transport layer module.
+ */
+
+#include <async.h>
+#include <fibril_synch.h>
+#include <ipc/services.h>
+
+#include <adt/measured_strings.h>
+#include <net/device.h>
+#include <net/packet.h>
+
+/** Module initialization.
+ *
+ * This has to be implemented in user code.
+ *
+ * @param[in] net_phone Networking module phone.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for each specific module
+ *         initialize function.
+ *
+ */
+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.
+ *
+ * This has to be implemented in user code.
+ *
+ * @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 Other error codes as defined for each specific module.
+ *
+ */
+extern int tl_message(ipc_callid_t, ipc_call_t *,
+    ipc_call_t *, size_t *);
+
+extern int tl_module_start(int);
+
+#endif
+
+/** @}
+ */
Index: pace/lib/net/netif/netif_local.c
===================================================================
--- uspace/lib/net/netif/netif_local.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,458 +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 
- * @{
- */
-
-/** @file
- * Network interface module skeleton implementation.
- * @see netif.h
- */
-
-#include <async.h>
-#include <mem.h>
-#include <fibril_synch.h>
-#include <stdio.h>
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-#include <ipc/netif.h>
-#include <errno.h>
-
-#include <generic.h>
-#include <net/modules.h>
-#include <net/packet.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <nil_interface.h>
-#include <netif_local.h>
-#include <netif_interface.h>
-
-DEVICE_MAP_IMPLEMENT(netif_device_map, netif_device_t);
-
-/** Network interface global data. */
-netif_globals_t netif_globals;
-
-/** Probe the existence of the device.
- *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @param[in] irq	The device interrupt number.
- * @param[in] io	The device input/output address.
- * @return		EOK on success.
- * @return		Other error codes as defined for the
- *			netif_probe_message().
- */
-int
-netif_probe_req_local(int netif_phone, device_id_t device_id, int irq, int io)
-{
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	int result = netif_probe_message(device_id, irq, io);
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	return result;
-}
-
-/** Send the packet queue.
- *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The packet queue.
- * @param[in] sender	The sending module service.
- * @return		EOK on success.
- * @return		Other error codes as defined for the generic_send_msg()
- *			function.
- */
-int netif_send_msg_local(int netif_phone, device_id_t device_id,
-    packet_t *packet, services_t sender)
-{
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	int result = netif_send_message(device_id, packet, sender);
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	return result;
-}
-
-/** Start the device.
- *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @return		EOK on success.
- * @return		Other error codes as defined for the find_device()
- *			function.
- * @return		Other error codes as defined for the
- *			netif_start_message() function.
- */
-int netif_start_req_local(int netif_phone, device_id_t device_id)
-{
-	int rc;
-	
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	
-	netif_device_t *device;
-	rc = find_device(device_id, &device);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		return rc;
-	}
-	
-	int result = netif_start_message(device);
-	if (result > NETIF_NULL) {
-		int phone = device->nil_phone;
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		nil_device_state_msg(phone, device_id, result);
-		return EOK;
-	}
-	
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	return result;
-}
-
-/** Stop the device.
- *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @return		EOK on success.
- * @return		Other error codes as defined for the find_device()
- *			function.
- * @return		Other error codes as defined for the
- *			netif_stop_message() function.
- */
-int netif_stop_req_local(int netif_phone, device_id_t device_id)
-{
-	int rc;
-	
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	
-	netif_device_t *device;
-	rc = find_device(device_id, &device);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		return rc;
-	}
-	
-	int result = netif_stop_message(device);
-	if (result > NETIF_NULL) {
-		int phone = device->nil_phone;
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		nil_device_state_msg(phone, device_id, result);
-		return EOK;
-	}
-	
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	return result;
-}
-
-/** Return the device usage statistics.
- *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @param[out] stats	The device usage statistics.
- * @return EOK on success.
- */
-int netif_stats_req_local(int netif_phone, device_id_t device_id,
-    device_stats_t *stats)
-{
-	fibril_rwlock_read_lock(&netif_globals.lock);
-	int res = netif_get_device_stats(device_id, stats);
-	fibril_rwlock_read_unlock(&netif_globals.lock);
-	
-	return res;
-}
-
-/** Return the device local hardware address.
- *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @param[out] address	The device local hardware address.
- * @param[out] data	The address data.
- * @return		EOK on success.
- * @return		EBADMEM if the address parameter is NULL.
- * @return		ENOENT if there no such device.
- * @return		Other error codes as defined for the
- *			netif_get_addr_message() function.
- */
-int netif_get_addr_req_local(int netif_phone, device_id_t device_id,
-    measured_string_t **address, uint8_t **data)
-{
-	int rc;
-	
-	if (!address || !data)
-		return EBADMEM;
-	
-	fibril_rwlock_read_lock(&netif_globals.lock);
-	
-	measured_string_t translation;
-	rc = netif_get_addr_message(device_id, &translation);
-	if (rc == EOK) {
-		*address = measured_string_copy(&translation);
-		rc = (*address) ? EOK : ENOMEM;
-	}
-	
-	fibril_rwlock_read_unlock(&netif_globals.lock);
-	
-	*data = (**address).value;
-	
-	return rc;
-}
-
-/** Find the device specific data.
- *
- * @param[in] device_id	The device identifier.
- * @param[out] device	The device specific data.
- * @return		EOK on success.
- * @return		ENOENT if device is not found.
- * @return		EPERM if the device is not initialized.
- */
-int find_device(device_id_t device_id, netif_device_t **device)
-{
-	if (!device)
-		return EBADMEM;
-	
-	*device = netif_device_map_find(&netif_globals.device_map, device_id);
-	if (*device == NULL)
-		return ENOENT;
-	
-	if ((*device)->state == NETIF_NULL)
-		return EPERM;
-	
-	return EOK;
-}
-
-/** Clear the usage statistics.
- *
- * @param[in] stats	The usage statistics.
- */
-void null_device_stats(device_stats_t *stats)
-{
-	bzero(stats, sizeof(device_stats_t));
-}
-
-/** Initialize the netif module.
- *
- * @param[in] client_connection The client connection functio to be registered.
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- *			message function.
- */
-int netif_init_module(async_client_conn_t client_connection)
-{
-	int rc;
-	
-	async_set_client_connection(client_connection);
-	
-	netif_globals.net_phone = connect_to_service(SERVICE_NETWORKING);
-	netif_device_map_initialize(&netif_globals.device_map);
-	
-	rc = pm_init();
-	if (rc != EOK)
-		return rc;
-	
-	fibril_rwlock_initialize(&netif_globals.lock);
-	
-	rc = netif_initialize();
-	if (rc != EOK) {
-		pm_destroy();
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/** Release the given packet.
- *
- * Prepared for future optimization.
- *
- * @param[in] packet_id	The packet identifier.
- */
-void netif_pq_release(packet_id_t packet_id)
-{
-	pq_release_remote(netif_globals.net_phone, packet_id);
-}
-
-/** Allocate new packet to handle the given content size.
- *
- * @param[in] content	The minimum content size.
- * @return		The allocated packet.
- * @return		NULL if there is an error.
- *
- */
-packet_t *netif_packet_get_1(size_t content)
-{
-	return packet_get_1_remote(netif_globals.net_phone, content);
-}
-
-/** Register the device notification receiver, the network interface layer
- * module.
- *
- * @param[in] name	Module name.
- * @param[in] device_id	The device identifier.
- * @param[in] phone	The network interface layer module phone.
- * @return		EOK on success.
- * @return		ENOENT if there is no such device.
- * @return		ELIMIT if there is another module registered.
- */
-static int register_message(const char *name, device_id_t device_id, int phone)
-{
-	netif_device_t *device;
-	int rc;
-	
-	rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	if (device->nil_phone > 0)
-		return ELIMIT;
-	
-	device->nil_phone = phone;
-	printf("%s: Receiver of device %d registered (phone: %d)\n",
-	    name, device->device_id, device->nil_phone);
-	return EOK;
-}
-
-/** Process the netif module messages.
- *
- * @param[in] name 	Module name.
- * @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.
- * @return		Other error codes as defined for each specific module
- *			message function.
- *
- * @see IS_NET_NETIF_MESSAGE()
- *
- */
-int netif_module_message_standalone(const char *name, ipc_callid_t callid,
-    ipc_call_t *call, ipc_call_t *answer, int *answer_count)
-{
-	size_t length;
-	device_stats_t stats;
-	packet_t *packet;
-	measured_string_t address;
-	int rc;
-	
-	*answer_count = 0;
-	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
-	case NET_NETIF_PROBE:
-		return netif_probe_req_local(0, IPC_GET_DEVICE(call),
-		    NETIF_GET_IRQ(call), NETIF_GET_IO(call));
-		    
-	case IPC_M_CONNECT_TO_ME:
-		fibril_rwlock_write_lock(&netif_globals.lock);
-		rc = register_message(name, IPC_GET_DEVICE(call),
-		    IPC_GET_PHONE(call));
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		return rc;
-		
-	case NET_NETIF_SEND:
-		rc = packet_translate_remote(netif_globals.net_phone, &packet,
-		    IPC_GET_PACKET(call));
-		if (rc != EOK)
-			return rc;
-		return netif_send_msg_local(0, IPC_GET_DEVICE(call), packet,
-		    IPC_GET_SENDER(call));
-		
-	case NET_NETIF_START:
-		return netif_start_req_local(0, IPC_GET_DEVICE(call));
-		
-	case NET_NETIF_STATS:
-		fibril_rwlock_read_lock(&netif_globals.lock);
-
-		rc = async_data_read_receive(&callid, &length);
-		if (rc != EOK) {
-			fibril_rwlock_read_unlock(&netif_globals.lock);
-			return rc;
-		}
-		if (length < sizeof(device_stats_t)) {
-			fibril_rwlock_read_unlock(&netif_globals.lock);
-			return EOVERFLOW;
-		}
-
-		rc = netif_get_device_stats(IPC_GET_DEVICE(call), &stats);
-		if (rc == EOK) {
-			rc = async_data_read_finalize(callid, &stats,
-			    sizeof(device_stats_t));
-		}
-
-		fibril_rwlock_read_unlock(&netif_globals.lock);
-		return rc;
-
-	case NET_NETIF_STOP:
-		return netif_stop_req_local(0, IPC_GET_DEVICE(call));
-		
-	case NET_NETIF_GET_ADDR:
-		fibril_rwlock_read_lock(&netif_globals.lock);
-		rc = netif_get_addr_message(IPC_GET_DEVICE(call), &address);
-		if (rc == EOK)
-			rc = measured_strings_reply(&address, 1);
-		fibril_rwlock_read_unlock(&netif_globals.lock);
-		return rc;
-	}
-	
-	return netif_specific_message(callid, call, answer, answer_count);
-}
-
-/** Start the network interface module.
- *
- * Initialize the client connection serving function, initialize the module,
- * registers the module service and start the async manager, processing IPC
- * messages in an infinite loop.
- *
- * @param[in] client_connection The client connection processing function.
- *			The module skeleton propagates its own one.
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- *			message function.
- */
-int netif_module_start_standalone(async_client_conn_t client_connection)
-{
-	int rc;
-	
-	rc = netif_init_module(client_connection);
-	if (rc != EOK)
-		return rc;
-	
-	async_manager();
-	
-	pm_destroy();
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/lib/net/netif/netif_remote.c
===================================================================
--- uspace/lib/net/netif/netif_remote.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/netif/netif_remote.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libnet 
+/** @addtogroup libnet
  * @{
  */
@@ -49,15 +49,17 @@
 /** Return the device local hardware address.
  *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @param[out] address	The device local hardware address.
- * @param[out] data	The address data.
- * @return		EOK on success.
- * @return		EBADMEM if the address parameter is NULL.
- * @return		ENOENT if there no such device.
- * @return		Other error codes as defined for the
- *			netif_get_addr_message() function.
+ * @param[in]  netif_phone Network interface phone.
+ * @param[in]  device_id   Device identifier.
+ * @param[out] address     Device local hardware address.
+ * @param[out] data        Address data.
+ *
+ * @return EOK on success.
+ * @return EBADMEM if the address parameter is NULL.
+ * @return ENOENT if there no such device.
+ * @return Other error codes as defined for the
+ *         netif_get_addr_message() function.
+ *
  */
-int netif_get_addr_req_remote(int netif_phone, device_id_t device_id,
+int netif_get_addr_req(int netif_phone, device_id_t device_id,
     measured_string_t **address, uint8_t **data)
 {
@@ -68,30 +70,33 @@
 /** Probe the existence of the device.
  *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @param[in] irq	The device interrupt number.
- * @param[in] io	The device input/output address.
- * @return		EOK on success.
- * @return		Other error codes as defined for the
- *			netif_probe_message().
+ * @param[in] netif_phone Network interface phone.
+ * @param[in] device_id   Device identifier.
+ * @param[in] irq         Device interrupt number.
+ * @param[in] io          Device input/output address.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the
+ *         netif_probe_message().
+ *
  */
-int
-netif_probe_req_remote(int netif_phone, device_id_t device_id, int irq, int io)
+int netif_probe_req(int netif_phone, device_id_t device_id, int irq, void *io)
 {
-	return async_req_3_0(netif_phone, NET_NETIF_PROBE, device_id, irq, io);
+	return async_req_3_0(netif_phone, NET_NETIF_PROBE, device_id, irq,
+	    (sysarg_t) io);
 }
 
 /** Send the packet queue.
  *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The packet queue.
- * @param[in] sender	The sending module service.
- * @return		EOK on success.
- * @return		Other error codes as defined for the generic_send_msg()
- *			function.
+ * @param[in] netif_phone Network interface phone.
+ * @param[in] device_id   Device identifier.
+ * @param[in] packet      Packet queue.
+ * @param[in] sender      Sending module service.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the generic_send_msg()
+ *         function.
+ *
  */
-int
-netif_send_msg_remote(int netif_phone, device_id_t device_id, packet_t *packet,
+int netif_send_msg(int netif_phone, device_id_t device_id, packet_t *packet,
     services_t sender)
 {
@@ -102,13 +107,15 @@
 /** Start the device.
  *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @return		EOK on success.
- * @return		Other error codes as defined for the find_device()
- *			function.
- * @return		Other error codes as defined for the
- *			netif_start_message() function.
+ * @param[in] netif_phone Network interface phone.
+ * @param[in] device_id   Device identifier.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the find_device()
+ *         function.
+ * @return Other error codes as defined for the
+ *         netif_start_message() function.
+ *
  */
-int netif_start_req_remote(int netif_phone, device_id_t device_id)
+int netif_start_req(int netif_phone, device_id_t device_id)
 {
 	return async_req_1_0(netif_phone, NET_NETIF_START, device_id);
@@ -117,13 +124,15 @@
 /** Stop the device.
  *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @return		EOK on success.
- * @return		Other error codes as defined for the find_device()
- *			function.
- * @return		Other error codes as defined for the
- *			netif_stop_message() function.
+ * @param[in] netif_phone Network interface phone.
+ * @param[in] device_id   Device identifier.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the find_device()
+ *         function.
+ * @return Other error codes as defined for the
+ *         netif_stop_message() function.
+ *
  */
-int netif_stop_req_remote(int netif_phone, device_id_t device_id)
+int netif_stop_req(int netif_phone, device_id_t device_id)
 {
 	return async_req_1_0(netif_phone, NET_NETIF_STOP, device_id);
@@ -132,10 +141,12 @@
 /** Return the device usage statistics.
  *
- * @param[in] netif_phone The network interface phone.
- * @param[in] device_id	The device identifier.
- * @param[out] stats	The device usage statistics.
+ * @param[in] netif_phone Network interface phone.
+ * @param[in] device_id   Device identifier.
+ * @param[out] stats      Device usage statistics.
+ *
  * @return EOK on success.
+ *
  */
-int netif_stats_req_remote(int netif_phone, device_id_t device_id,
+int netif_stats_req(int netif_phone, device_id_t device_id,
     device_stats_t *stats)
 {
@@ -153,6 +164,8 @@
 }
 
-/** Create bidirectional connection with the network interface module and
- * registers the message receiver.
+/** Create bidirectional connection with the network interface module
+ *
+ * Create bidirectional connection with the network interface module and
+ * register the message receiver.
  *
  * @param[in] service   The network interface module service.
@@ -161,11 +174,11 @@
  * @param[in] receiver  The message receiver.
  *
- * @return		The phone of the needed service.
- * @return		EOK on success.
- * @return		Other error codes as defined for the bind_service()
- *			function.
+ * @return The phone of the needed service.
+ * @return EOK on success.
+ * @return Other error codes as defined for the bind_service()
+ *         function.
+ *
  */
-int
-netif_bind_service_remote(services_t service, device_id_t device_id,
+int netif_bind_service(services_t service, device_id_t device_id,
     services_t me, async_client_conn_t receiver)
 {
Index: uspace/lib/net/netif/netif_skel.c
===================================================================
--- uspace/lib/net/netif/netif_skel.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/netif/netif_skel.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,433 @@
+/*
+ * 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
+ * @{
+ */
+
+/** @file
+ * Network interface module skeleton implementation.
+ * @see netif_skel.h
+ */
+
+#include <async.h>
+#include <mem.h>
+#include <fibril_synch.h>
+#include <stdio.h>
+#include <ipc/services.h>
+#include <ipc/netif.h>
+#include <errno.h>
+
+#include <generic.h>
+#include <net/modules.h>
+#include <net/packet.h>
+#include <packet_client.h>
+#include <packet_remote.h>
+#include <adt/measured_strings.h>
+#include <net/device.h>
+#include <netif_skel.h>
+#include <nil_remote.h>
+
+DEVICE_MAP_IMPLEMENT(netif_device_map, netif_device_t);
+
+/** Network interface global data. */
+netif_globals_t netif_globals;
+
+/** Probe the existence of the device.
+ *
+ * @param[in] netif_phone Network interface phone.
+ * @param[in] device_id   Device identifier.
+ * @param[in] irq         Device interrupt number.
+ * @param[in] io          Device input/output address.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the
+ *         netif_probe_message().
+ *
+ */
+static int netif_probe_req_local(int netif_phone, device_id_t device_id,
+    int irq, void *io)
+{
+	fibril_rwlock_write_lock(&netif_globals.lock);
+	int result = netif_probe_message(device_id, irq, io);
+	fibril_rwlock_write_unlock(&netif_globals.lock);
+	
+	return result;
+}
+
+/** Send the packet queue.
+ *
+ * @param[in] netif_phone Network interface phone.
+ * @param[in] device_id   Device identifier.
+ * @param[in] packet      Packet queue.
+ * @param[in] sender      Sending module service.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the generic_send_msg()
+ *         function.
+ *
+ */
+static int netif_send_msg_local(int netif_phone, device_id_t device_id,
+    packet_t *packet, services_t sender)
+{
+	fibril_rwlock_write_lock(&netif_globals.lock);
+	int result = netif_send_message(device_id, packet, sender);
+	fibril_rwlock_write_unlock(&netif_globals.lock);
+	
+	return result;
+}
+
+/** Start the device.
+ *
+ * @param[in] netif_phone Network interface phone.
+ * @param[in] device_id   Device identifier.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the find_device()
+ *         function.
+ * @return Other error codes as defined for the
+ *         netif_start_message() function.
+ *
+ */
+static int netif_start_req_local(int netif_phone, device_id_t device_id)
+{
+	fibril_rwlock_write_lock(&netif_globals.lock);
+	
+	netif_device_t *device;
+	int rc = find_device(device_id, &device);
+	if (rc != EOK) {
+		fibril_rwlock_write_unlock(&netif_globals.lock);
+		return rc;
+	}
+	
+	int result = netif_start_message(device);
+	if (result > NETIF_NULL) {
+		int phone = device->nil_phone;
+		nil_device_state_msg(phone, device_id, result);
+		fibril_rwlock_write_unlock(&netif_globals.lock);
+		return EOK;
+	}
+	
+	fibril_rwlock_write_unlock(&netif_globals.lock);
+	
+	return result;
+}
+
+/** Stop the device.
+ *
+ * @param[in] netif_phone Network interface phone.
+ * @param[in] device_id   Device identifier.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the find_device()
+ *         function.
+ * @return Other error codes as defined for the
+ *         netif_stop_message() function.
+ *
+ */
+static int netif_stop_req_local(int netif_phone, device_id_t device_id)
+{
+	fibril_rwlock_write_lock(&netif_globals.lock);
+	
+	netif_device_t *device;
+	int rc = find_device(device_id, &device);
+	if (rc != EOK) {
+		fibril_rwlock_write_unlock(&netif_globals.lock);
+		return rc;
+	}
+	
+	int result = netif_stop_message(device);
+	if (result > NETIF_NULL) {
+		int phone = device->nil_phone;
+		nil_device_state_msg(phone, device_id, result);
+		fibril_rwlock_write_unlock(&netif_globals.lock);
+		return EOK;
+	}
+	
+	fibril_rwlock_write_unlock(&netif_globals.lock);
+	
+	return result;
+}
+
+/** Find the device specific data.
+ *
+ * @param[in]  device_id Device identifier.
+ * @param[out] device    Device specific data.
+ *
+ * @return EOK on success.
+ * @return ENOENT if device is not found.
+ * @return EPERM if the device is not initialized.
+ *
+ */
+int find_device(device_id_t device_id, netif_device_t **device)
+{
+	if (!device)
+		return EBADMEM;
+	
+	*device = netif_device_map_find(&netif_globals.device_map, device_id);
+	if (*device == NULL)
+		return ENOENT;
+	
+	if ((*device)->state == NETIF_NULL)
+		return EPERM;
+	
+	return EOK;
+}
+
+/** Clear the usage statistics.
+ *
+ * @param[in] stats The usage statistics.
+ *
+ */
+void null_device_stats(device_stats_t *stats)
+{
+	bzero(stats, sizeof(device_stats_t));
+}
+
+/** Release the given packet.
+ *
+ * Prepared for future optimization.
+ *
+ * @param[in] packet_id The packet identifier.
+ *
+ */
+void netif_pq_release(packet_id_t packet_id)
+{
+	pq_release_remote(netif_globals.net_phone, packet_id);
+}
+
+/** Allocate new packet to handle the given content size.
+ *
+ * @param[in] content Minimum content size.
+ *
+ * @return The allocated packet.
+ * @return NULL on error.
+ *
+ */
+packet_t *netif_packet_get_1(size_t content)
+{
+	return packet_get_1_remote(netif_globals.net_phone, content);
+}
+
+/** Register the device notification receiver,
+ *
+ * Register a  network interface layer module as the device
+ * notification receiver.
+ *
+ * @param[in] device_id Device identifier.
+ * @param[in] phone     Network interface layer module phone.
+ *
+ * @return EOK on success.
+ * @return ENOENT if there is no such device.
+ * @return ELIMIT if there is another module registered.
+ *
+ */
+static int register_message(device_id_t device_id, int phone)
+{
+	netif_device_t *device;
+	int rc = find_device(device_id, &device);
+	if (rc != EOK)
+		return rc;
+	
+	if (device->nil_phone >= 0)
+		return ELIMIT;
+	
+	device->nil_phone = phone;
+	return EOK;
+}
+
+/** Process the netif module messages.
+ *
+ * @param[in]  callid Mmessage identifier.
+ * @param[in]  call   Message.
+ * @param[out] answer Answer.
+ * @param[out] count  Number of arguments of the answer.
+ *
+ * @return EOK on success.
+ * @return ENOTSUP if the message is unknown.
+ * @return Other error codes as defined for each specific module
+ *         message function.
+ *
+ * @see IS_NET_NETIF_MESSAGE()
+ *
+ */
+static int netif_module_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, size_t *count)
+{
+	size_t length;
+	device_stats_t stats;
+	packet_t *packet;
+	measured_string_t address;
+	int rc;
+	
+	*count = 0;
+	
+	switch (IPC_GET_IMETHOD(*call)) {
+	case IPC_M_PHONE_HUNGUP:
+		return EOK;
+	
+	case NET_NETIF_PROBE:
+		return netif_probe_req_local(0, IPC_GET_DEVICE(*call),
+		    NETIF_GET_IRQ(*call), NETIF_GET_IO(*call));
+	
+	case IPC_M_CONNECT_TO_ME:
+		fibril_rwlock_write_lock(&netif_globals.lock);
+		
+		rc = register_message(IPC_GET_DEVICE(*call), IPC_GET_PHONE(*call));
+		
+		fibril_rwlock_write_unlock(&netif_globals.lock);
+		return rc;
+	
+	case NET_NETIF_SEND:
+		rc = packet_translate_remote(netif_globals.net_phone, &packet,
+		    IPC_GET_PACKET(*call));
+		if (rc != EOK)
+			return rc;
+		
+		return netif_send_msg_local(0, IPC_GET_DEVICE(*call), packet,
+		    IPC_GET_SENDER(*call));
+	
+	case NET_NETIF_START:
+		return netif_start_req_local(0, IPC_GET_DEVICE(*call));
+	
+	case NET_NETIF_STATS:
+		fibril_rwlock_read_lock(&netif_globals.lock);
+		
+		rc = async_data_read_receive(&callid, &length);
+		if (rc != EOK) {
+			fibril_rwlock_read_unlock(&netif_globals.lock);
+			return rc;
+		}
+		
+		if (length < sizeof(device_stats_t)) {
+			fibril_rwlock_read_unlock(&netif_globals.lock);
+			return EOVERFLOW;
+		}
+		
+		rc = netif_get_device_stats(IPC_GET_DEVICE(*call), &stats);
+		if (rc == EOK) {
+			rc = async_data_read_finalize(callid, &stats,
+			    sizeof(device_stats_t));
+		}
+		
+		fibril_rwlock_read_unlock(&netif_globals.lock);
+		return rc;
+	
+	case NET_NETIF_STOP:
+		return netif_stop_req_local(0, IPC_GET_DEVICE(*call));
+	
+	case NET_NETIF_GET_ADDR:
+		fibril_rwlock_read_lock(&netif_globals.lock);
+		
+		rc = netif_get_addr_message(IPC_GET_DEVICE(*call), &address);
+		if (rc == EOK)
+			rc = measured_strings_reply(&address, 1);
+		
+		fibril_rwlock_read_unlock(&netif_globals.lock);
+		return rc;
+	}
+	
+	return netif_specific_message(callid, call, answer, count);
+}
+
+/** Default fibril for new module connections.
+ *
+ * @param[in] iid   Initial message identifier.
+ * @param[in] icall Initial message call structure.
+ *
+ */
+static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/*
+	 * Accept the connection by answering
+	 * the initial IPC_M_CONNECT_ME_TO call.
+	 */
+	async_answer_0(iid, EOK);
+	
+	while (true) {
+		ipc_call_t answer;
+		size_t count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = netif_module_message(callid, &call, &answer, &count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
+		    (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, count);
+	}
+}
+
+/** Start the network interface module.
+ *
+ * Initialize the client connection serving function, initialize the module,
+ * registers the module service and start the async manager, processing IPC
+ * messages in an infinite loop.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for each specific module
+ *         message function.
+ *
+ */
+int netif_module_start(void)
+{
+	async_set_client_connection(netif_client_connection);
+	
+	netif_globals.net_phone = connect_to_service(SERVICE_NETWORKING);
+	netif_device_map_initialize(&netif_globals.device_map);
+	
+	int rc = pm_init();
+	if (rc != EOK)
+		return rc;
+	
+	fibril_rwlock_initialize(&netif_globals.lock);
+	
+	rc = netif_initialize();
+	if (rc != EOK) {
+		pm_destroy();
+		return rc;
+	}
+	
+	async_manager();
+	
+	pm_destroy();
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/net/nil/nil_remote.c
===================================================================
--- uspace/lib/net/nil/nil_remote.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/nil/nil_remote.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -33,26 +33,26 @@
 /** @file
  * Network interface layer interface implementation for remote modules.
- * @see nil_interface.h
+ * @see nil_remote.h
  */
 
 #include <nil_remote.h>
-#include <nil_interface.h>
 #include <generic.h>
 #include <net/device.h>
 #include <net/packet.h>
 #include <packet_client.h>
-
 #include <ipc/nil.h>
 
 /** Notify the network interface layer about the device state change.
  *
- * @param[in] nil_phone	The network interface layer phone.
- * @param[in] device_id	The device identifier.
- * @param[in] state	The new device state.
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- *			device state function.
+ * @param[in] nil_phone Network interface layer phone.
+ * @param[in] device_id Device identifier.
+ * @param[in] state     New device state.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for each specific module
+ *         device state function.
+ *
  */
-int nil_device_state_msg_remote(int nil_phone, device_id_t device_id, int state)
+int nil_device_state_msg(int nil_phone, device_id_t device_id, int state)
 {
 	return generic_device_state_msg_remote(nil_phone, NET_NIL_DEVICE_STATE,
@@ -65,13 +65,15 @@
  * upper layers.
  *
- * @param[in] nil_phone	The network interface layer phone.
- * @param[in] device_id	The source device identifier.
- * @param[in] packet	The received packet or the received packet queue.
- * @param target	The target service. Ignored parameter.
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- * 			received function.
+ * @param[in] nil_phone Network interface layer phone.
+ * @param[in] device_id Source device identifier.
+ * @param[in] packet    Received packet or the received packet queue.
+ * @param[in] target    Target service. Ignored parameter.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for each specific module
+ *         received function.
+ *
  */
-int nil_received_msg_remote(int nil_phone, device_id_t device_id,
+int nil_received_msg(int nil_phone, device_id_t device_id,
     packet_t *packet, services_t target)
 {
Index: uspace/lib/net/nil/nil_skel.c
===================================================================
--- uspace/lib/net/nil/nil_skel.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/nil/nil_skel.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,129 @@
+/*
+ * 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 libnet
+ * @{
+ */
+
+/** @file
+ * Network interface layer module skeleton implementation.
+ * @see nil_skel.h
+ */
+
+#include <bool.h>
+#include <errno.h>
+#include <nil_skel.h>
+#include <net_interface.h>
+#include <net/modules.h>
+
+/** Default thread for new connections.
+ *
+ * @param[in] iid   The initial message identifier.
+ * @param[in] icall The initial message call structure.
+ *
+ */
+static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/*
+	 * Accept the connection by answering
+	 * the initial IPC_M_CONNECT_ME_TO call.
+	 */
+	async_answer_0(iid, EOK);
+	
+	while (true) {
+		ipc_call_t answer;
+		size_t count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = nil_module_message(callid, &call, &answer,
+		    &count);
+		
+		/*
+		 * End if told to either by the message or the processing
+		 * result.
+		 */
+		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
+		    (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, count);
+	}
+}
+
+/** Start the network interface layer module.
+ *
+ * Initialize the client connection serving function, initialize
+ * the module, register the module service and start the async
+ * manager, processing IPC messages in an infinite loop.
+ *
+ * @param[in] service Service identification.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the pm_init() function.
+ * @return Other error codes as defined for the nil_initialize()
+ *         function.
+ * @return Other error codes as defined for the REGISTER_ME() macro
+ *         function.
+ *
+ */
+int nil_module_start(int service)
+{
+	async_set_client_connection(nil_client_connection);
+	int net_phone = net_connect_module();
+	if (net_phone < 0)
+		return net_phone;
+	
+	int rc = pm_init();
+	if (rc != EOK)
+		return rc;
+	
+	rc = nil_initialize(net_phone);
+	if (rc != EOK)
+		goto out;
+	
+	rc = async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
+	if (rc != EOK)
+		goto out;
+	
+	async_manager();
+	
+out:
+	pm_destroy();
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/net/tl/icmp_remote.c
===================================================================
--- uspace/lib/net/tl/icmp_remote.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/tl/icmp_remote.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/net/tl/tl_common.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libnet 
+/** @addtogroup libnet
  * @{
  */
@@ -39,8 +39,8 @@
 #include <packet_client.h>
 #include <packet_remote.h>
-#include <icmp_interface.h>
+#include <icmp_remote.h>
 #include <ip_remote.h>
 #include <ip_interface.h>
-#include <tl_interface.h>
+#include <tl_remote.h>
 
 #include <net/socket_codes.h>
Index: pace/lib/net/tl/tl_interface.c
===================================================================
--- uspace/lib/net/tl/tl_interface.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,68 +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
- * @{
- */
-
-#include <tl_interface.h>
-#include <generic.h>
-#include <packet_client.h>
-
-#include <ipc/services.h>
-#include <ipc/tl.h>
-
-#include <net/device.h>
-#include <net/packet.h>
-
-/** Notify the remote transport layer modules about the received packet/s.
- *
- * @param[in] tl_phone  The transport layer module phone used for remote calls.
- * @param[in] device_id The device identifier.
- * @param[in] packet    The received packet or the received packet queue.
- *                      The packet queue is used to carry a fragmented
- *                      datagram. The first packet contains the headers,
- *                      the others contain only data.
- * @param[in] target    The target transport layer module service to be
- *                      delivered to.
- * @param[in] error     The packet error reporting service. Prefixes the
- *                      received packet.
- *
- * @return EOK on success.
- *
- */
-int
-tl_received_msg(int tl_phone, device_id_t device_id, packet_t *packet,
-    services_t target, services_t error)
-{
-	return generic_received_msg_remote(tl_phone, NET_TL_RECEIVED, device_id,
-	    packet_get_id(packet), target, error);
-}
-
-/** @}
- */
Index: uspace/lib/net/tl/tl_remote.c
===================================================================
--- uspace/lib/net/tl/tl_remote.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/tl/tl_remote.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,67 @@
+/*
+ * 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
+ * @{
+ */
+
+#include <tl_remote.h>
+#include <generic.h>
+#include <packet_client.h>
+
+#include <ipc/services.h>
+#include <ipc/tl.h>
+
+#include <net/device.h>
+#include <net/packet.h>
+
+/** Notify the remote transport layer modules about the received packet/s.
+ *
+ * @param[in] tl_phone  The transport layer module phone used for remote calls.
+ * @param[in] device_id The device identifier.
+ * @param[in] packet    The received packet or the received packet queue.
+ *                      The packet queue is used to carry a fragmented
+ *                      datagram. The first packet contains the headers,
+ *                      the others contain only data.
+ * @param[in] target    The target transport layer module service to be
+ *                      delivered to.
+ * @param[in] error     The packet error reporting service. Prefixes the
+ *                      received packet.
+ *
+ * @return EOK on success.
+ *
+ */
+int tl_received_msg(int tl_phone, device_id_t device_id, packet_t *packet,
+    services_t target, services_t error)
+{
+	return generic_received_msg_remote(tl_phone, NET_TL_RECEIVED, device_id,
+	    packet_get_id(packet), target, error);
+}
+
+/** @}
+ */
Index: uspace/lib/net/tl/tl_skel.c
===================================================================
--- uspace/lib/net/tl/tl_skel.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/lib/net/tl/tl_skel.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,131 @@
+/*
+ * 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 libnet
+ * @{
+ */
+
+/** @file
+ * Transport layer module skeleton implementation.
+ * @see tl_skel.h
+ */
+
+#include <bool.h>
+#include <errno.h>
+#include <tl_skel.h>
+#include <net_interface.h>
+#include <net/modules.h>
+
+/** Default thread for new connections.
+ *
+ * @param[in] iid   The initial message identifier.
+ * @param[in] icall The initial message call structure.
+ *
+ */
+static void tl_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/*
+	 * Accept the connection by answering
+	 * the initial IPC_M_CONNECT_ME_TO call.
+	 */
+	async_answer_0(iid, EOK);
+	
+	/* Per-connection initialization */
+	tl_connection();
+	
+	while (true) {
+		ipc_call_t answer;
+		size_t count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = tl_message(callid, &call, &answer, &count);
+		
+		/*
+		 * End if told to either by the message or the processing
+		 * result.
+		 */
+		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
+		    (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, count);
+	}
+}
+
+/** Start the trasport layer module.
+ *
+ * Initialize the client connection serving function, initialize
+ * the module, register the module service and start the async
+ * manager, processing IPC messages in an infinite loop.
+ *
+ * @param[in] service Service identification.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the pm_init() function.
+ * @return Other error codes as defined for the il_initialize()
+ *         function.
+ * @return Other error codes as defined for the REGISTER_ME() macro
+ *         function.
+ *
+ */
+int tl_module_start(int service)
+{
+	async_set_client_connection(tl_client_connection);
+	int net_phone = net_connect_module();
+	if (net_phone < 0)
+		return net_phone;
+	
+	int rc = pm_init();
+	if (rc != EOK)
+		return rc;
+	
+	rc = tl_initialize(net_phone);
+	if (rc != EOK)
+		goto out;
+	
+	rc = async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
+	if (rc != EOK)
+		goto out;
+	
+	async_manager();
+	
+out:
+	pm_destroy();
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/packet/generic/packet_server.c
===================================================================
--- uspace/lib/packet/generic/packet_server.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/packet/generic/packet_server.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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;
 	}
@@ -322,5 +319,5 @@
 int
 packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    int *answer_count)
+    size_t *answer_count)
 {
 	packet_t *packet;
@@ -333,5 +330,5 @@
 	case NET_PACKET_CREATE_1:
 		packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX,
-		    IPC_GET_CONTENT(call), DEFAULT_SUFFIX);
+		    IPC_GET_CONTENT(*call), DEFAULT_SUFFIX);
 		if (!packet)
 			return ENOMEM;
@@ -343,9 +340,9 @@
 	case NET_PACKET_CREATE_4:
 		packet = packet_get_local(
-		    ((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(call)) ?
-		    IPC_GET_ADDR_LEN(call) : DEFAULT_ADDR_LEN),
-		    DEFAULT_PREFIX + IPC_GET_PREFIX(call),
-		    IPC_GET_CONTENT(call),
-		    DEFAULT_SUFFIX + IPC_GET_SUFFIX(call));
+		    ((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(*call)) ?
+		    IPC_GET_ADDR_LEN(*call) : DEFAULT_ADDR_LEN),
+		    DEFAULT_PREFIX + IPC_GET_PREFIX(*call),
+		    IPC_GET_CONTENT(*call),
+		    DEFAULT_SUFFIX + IPC_GET_SUFFIX(*call));
 		if (!packet)
 			return ENOMEM;
@@ -356,5 +353,5 @@
 	
 	case NET_PACKET_GET:
-		packet = pm_find(IPC_GET_ID(call));
+		packet = pm_find(IPC_GET_ID(*call));
 		if (!packet_is_valid(packet))
 			return ENOENT;
@@ -362,5 +359,5 @@
 	
 	case NET_PACKET_GET_SIZE:
-		packet = pm_find(IPC_GET_ID(call));
+		packet = pm_find(IPC_GET_ID(*call));
 		if (!packet_is_valid(packet))
 			return ENOENT;
@@ -370,5 +367,5 @@
 	
 	case NET_PACKET_RELEASE:
-		return packet_release_wrapper(IPC_GET_ID(call));
+		return packet_release_wrapper(IPC_GET_ID(*call));
 	}
 	
Index: uspace/lib/packet/include/packet_server.h
===================================================================
--- uspace/lib/packet/include/packet_server.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/lib/packet/include/packet_server.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -45,8 +45,8 @@
 #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 *,
-    int *);
+    size_t *);
 
 #endif
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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);
@@ -171,5 +181,4 @@
 		rc = devmap_device_register(name, &disk[i].devmap_handle);
 		if (rc != EOK) {
-			devmap_hangup_phone(DEVMAP_DRIVER);
 			printf(NAME ": Unable to register device %s.\n", name);
 			return rc;
@@ -205,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");
 	}
 
@@ -267,5 +281,5 @@
 	sysarg_t method;
 	devmap_handle_t dh;
-	int flags;
+	unsigned int flags;
 	int retval;
 	uint64_t ba;
@@ -283,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;
 	}
@@ -297,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;
 	}
@@ -309,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:
@@ -315,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;
@@ -325,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;
@@ -332,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;
@@ -342,5 +356,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -355,4 +369,5 @@
 	identify_data_t idata;
 	uint8_t model[40];
+	ata_inquiry_data_t inq_data;
 	uint16_t w;
 	uint8_t c;
@@ -361,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;
@@ -424,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;
 }
@@ -437,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;
@@ -443,5 +512,5 @@
 		++ba;
 		--cnt;
-		buf += block_size;
+		buf += disk[disk_id].block_size;
 	}
 
@@ -455,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;
@@ -462,5 +534,5 @@
 		++ba;
 		--cnt;
-		buf += block_size;
+		buf += disk[disk_id].block_size;
 	}
 
@@ -475,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)
@@ -486,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);
@@ -495,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;
@@ -511,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;
@@ -526,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)
 {
@@ -581,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;
@@ -603,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)
 {
@@ -657,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/bd/ata_bd/ata_bd.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/bd/ata_bd/ata_hw.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/bd/file_bd/file_bd.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -41,5 +41,4 @@
 #include <stdio.h>
 #include <unistd.h>
-#include <ipc/ipc.h>
 #include <ipc/bd.h>
 #include <async.h>
@@ -120,5 +119,4 @@
 	rc = devmap_device_register(device_name, &devmap_handle);
 	if (rc != EOK) {
-		devmap_hangup_phone(DEVMAP_DRIVER);
 		printf(NAME ": Unable to register device '%s'.\n",
 			device_name);
@@ -179,5 +177,5 @@
 	sysarg_t method;
 	size_t comm_size;
-	int flags;
+	unsigned int flags;
 	int retval;
 	uint64_t ba;
@@ -185,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;
 	}
@@ -194,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;
 	}
@@ -206,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:
@@ -229,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;
@@ -239,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/bd/gxe_bd/gxe_bd.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -39,5 +39,4 @@
 #include <libarch/ddi.h>
 #include <ddi.h>
-#include <ipc/ipc.h>
 #include <ipc/bd.h>
 #include <async.h>
@@ -145,5 +144,4 @@
 		rc = devmap_device_register(name, &devmap_handle[i]);
 		if (rc != EOK) {
-			devmap_hangup_phone(DEVMAP_DRIVER);
 			printf(NAME ": Unable to register device %s.\n", name);
 			return rc;
@@ -162,5 +160,5 @@
 	sysarg_t method;
 	devmap_handle_t dh;
-	int flags;
+	unsigned int flags;
 	int retval;
 	uint64_t ba;
@@ -178,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;
 	}
@@ -197,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;
 	}
@@ -209,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:
@@ -232,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:
@@ -241,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/bd/part/guid_part/guid_part.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -47,5 +47,4 @@
 #include <stdlib.h>
 #include <unistd.h>
-#include <ipc/ipc.h>
 #include <ipc/bd.h>
 #include <async.h>
@@ -191,5 +190,4 @@
 		rc = devmap_device_register(name, &dev);
 		if (rc != EOK) {
-			devmap_hangup_phone(DEVMAP_DRIVER);
 			printf(NAME ": Unable to register device %s.\n", name);
 			return rc;
@@ -317,5 +315,5 @@
 	sysarg_t method;
 	devmap_handle_t dh;
-	int flags;
+	unsigned int flags;
 	int retval;
 	aoff64_t ba;
@@ -336,5 +334,5 @@
 
 	if (part == NULL) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -343,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;
 	}
@@ -352,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;
 	}
@@ -364,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:
@@ -387,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;
@@ -397,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/bd/part/mbr_part/mbr_part.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -57,5 +57,4 @@
 #include <stdlib.h>
 #include <unistd.h>
-#include <ipc/ipc.h>
 #include <ipc/bd.h>
 #include <async.h>
@@ -242,5 +241,4 @@
 		rc = devmap_device_register(name, &dev);
 		if (rc != EOK) {
-			devmap_hangup_phone(DEVMAP_DRIVER);
 			printf(NAME ": Unable to register device %s.\n", name);
 			return rc;
@@ -395,5 +393,5 @@
 	sysarg_t method;
 	devmap_handle_t dh;
-	int flags;
+	unsigned int flags;
 	int retval;
 	uint64_t ba;
@@ -414,5 +412,5 @@
 
 	if (part == NULL) {
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -421,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;
 	}
@@ -430,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;
 	}
@@ -442,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:
@@ -465,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;
@@ -475,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/bd/rd/rd.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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);
 	}
 }
@@ -241,5 +240,4 @@
 	devmap_handle_t devmap_handle;
 	if (devmap_device_register("bd/initrd", &devmap_handle) != EOK) {
-		devmap_hangup_phone(DEVMAP_DRIVER);
 		printf("%s: Unable to register device\n", NAME);
 		return false;
Index: uspace/srv/clip/clip.c
===================================================================
--- uspace/srv/clip/clip.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/clip/clip.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/devman/devman.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -590,5 +590,5 @@
 	}
 
-	ipc_hangup(phone);
+	async_hangup(phone);
 
 	/*
@@ -787,5 +787,5 @@
 		if (phone >= 0) {
 			add_device(phone, drv, node, tree);
-			ipc_hangup(phone);
+			async_hangup(phone);
 		}
 	}
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/devman/devman.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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>
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/devman/main.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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);
@@ -219,5 +219,5 @@
 	if (parent == NULL) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
-		ipc_answer_0(callid, ENOENT);
+		async_answer_0(callid, ENOENT);
 		return;
 	}
@@ -227,5 +227,5 @@
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
-		ipc_answer_0(callid, rc);
+		async_answer_0(callid, rc);
 		return;
 	}
@@ -235,5 +235,5 @@
 		fibril_rwlock_write_unlock(&tree->rwlock);
 		delete_dev_node(node);
-		ipc_answer_0(callid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
 		return;
 	}
@@ -264,5 +264,5 @@
 
 	/* Return device handle to parent's driver. */
-	ipc_answer_1(callid, EOK, node->handle);
+	async_answer_1(callid, EOK, node->handle);
 }
 
@@ -302,5 +302,5 @@
 	    0, 0, 0, 0);
 	if (rc != EOK) {
-		ipc_answer_0(callid, rc);
+		async_answer_0(callid, rc);
 		return;
 	}	
@@ -308,5 +308,5 @@
 	node_t *dev = find_dev_node(&device_tree, handle);
 	if (dev == NULL) {
-		ipc_answer_0(callid, ENOENT);
+		async_answer_0(callid, ENOENT);
 		return;
 	}
@@ -321,5 +321,5 @@
 	    "asigned to it\n", dev->pathname, class_name, class_info->dev_name);
 
-	ipc_answer_0(callid, EOK);
+	async_answer_0(callid, EOK);
 }
 
@@ -343,5 +343,5 @@
 {
 	/* Accept the connection. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	driver_t *driver = devman_driver_register();
@@ -379,5 +379,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, EINVAL); 
+			async_answer_0(callid, EINVAL); 
 			break;
 		}
@@ -393,5 +393,5 @@
 	int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
 	if (rc != EOK) {
-		ipc_answer_0(iid, rc);
+		async_answer_0(iid, rc);
 		return;
 	}
@@ -402,9 +402,9 @@
 
 	if (dev == NULL) {
-		ipc_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	ipc_answer_1(iid, EOK, dev->handle);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, dev->handle);
 }
 
@@ -414,5 +414,5 @@
 {
 	/* Accept connection. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	bool cont = true;
@@ -429,5 +429,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOENT);
+			async_answer_0(callid, ENOENT);
 		}
 	}
@@ -443,5 +443,5 @@
 		printf(NAME ": devman_forward error - no device with handle %" PRIun
 		    " was found.\n", handle);
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
@@ -460,5 +460,5 @@
 		printf(NAME ": devman_forward error - the device is not in %" PRIun
 		    " usable state.\n", handle);
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
@@ -474,5 +474,5 @@
 		    driver->name);
 		printf("the driver's phone is %" PRIun ").\n", driver->phone);
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -480,5 +480,5 @@
 	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_forward_fast(iid, driver->phone, method, dev->handle, 0, IPC_FF_NONE);
 }
 
@@ -495,14 +495,14 @@
 	
 	if (dev == NULL || dev->drv == NULL) {
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
 	
 	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, dev->handle, 0,
 	    IPC_FF_NONE);
 	printf(NAME ": devman_connection_devmapper: forwarded connection to "
@@ -535,5 +535,5 @@
 	default:
 		/* No such interface */
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 	}
 }
@@ -586,6 +586,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/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/devmap/devmap.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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);
 	
 	/*
@@ -438,5 +438,5 @@
 	fibril_mutex_unlock(&drivers_list_mutex);
 	
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	return driver;
@@ -456,5 +456,5 @@
 	
 	if (driver->phone != 0)
-		ipc_hangup(driver->phone);
+		async_hangup(driver->phone);
 	
 	/* Remove it from list of drivers */
@@ -491,5 +491,5 @@
 {
 	if (driver == NULL) {
-		ipc_answer_0(iid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
 		return;
 	}
@@ -499,5 +499,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 +512,5 @@
 	if (rc != EOK) {
 		free(device);
-		ipc_answer_0(iid, rc);
+		async_answer_0(iid, rc);
 		return;
 	}
@@ -520,5 +520,5 @@
 		free(fqdn);
 		free(device);
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -534,5 +534,5 @@
 		free(device->name);
 		free(device);
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
@@ -549,5 +549,5 @@
 		free(device->name);
 		free(device);
-		ipc_answer_0(iid, EEXISTS);
+		async_answer_0(iid, EEXISTS);
 		return;
 	}
@@ -571,5 +571,5 @@
 	fibril_mutex_unlock(&devices_list_mutex);
 	
-	ipc_answer_1(iid, EOK, device->handle);
+	async_answer_1(iid, EOK, device->handle);
 }
 
@@ -602,14 +602,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 +633,5 @@
 	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(iid, rc);
+		async_answer_0(iid, rc);
 		return;
 	}
@@ -641,5 +641,5 @@
 	if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
 		free(fqdn);
-		ipc_answer_0(iid, EINVAL);
+		async_answer_0(iid, EINVAL);
 		return;
 	}
@@ -668,5 +668,5 @@
 		}
 		
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		free(ns_name);
 		free(name);
@@ -675,5 +675,5 @@
 	}
 	
-	ipc_answer_1(iid, EOK, dev->handle);
+	async_answer_1(iid, EOK, dev->handle);
 	
 	fibril_mutex_unlock(&devices_list_mutex);
@@ -696,5 +696,5 @@
 	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
-		ipc_answer_0(iid, rc);
+		async_answer_0(iid, rc);
 		return;
 	}
@@ -721,5 +721,5 @@
 		}
 		
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		free(name);
 		fibril_mutex_unlock(&devices_list_mutex);
@@ -727,5 +727,5 @@
 	}
 	
-	ipc_answer_1(iid, EOK, namespace->handle);
+	async_answer_1(iid, EOK, namespace->handle);
 	
 	fibril_mutex_unlock(&devices_list_mutex);
@@ -743,9 +743,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 +755,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 +766,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 +778,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 +794,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 +802,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 +824,5 @@
 	fibril_mutex_unlock(&devices_list_mutex);
 	
-	ipc_answer_0(iid, retval);
+	async_answer_0(iid, retval);
 }
 
@@ -835,12 +835,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 +852,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 +860,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 +868,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 +891,5 @@
 	fibril_mutex_unlock(&devices_list_mutex);
 	
-	ipc_answer_0(iid, retval);
+	async_answer_0(iid, retval);
 }
 
@@ -910,5 +910,5 @@
 	if (!fnd) {
 		fibril_mutex_unlock(&null_devices_mutex);
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
@@ -920,5 +920,5 @@
 	if (dev_name == NULL) {
 		fibril_mutex_unlock(&null_devices_mutex);
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
@@ -928,5 +928,5 @@
 	if (device == NULL) {
 		fibril_mutex_unlock(&null_devices_mutex);
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
@@ -938,5 +938,5 @@
 		fibril_mutex_lock(&devices_list_mutex);
 		fibril_mutex_unlock(&null_devices_mutex);
-		ipc_answer_0(iid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
 		return;
 	}
@@ -960,5 +960,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 +967,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 +975,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 +986,5 @@
 	
 	fibril_mutex_unlock(&null_devices_mutex);
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 }
 
@@ -1012,5 +1012,5 @@
 {
 	/* Accept connection */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	devmap_driver_t *driver = devmap_driver_register();
@@ -1029,7 +1029,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 +1048,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOENT);
+			async_answer_0(callid, ENOENT);
 		}
 	}
@@ -1067,5 +1067,5 @@
 {
 	/* Accept connection */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	bool cont = true;
@@ -1106,5 +1106,5 @@
 			break;
 		default:
-			ipc_answer_0(callid, ENOENT);
+			async_answer_0(callid, ENOENT);
 		}
 	}
@@ -1130,5 +1130,5 @@
 	default:
 		/* No such interface */
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 	}
 }
@@ -1150,6 +1150,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/fs/devfs/devfs.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -36,5 +36,4 @@
  */
 
-#include <ipc/ipc.h>
 #include <macros.h>
 #include <bool.h>
@@ -454,7 +453,4 @@
 		return false;
 	
-	if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0)
-		return false;
-	
 	return true;
 }
@@ -468,10 +464,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);
 }
 
@@ -483,5 +479,5 @@
 void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_answer_0(rid, ENOTSUP);
+	async_answer_0(rid, ENOTSUP);
 }
 
@@ -516,6 +512,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;
 		}
@@ -538,5 +534,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;
 		}
@@ -553,5 +549,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;
 			}
@@ -560,6 +556,6 @@
 		}
 		
-		ipc_answer_0(callid, ENOENT);
-		ipc_answer_1(rid, ENOENT, 0);
+		async_answer_0(callid, ENOENT);
+		async_answer_1(rid, ENOENT, 0);
 		return;
 	}
@@ -572,6 +568,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;
 		}
@@ -583,11 +579,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;
 	}
@@ -604,5 +600,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(rid, ENOENT);
+			async_answer_0(rid, ENOENT);
 			return;
 		}
@@ -614,6 +610,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;
 		}
@@ -626,5 +622,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);
 		
@@ -635,9 +631,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);
 }
 
@@ -646,5 +642,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;
 	}
@@ -654,5 +650,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		ipc_answer_0(rid, ENOTSUP);
+		async_answer_0(rid, ENOTSUP);
 		return;
 	}
@@ -668,5 +664,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(rid, ENOENT);
+			async_answer_0(rid, ENOENT);
 			return;
 		}
@@ -678,6 +674,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;
 		}
@@ -690,5 +686,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);
@@ -700,14 +696,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);
 }
 
@@ -717,5 +713,5 @@
 	
 	if (index == 0) {
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		return;
 	}
@@ -725,5 +721,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		return;
 	}
@@ -738,5 +734,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(rid, ENOENT);
+			async_answer_0(rid, ENOENT);
 			return;
 		}
@@ -747,5 +743,5 @@
 		
 		if (dev->refcount == 0) {
-			ipc_hangup(dev->phone);
+			async_hangup(dev->phone);
 			hash_table_remove(&devices, key, DEVICES_KEYS);
 		}
@@ -753,9 +749,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);
 }
 
@@ -765,5 +761,5 @@
 	
 	if (index == 0) {
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		return;
 	}
@@ -773,5 +769,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		ipc_answer_0(rid, EOK);
+		async_answer_0(rid, EOK);
 		return;
 	}
@@ -786,5 +782,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(rid, ENOENT);
+			async_answer_0(rid, ENOENT);
 			return;
 		}
@@ -805,14 +801,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/fs/devfs/devfs_ops.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/fs/fat/fat.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/fs/fat/fat.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/fs/tmpfs/tmpfs.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/adb_mouse/adb_dev.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/adb_mouse/adb_mouse.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/char_mouse/char_mouse.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/char_mouse/chardev.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/console/console.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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);
 }
 
@@ -437,5 +437,5 @@
 			retval = ENOENT;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -472,5 +472,5 @@
 		}
 
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -483,5 +483,5 @@
 	
 	if (rc != EOK) {
-		ipc_answer_0(rid, rc);
+		async_answer_0(rid, rc);
 		return;
 	}
@@ -498,5 +498,5 @@
 	
 	gcons_notify_char(cons->index);
-	ipc_answer_1(rid, EOK, size);
+	async_answer_1(rid, EOK, size);
 	
 	free(buf);
@@ -508,6 +508,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;
 	}
@@ -515,6 +515,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;
 	}
@@ -534,5 +534,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 {
@@ -552,5 +552,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);
@@ -578,5 +578,5 @@
 	
 	if (cons == NULL) {
-		ipc_answer_0(iid, ENOENT);
+		async_answer_0(iid, ENOENT);
 		return;
 	}
@@ -597,5 +597,5 @@
 	
 	/* Accept the connection */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
@@ -657,5 +657,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;
 			}
@@ -701,5 +701,5 @@
 			break;
 		}
-		ipc_answer_3(callid, EOK, arg1, arg2, arg3);
+		async_answer_3(callid, EOK, arg1, arg2, arg3);
 	}
 }
@@ -726,11 +726,9 @@
 	
 	/* NB: The callback connection is slotted for removal */
-	sysarg_t phonehash;
-	if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
+	if (async_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, keyboard_events)
+	    != 0) {
 		printf(NAME ": Failed to create callback from input device\n");
 		return false;
 	}
-	
-	async_new_connection(phonehash, 0, NULL, keyboard_events);
 	
 	/* Connect to mouse device */
@@ -749,5 +747,6 @@
 	}
 	
-	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;
@@ -755,9 +754,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");
@@ -816,5 +814,4 @@
 			
 			if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) {
-				devmap_hangup_phone(DEVMAP_DRIVER);
 				printf(NAME ": Unable to register device %s\n", vc);
 				return false;
@@ -836,8 +833,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);
 	
 	return true;
Index: uspace/srv/hid/console/gcons.c
===================================================================
--- uspace/srv/hid/console/gcons.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/console/gcons.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/fb/ega.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/fb/fb.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/fb/main.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/fb/serial_console.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/fb/serial_console.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/kbd/generic/kbd.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/kbd/port/adb.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/kbd/port/chardev.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/kbd/port/gxemul.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/kbd/port/msim.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/kbd/port/ns16550.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/kbd/port/pl050.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/kbd/port/z8530.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -42,5 +42,4 @@
 #include <io/console.h>
 #include <vfs/vfs.h>
-#include <ipc/ipc.h>
 #include <ipc/mouse.h>
 #include <async.h>
@@ -102,5 +101,4 @@
 	rc = devmap_device_register(NAMESPACE "/mouse", &ts->devmap_handle);
 	if (rc != EOK) {
-		devmap_hangup_phone(DEVMAP_DRIVER);
 		printf(NAME ": Unable to register device %s.\n",
 		    NAMESPACE "/mouse");
@@ -141,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);
@@ -378,5 +376,5 @@
 	int retval;
 
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	while (1) {
@@ -385,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:
@@ -402,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -162,5 +162,4 @@
 	rc = devmap_device_register("adb/kbd", &devmap_handle);
 	if (rc != EOK) {
-		devmap_hangup_phone(DEVMAP_DRIVER);
 		printf(NAME ": Unable to register device %s.\n", "adb/kdb");
 		return rc;
@@ -172,5 +171,4 @@
 	rc = devmap_device_register("adb/mouse", &devmap_handle);
 	if (rc != EOK) {
-		devmap_hangup_phone(DEVMAP_DRIVER);
 		printf(NAME ": Unable to register device %s.\n", "adb/mouse");
 		return rc;
@@ -211,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) {
@@ -224,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:
@@ -247,5 +245,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -278,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hw/char/i8042/i8042.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -40,5 +40,4 @@
 #include <libarch/ddi.h>
 #include <devmap.h>
-#include <ipc/ipc.h>
 #include <async.h>
 #include <unistd.h>
@@ -148,5 +147,4 @@
 		rc = devmap_device_register(name, &i8042_port[i].devmap_handle);
 		if (rc != EOK) {
-			devmap_hangup_phone(DEVMAP_DRIVER);
 			printf(NAME ": Unable to register device %s.\n", name);
 			return rc;
@@ -200,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);
@@ -237,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");
@@ -252,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:
@@ -273,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -40,5 +40,4 @@
 #include <libarch/ddi.h>
 #include <devmap.h>
-#include <ipc/ipc.h>
 #include <ipc/char.h>
 #include <async.h>
@@ -95,5 +94,4 @@
 	rc = devmap_device_register(NAMESPACE "/" NAME, &uart->devmap_handle);
 	if (rc != EOK) {
-		devmap_hangup_phone(DEVMAP_DRIVER);
 		printf(NAME ": Unable to register device %s.\n",
 		    NAMESPACE "/" NAME);
@@ -120,5 +118,5 @@
 
 	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 
 	while (1) {
@@ -128,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:
@@ -145,5 +143,5 @@
 			break;
 		}
-		ipc_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -192,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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hw/irc/apic/apic.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hw/irc/fhc/fhc.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hw/irc/i8259/i8259.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/hw/irc/obio/obio.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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: pace/srv/hw/netif/DRIVER_REMOVAL
===================================================================
--- uspace/srv/hw/netif/DRIVER_REMOVAL	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,5 +1,0 @@
-The netif drivers in this directory are subject to removal / replacement by
-prospective new drivers that meet our criteria for portability, follow our
-coding style and integrate with our device driver framework.
-
-DO NOT ADD ANY NEW DRIVERS HERE OR BASE NEW DRIVERS ON THOSE FOUND HERE.
Index: pace/srv/hw/netif/dp8390/Makefile
===================================================================
--- uspace/srv/hw/netif/dp8390/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,48 +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 = ../../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-BINARY = dp8390
-
-SOURCES = \
-	dp8390.c \
-	dp8390_module.c \
-	ne2000.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/hw/netif/dp8390/dp8390.c
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,695 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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.
- */
-
-/*
- * This code is based upon the NE2000 driver for MINIX,
- * distributed according to a BSD-style license.
- *
- * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
- * Copyright (c) 1992, 1994 Philip Homburg
- * Copyright (c) 1996 G. Falzoni
- *
- */
-
-/** @addtogroup dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface core implementation.
- */
-
-#include <assert.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <netif_local.h>
-#include <net/packet.h>
-#include <nil_interface.h>
-#include <packet_client.h>
-#include "dp8390_drv.h"
-#include "dp8390_port.h"
-#include "dp8390.h"
-#include "ne2000.h"
-
-/** Read a memory block byte by byte.
- *
- *  @param[in] port The source address.
- *  @param[out] buf The destination buffer.
- *  @param[in] size The memory block size in bytes.
- *
- */
-static void outsb(port_t port, void * buf, size_t size);
-
-/** Read a memory block word by word.
- *
- *  @param[in] port The source address.
- *  @param[out] buf The destination buffer.
- *  @param[in] size The memory block size in bytes.
- *
- */
-static void outsw(port_t port, void * buf, size_t size);
-
-/*
- * Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
- * on writes to the CR register. Additional CR_STAs do not appear to hurt
- * genuine dp8390s.
- */
-#define CR_EXTRA  CR_STA
-
-static void dp_init(dpeth_t *dep);
-static void dp_reinit(dpeth_t *dep);
-static void dp_reset(dpeth_t *dep);
-static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep);
-static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length);
-static void conf_hw(dpeth_t *dep);
-static void insb(port_t port, void *buf, size_t size);
-static void insw(port_t port, void *buf, size_t size);
-
-int do_probe(dpeth_t *dep)
-{
-	/* This is the default, try to (re)locate the device. */
-	conf_hw(dep);
-	if (!dep->up)
-		/* Probe failed, or the device is configured off. */
-		return EXDEV;
-	
-	if (dep->up)
-		dp_init(dep);
-	
-	return EOK;
-}
-
-/** Initialize and/or start the network interface.
- *
- *  @param[in,out] dep The network interface structure.
- *
- *  @return EOK on success.
- *  @return EXDEV if the network interface is disabled.
- *
- */
-int do_init(dpeth_t *dep)
-{
-	if (!dep->up)
-		/* FIXME: Perhaps call do_probe()? */
-		return EXDEV;
-	
-	assert(dep->up);
-	assert(dep->enabled);
-	
-	dp_reinit(dep);
-	return EOK;
-}
-
-void do_stop(dpeth_t *dep)
-{
-	if ((dep->up) && (dep->enabled)) {
-		outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
-		ne_stop(dep);
-		
-		dep->enabled = false;
-		dep->stopped = false;
-		dep->sending = false;
-		dep->send_avail = false;
-	}
-}
-
-static void dp_user2nic(dpeth_t *dep, void *buf, size_t offset, int nic_addr, size_t size)
-{
-	size_t ecount = size & ~1;
-	
-	outb_reg0(dep, DP_ISR, ISR_RDC);
-	
-	if (dep->de_16bit) {
-		outb_reg0(dep, DP_RBCR0, ecount & 0xff);
-		outb_reg0(dep, DP_RBCR1, ecount >> 8);
-	} else {
-		outb_reg0(dep, DP_RBCR0, size & 0xff);
-		outb_reg0(dep, DP_RBCR1, size >> 8);
-	}
-	
-	outb_reg0(dep, DP_RSAR0, nic_addr & 0xff);
-	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
-	
-	if (dep->de_16bit) {
-		void *ptr = buf + offset;
-		
-		if (ecount != 0) {
-			outsw(dep->de_data_port, ptr, ecount);
-			size -= ecount;
-			offset += ecount;
-			ptr += ecount;
-		}
-		
-		if (size) {
-			assert(size == 1);
-			
-			uint16_t two_bytes;
-			
-			memcpy(&(((uint8_t *) &two_bytes)[0]), ptr, 1);
-			outw(dep->de_data_port, two_bytes);
-		}
-	} else
-		outsb(dep->de_data_port, buf + offset, size);
-	
-	unsigned int i;
-	for (i = 0; i < 100; i++) {
-		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
-			break;
-	}
-	
-	if (i == 100)
-		fprintf(stderr, "Remote DMA failed to complete\n");
-}
-
-int do_pwrite(dpeth_t *dep, packet_t *packet, int from_int)
-{
-	int size;
-	int sendq_head;
-	
-	assert(dep->up);
-	assert(dep->enabled);
-	
-	if (dep->send_avail) {
-		fprintf(stderr, "Send already in progress\n");
-		return EBUSY;
-	}
-	
-	sendq_head = dep->de_sendq_head;
-	if (dep->de_sendq[sendq_head].sq_filled) {
-		if (from_int)
-			fprintf(stderr, "dp8390: should not be sending\n");
-		dep->send_avail = true;
-		dep->sending = false;
-		
-		return EBUSY;
-	}
-	
-	assert(!dep->sending);
-	
-	void *buf = packet_get_data(packet);
-	size = packet_get_data_length(packet);
-	
-	if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) {
-		fprintf(stderr, "dp8390: invalid packet size\n");
-		return EINVAL;
-	}
-	
-	dp_user2nic(dep, buf, 0, dep->de_sendq[sendq_head].sq_sendpage
-	    * DP_PAGESIZE, size);
-	dep->de_sendq[sendq_head].sq_filled = true;
-	
-	if (dep->de_sendq_tail == sendq_head) {
-		outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
-		outb_reg0(dep, DP_TBCR1, size >> 8);
-		outb_reg0(dep, DP_TBCR0, size & 0xff);
-		outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);  /* there it goes .. */
-	} else
-		dep->de_sendq[sendq_head].sq_size = size;
-	
-	if (++sendq_head == dep->de_sendq_nr)
-		sendq_head = 0;
-	
-	assert(sendq_head < SENDQ_NR);
-	dep->de_sendq_head = sendq_head;
-	dep->sending = true;
-	
-	if (from_int)
-		return EOK;
-	
-	dep->sending = false;
-	
-	return EOK;
-}
-
-void dp_init(dpeth_t *dep)
-{
-	int dp_rcr_reg;
-	int i;
-	
-	/* General initialization */
-	dep->enabled = false;
-	dep->stopped = false;
-	dep->sending = false;
-	dep->send_avail = false;
-	ne_init(dep);
-	
-	printf("Ethernet address ");
-	for (i = 0; i < 6; i++)
-		printf("%02x%c", dep->de_address.ea_addr[i], i < 5 ? ':' : '\n');
-	
-	/*
-	 * Initialization of the dp8390 following the mandatory procedure
-	 * in reference manual ("DP8390D/NS32490D NIC Network Interface
-	 * Controller", National Semiconductor, July 1995, Page 29).
-	 */
-	
-	/* Step 1: */
-	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
-	
-	/* Step 2: */
-	if (dep->de_16bit)
-		outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
-	else
-		outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
-	
-	/* Step 3: */
-	outb_reg0(dep, DP_RBCR0, 0);
-	outb_reg0(dep, DP_RBCR1, 0);
-	
-	/* Step 4: */
-	dp_rcr_reg = RCR_AB;  /* Enable broadcasts */
-	
-	outb_reg0(dep, DP_RCR, dp_rcr_reg);
-	
-	/* Step 5: */
-	outb_reg0(dep, DP_TCR, TCR_INTERNAL);
-	
-	/* Step 6: */
-	outb_reg0(dep, DP_BNRY, dep->de_startpage);
-	outb_reg0(dep, DP_PSTART, dep->de_startpage);
-	outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
-	
-	/* Step 7: */
-	outb_reg0(dep, DP_ISR, 0xFF);
-	
-	/* Step 8: */
-	outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
-	    IMR_OVWE | IMR_CNTE);
-	
-	/* Step 9: */
-	outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
-	
-	outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
-	outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
-	outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
-	outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
-	outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
-	outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
-	
-	outb_reg1(dep, DP_MAR0, 0xff);
-	outb_reg1(dep, DP_MAR1, 0xff);
-	outb_reg1(dep, DP_MAR2, 0xff);
-	outb_reg1(dep, DP_MAR3, 0xff);
-	outb_reg1(dep, DP_MAR4, 0xff);
-	outb_reg1(dep, DP_MAR5, 0xff);
-	outb_reg1(dep, DP_MAR6, 0xff);
-	outb_reg1(dep, DP_MAR7, 0xff);
-	
-	outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
-	
-	/* Step 10: */
-	outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
-	
-	/* Step 11: */
-	outb_reg0(dep, DP_TCR, TCR_NORMAL);
-	
-	inb_reg0(dep, DP_CNTR0);  /* Reset counters by reading */
-	inb_reg0(dep, DP_CNTR1);
-	inb_reg0(dep, DP_CNTR2);
-	
-	/* Finish the initialization. */
-	dep->enabled = true;
-	for (i = 0; i < dep->de_sendq_nr; i++)
-		dep->de_sendq[i].sq_filled= 0;
-	
-	dep->de_sendq_head = 0;
-	dep->de_sendq_tail = 0;
-}
-
-static void dp_reinit(dpeth_t *dep)
-{
-	int dp_rcr_reg;
-	
-	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
-	
-	/* Enable broadcasts */
-	dp_rcr_reg = RCR_AB;
-	
-	outb_reg0(dep, DP_RCR, dp_rcr_reg);
-}
-
-static void dp_reset(dpeth_t *dep)
-{
-	int i;
-	
-	/* Stop chip */
-	outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
-	outb_reg0(dep, DP_RBCR0, 0);
-	outb_reg0(dep, DP_RBCR1, 0);
-	
-	for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
-		; /* Do nothing */
-	
-	outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST);
-	outb_reg0(dep, DP_CR, CR_STA | CR_DM_ABORT);
-	outb_reg0(dep, DP_TCR, TCR_NORMAL);
-	
-	/* Acknowledge the ISR_RDC (remote DMA) interrupt. */
-	for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RDC) == 0); i++)
-		; /* Do nothing */
-	
-	outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
-	
-	/*
-	 * Reset the transmit ring. If we were transmitting a packet, we
-	 * pretend that the packet is processed. Higher layers will
-	 * retransmit if the packet wasn't actually sent.
-	 */
-	dep->de_sendq_head = 0;
-	dep->de_sendq_tail = 0;
-	
-	for (i = 0; i < dep->de_sendq_nr; i++)
-		dep->de_sendq[i].sq_filled = 0;
-	
-	dep->send_avail = false;
-	dep->stopped = false;
-}
-
-static uint8_t isr_acknowledge(dpeth_t *dep)
-{
-	uint8_t isr = inb_reg0(dep, DP_ISR);
-	if (isr != 0)
-		outb_reg0(dep, DP_ISR, isr);
-	
-	return isr;
-}
-
-void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, uint8_t isr)
-{
-	int tsr;
-	int size, sendq_tail;
-	
-	for (; (isr & 0x7f) != 0; isr = isr_acknowledge(dep)) {
-		if (isr & (ISR_PTX | ISR_TXE)) {
-			if (isr & ISR_TXE)
-				dep->de_stat.ets_sendErr++;
-			else {
-				tsr = inb_reg0(dep, DP_TSR);
-				
-				if (tsr & TSR_PTX)
-					dep->de_stat.ets_packetT++;
-				
-				if (tsr & TSR_COL)
-					dep->de_stat.ets_collision++;
-				
-				if (tsr & TSR_ABT)
-					dep->de_stat.ets_transAb++;
-				
-				if (tsr & TSR_CRS)
-					dep->de_stat.ets_carrSense++;
-				
-				if ((tsr & TSR_FU) && (++dep->de_stat.ets_fifoUnder <= 10))
-					printf("FIFO underrun\n");
-				
-				if ((tsr & TSR_CDH) && (++dep->de_stat.ets_CDheartbeat <= 10))
-					printf("CD heart beat failure\n");
-				
-				if (tsr & TSR_OWC)
-					dep->de_stat.ets_OWC++;
-			}
-			
-			sendq_tail = dep->de_sendq_tail;
-			
-			if (!(dep->de_sendq[sendq_tail].sq_filled)) {
-				printf("PTX interrupt, but no frame to send\n");
-				continue;
-			}
-			
-			dep->de_sendq[sendq_tail].sq_filled = false;
-			
-			if (++sendq_tail == dep->de_sendq_nr)
-				sendq_tail = 0;
-			
-			dep->de_sendq_tail = sendq_tail;
-			
-			if (dep->de_sendq[sendq_tail].sq_filled) {
-				size = dep->de_sendq[sendq_tail].sq_size;
-				outb_reg0(dep, DP_TPSR,
-				    dep->de_sendq[sendq_tail].sq_sendpage);
-				outb_reg0(dep, DP_TBCR1, size >> 8);
-				outb_reg0(dep, DP_TBCR0, size & 0xff);
-				outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
-			}
-			
-			dep->send_avail = false;
-		}
-		
-		if (isr & ISR_PRX)
-			dp_recv(nil_phone, device_id, dep);
-		
-		if (isr & ISR_RXE)
-			dep->de_stat.ets_recvErr++;
-		
-		if (isr & ISR_CNT) {
-			dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
-			dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
-			dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
-		}
-		
-		if (isr & ISR_OVW)
-			dep->de_stat.ets_OVW++;
-		
-		if (isr & ISR_RDC) {
-			/* Nothing to do */
-		}
-		
-		if (isr & ISR_RST) {
-			/*
-			 * This means we got an interrupt but the ethernet
-			 * chip is shutdown. We set the flag 'stopped'
-			 * and continue processing arrived packets. When the
-			 * receive buffer is empty, we reset the dp8390.
-			 */
-			dep->stopped = true;
-			break;
-		}
-	}
-	
-	if (dep->stopped) {
-		/*
-		 * The chip is stopped, and all arrived
-		 * frames are delivered.
-		 */
-		dp_reset(dep);
-	}
-	
-	dep->sending = false;
-}
-
-static void dp_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst)
-{
-	offset = page * DP_PAGESIZE + offset;
-	
-	outb_reg0(dep, DP_RBCR0, size & 0xff);
-	outb_reg0(dep, DP_RBCR1, size >> 8);
-	outb_reg0(dep, DP_RSAR0, offset & 0xff);
-	outb_reg0(dep, DP_RSAR1, offset >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	if (dep->de_16bit) {
-		assert((size % 2) == 0);
-		insw(dep->de_data_port, dst, size);
-	} else
-		insb(dep->de_data_port, dst, size);
-}
-
-static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep)
-{
-	dp_rcvhdr_t header;
-	int pageno, curr, next;
-	size_t length;
-	int packet_processed, r;
-	uint16_t eth_type;
-	
-	packet_processed = false;
-	pageno = inb_reg0(dep, DP_BNRY) + 1;
-	if (pageno == dep->de_stoppage)
-		pageno = dep->de_startpage;
-	
-	do {
-		outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
-		curr = inb_reg1(dep, DP_CURR);
-		outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
-		
-		if (curr == pageno)
-			break;
-		
-		dp_getblock(dep, pageno, (size_t) 0, sizeof(header), &header);
-		dp_getblock(dep, pageno, sizeof(header) +
-		    2 * sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
-		
-		length = (header.dr_rbcl | (header.dr_rbch << 8)) - sizeof(dp_rcvhdr_t);
-		next = header.dr_next;
-		if ((length < ETH_MIN_PACK_SIZE) || (length > ETH_MAX_PACK_SIZE_TAGGED)) {
-			printf("Packet with strange length arrived: %zu\n", length);
-			next = curr;
-		} else if ((next < dep->de_startpage) || (next >= dep->de_stoppage)) {
-			printf("Strange next page\n");
-			next = curr;
-		} else if (header.dr_status & RSR_FO) {
-			/*
-			 * This is very serious, so we issue a warning and
-			 * reset the buffers
-			 */
-			printf("FIFO overrun, resetting receive buffer\n");
-			dep->de_stat.ets_fifoOver++;
-			next = curr;
-		} else if ((header.dr_status & RSR_PRX) && (dep->enabled)) {
-			r = dp_pkt2user(nil_phone, device_id, dep, pageno, length);
-			if (r != EOK)
-				return;
-			
-			packet_processed = true;
-			dep->de_stat.ets_packetR++;
-		}
-		
-		if (next == dep->de_startpage)
-			outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
-		else
-			outb_reg0(dep, DP_BNRY, next - 1);
-		
-		pageno = next;
-	} while (!packet_processed);
-}
-
-static void dp_nic2user(dpeth_t *dep, int nic_addr, void *buf, size_t offset, size_t size)
-{
-	size_t ecount = size & ~1;
-	
-	if (dep->de_16bit) {
-		outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
-		outb_reg0(dep, DP_RBCR1, ecount >> 8);
-	} else {
-		outb_reg0(dep, DP_RBCR0, size & 0xff);
-		outb_reg0(dep, DP_RBCR1, size >> 8);
-	}
-	
-	outb_reg0(dep, DP_RSAR0, nic_addr & 0xff);
-	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	if (dep->de_16bit) {
-		void *ptr = buf + offset;
-		
-		if (ecount != 0) {
-			insw(dep->de_data_port, ptr, ecount);
-			size -= ecount;
-			offset += ecount;
-			ptr += ecount;
-		}
-		
-		if (size) {
-			assert(size == 1);
-			
-			uint16_t two_bytes = inw(dep->de_data_port);
-			memcpy(ptr, &(((uint8_t *) &two_bytes)[0]), 1);
-		}
-	} else
-		insb(dep->de_data_port, buf + offset, size);
-}
-
-static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length)
-{
-	int last, count;
-	packet_t *packet;
-	
-	packet = netif_packet_get_1(length);
-	if (!packet)
-		return ENOMEM;
-	
-	void *buf = packet_suffix(packet, length);
-	
-	last = page + (length - 1) / DP_PAGESIZE;
-	if (last >= dep->de_stoppage) {
-		count = (dep->de_stoppage - page) * DP_PAGESIZE - sizeof(dp_rcvhdr_t);
-		
-		dp_nic2user(dep, page * DP_PAGESIZE + sizeof(dp_rcvhdr_t),
-		    buf, 0, count);
-		dp_nic2user(dep, dep->de_startpage * DP_PAGESIZE,
-		    buf, count, length - count);
-	} else {
-		dp_nic2user(dep, page * DP_PAGESIZE + sizeof(dp_rcvhdr_t),
-		    buf, 0, length);
-	}
-	
-	nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE);
-	
-	return EOK;
-}
-
-static void conf_hw(dpeth_t *dep)
-{
-	if (!ne_probe(dep)) {
-		printf("No ethernet card found at %#lx\n", dep->de_base_port);
-		dep->up = false;
-		return;
-	}
-	
-	dep->up = true;
-	dep->enabled = false;
-	dep->stopped = false;
-	dep->sending = false;
-	dep->send_avail = false;
-}
-
-static void insb(port_t port, void *buf, size_t size)
-{
-	size_t i;
-	
-	for (i = 0; i < size; i++)
-		*((uint8_t *) buf + i) = inb(port);
-}
-
-static void insw(port_t port, void *buf, size_t size)
-{
-	size_t i;
-	
-	for (i = 0; i * 2 < size; i++)
-		*((uint16_t *) buf + i) = inw(port);
-}
-
-static void outsb(port_t port, void *buf, size_t size)
-{
-	size_t i;
-	
-	for (i = 0; i < size; i++)
-		outb(port, *((uint8_t *) buf + i));
-}
-
-static void outsw(port_t port, void *buf, size_t size)
-{
-	size_t i;
-	
-	for (i = 0; i * 2 < size; i++)
-		outw(port, *((uint16_t *) buf + i));
-}
-
-/** @}
- */
Index: pace/srv/hw/netif/dp8390/dp8390.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,294 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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.
- */
-
-/*
- * This code is based upon the NE2000 driver for MINIX,
- * distributed according to a BSD-style license.
- *
- * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
- * Copyright (c) 1992, 1994 Philip Homburg
- * Copyright (c) 1996 G. Falzoni
- *
- */
-
-/** @addtogroup dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface definitions.
- */
-
-#ifndef __NET_NETIF_DP8390_H__
-#define __NET_NETIF_DP8390_H__
-
-#include <net/packet.h>
-#include "dp8390_port.h"
-
-/** Input/output size */
-#define DP8390_IO_SIZE  0x0020
-
-/* National Semiconductor DP8390 Network Interface Controller. */
-
-/** Page 0, for reading */
-#define DP_CR     0x00  /**< Command Register */
-#define DP_CLDA0  0x01  /**< Current Local DMA Address 0 */
-#define DP_CLDA1  0x02  /**< Current Local DMA Address 1 */
-#define DP_BNRY   0x03  /**< Boundary Pointer */
-#define DP_TSR    0x04  /**< Transmit Status Register */
-#define DP_NCR    0x05  /**< Number of Collisions Register */
-#define DP_FIFO   0x06  /**< FIFO */
-#define DP_ISR    0x07  /**< Interrupt Status Register */
-#define DP_CRDA0  0x08  /**< Current Remote DMA Address 0 */
-#define DP_CRDA1  0x09  /**< Current Remote DMA Address 1 */
-#define DP_RSR    0x0c  /**< Receive Status Register */
-#define DP_CNTR0  0x0d  /**< Tally Counter 0 */
-#define DP_CNTR1  0x0e  /**< Tally Counter 1 */
-#define DP_CNTR2  0x0f  /**< Tally Counter 2 */
-
-/** Page 0, for writing */
-#define DP_PSTART  0x01  /**< Page Start Register*/
-#define DP_PSTOP   0x02  /**< Page Stop Register */
-#define DP_TPSR    0x04  /**< Transmit Page Start Register */
-#define DP_TBCR0   0x05  /**< Transmit Byte Count Register 0 */
-#define DP_TBCR1   0x06  /**< Transmit Byte Count Register 1 */
-#define DP_RSAR0   0x08  /**< Remote Start Address Register 0 */
-#define DP_RSAR1   0x09  /**< Remote Start Address Register 1 */
-#define DP_RBCR0   0x0a  /**< Remote Byte Count Register 0 */
-#define DP_RBCR1   0x0b  /**< Remote Byte Count Register 1 */
-#define DP_RCR     0x0c  /**< Receive Configuration Register */
-#define DP_TCR     0x0d  /**< Transmit Configuration Register */
-#define DP_DCR     0x0e  /**< Data Configuration Register */
-#define DP_IMR     0x0f  /**< Interrupt Mask Register */
-
-/** Page 1, read/write */
-#define DP_PAR0  0x01  /**< Physical Address Register 0 */
-#define DP_PAR1  0x02  /**< Physical Address Register 1 */
-#define DP_PAR2  0x03  /**< Physical Address Register 2 */
-#define DP_PAR3  0x04  /**< Physical Address Register 3 */
-#define DP_PAR4  0x05  /**< Physical Address Register 4 */
-#define DP_PAR5  0x06  /**< Physical Address Register 5 */
-#define DP_CURR  0x07  /**< Current Page Register */
-#define DP_MAR0  0x08  /**< Multicast Address Register 0 */
-#define DP_MAR1  0x09  /**< Multicast Address Register 1 */
-#define DP_MAR2  0x0a  /**< Multicast Address Register 2 */
-#define DP_MAR3  0x0b  /**< Multicast Address Register 3 */
-#define DP_MAR4  0x0c  /**< Multicast Address Register 4 */
-#define DP_MAR5  0x0d  /**< Multicast Address Register 5 */
-#define DP_MAR6  0x0e  /**< Multicast Address Register 6 */
-#define DP_MAR7  0x0f  /**< Multicast Address Register 7 */
-
-/* Bits in dp_cr */
-#define CR_STP		0x01	/* Stop: software reset              */
-#define CR_STA		0x02	/* Start: activate NIC               */
-#define CR_TXP		0x04	/* Transmit Packet                   */
-#define CR_DMA		0x38	/* Mask for DMA control              */
-#define CR_DM_NOP	0x00	/* DMA: No Operation                 */
-#define CR_DM_RR	0x08	/* DMA: Remote Read                  */
-#define CR_DM_RW	0x10	/* DMA: Remote Write                 */
-#define CR_DM_SP	0x18	/* DMA: Send Packet                  */
-#define CR_DM_ABORT	0x20	/* DMA: Abort Remote DMA Operation   */
-#define CR_PS		0xC0	/* Mask for Page Select              */
-#define CR_PS_P0	0x00	/* Register Page 0                   */
-#define CR_PS_P1	0x40	/* Register Page 1                   */
-#define CR_PS_P2	0x80	/* Register Page 2                   */
-#define CR_PS_T1	0xC0	/* Test Mode Register Map            */
-
-/* Bits in dp_isr */
-#define ISR_PRX		0x01	/* Packet Received with no errors    */
-#define ISR_PTX		0x02	/* Packet Transmitted with no errors */
-#define ISR_RXE		0x04	/* Receive Error                     */
-#define ISR_TXE		0x08	/* Transmit Error                    */
-#define ISR_OVW		0x10	/* Overwrite Warning                 */
-#define ISR_CNT		0x20	/* Counter Overflow                  */
-#define ISR_RDC		0x40	/* Remote DMA Complete               */
-#define ISR_RST		0x80	/* Reset Status                      */
-
-/* Bits in dp_imr */
-#define IMR_PRXE	0x01	/* Packet Received iEnable           */
-#define IMR_PTXE	0x02	/* Packet Transmitted iEnable        */
-#define IMR_RXEE	0x04	/* Receive Error iEnable             */
-#define IMR_TXEE	0x08	/* Transmit Error iEnable            */
-#define IMR_OVWE	0x10	/* Overwrite Warning iEnable         */
-#define IMR_CNTE	0x20	/* Counter Overflow iEnable          */
-#define IMR_RDCE	0x40	/* DMA Complete iEnable              */
-
-/* Bits in dp_dcr */
-#define DCR_WTS		0x01	/* Word Transfer Select              */
-#define DCR_BYTEWIDE	0x00	/* WTS: byte wide transfers          */
-#define DCR_WORDWIDE	0x01	/* WTS: word wide transfers          */
-#define DCR_BOS		0x02	/* Byte Order Select                 */
-#define DCR_LTLENDIAN	0x00	/* BOS: Little Endian                */
-#define DCR_BIGENDIAN	0x02	/* BOS: Big Endian                   */
-#define DCR_LAS		0x04	/* Long Address Select               */
-#define DCR_BMS		0x08	/* Burst Mode Select
-				 * Called Loopback Select (LS) in 
-				 * later manuals. Should be set.     */
-#define DCR_AR		0x10	/* Autoinitialize Remote             */
-#define DCR_FTS		0x60	/* Fifo Threshold Select             */
-#define DCR_2BYTES	0x00	/* 2 bytes                           */
-#define DCR_4BYTES	0x40	/* 4 bytes                           */
-#define DCR_8BYTES	0x20	/* 8 bytes                           */
-#define DCR_12BYTES	0x60	/* 12 bytes                          */
-
-/* Bits in dp_tcr */
-#define TCR_CRC		0x01	/* Inhibit CRC                       */
-#define TCR_ELC		0x06	/* Encoded Loopback Control          */
-#define TCR_NORMAL	0x00	/* ELC: Normal Operation             */
-#define TCR_INTERNAL	0x02	/* ELC: Internal Loopback            */
-#define TCR_0EXTERNAL	0x04	/* ELC: External Loopback LPBK=0     */
-#define TCR_1EXTERNAL	0x06	/* ELC: External Loopback LPBK=1     */
-#define TCR_ATD		0x08	/* Auto Transmit Disable             */
-#define TCR_OFST	0x10	/* Collision Offset Enable (be nice) */
-
-/* Bits in dp_tsr */
-#define TSR_PTX		0x01	/* Packet Transmitted (without error)*/
-#define TSR_DFR		0x02	/* Transmit Deferred, reserved in
-				 * later manuals.		     */
-#define TSR_COL		0x04	/* Transmit Collided                 */
-#define TSR_ABT		0x08	/* Transmit Aborted                  */
-#define TSR_CRS		0x10	/* Carrier Sense Lost                */
-#define TSR_FU		0x20	/* FIFO Underrun                     */
-#define TSR_CDH		0x40	/* CD Heartbeat                      */
-#define TSR_OWC		0x80	/* Out of Window Collision           */
-
-/* Bits in tp_rcr */
-#define RCR_SEP		0x01	/* Save Errored Packets              */
-#define RCR_AR		0x02	/* Accept Runt Packets               */
-#define RCR_AB		0x04	/* Accept Broadcast                  */
-#define RCR_AM		0x08	/* Accept Multicast                  */
-#define RCR_PRO		0x10	/* Physical Promiscuous              */
-#define RCR_MON		0x20	/* Monitor Mode                      */
-
-/* Bits in dp_rsr */
-#define RSR_PRX		0x01	/* Packet Received Intact            */
-#define RSR_CRC		0x02	/* CRC Error                         */
-#define RSR_FAE		0x04	/* Frame Alignment Error             */
-#define RSR_FO		0x08	/* FIFO Overrun                      */
-#define RSR_MPA		0x10	/* Missed Packet                     */
-#define RSR_PHY		0x20	/* Multicast Address Match           */
-#define RSR_DIS		0x40	/* Receiver Disabled                 */
-#define RSR_DFR		0x80	/* In later manuals: Deferring       */
-
-/** Type definition of the receive header
- *
- */
-typedef struct dp_rcvhdr {
-	/** Copy of rsr */
-	uint8_t dr_status;
-	
-	/** Pointer to next packet */
-	uint8_t dr_next;
-	
-	/** Receive Byte Count Low */
-	uint8_t dr_rbcl;
-	
-	/** Receive Byte Count High */
-	uint8_t dr_rbch;
-} dp_rcvhdr_t;
-
-/** Page size */
-#define DP_PAGESIZE  256
-
-/** Read 1 byte from the zero page register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inb_reg0(dep, reg)  (inb(dep->de_dp8390_port + reg))
-
-/** Write 1 byte zero page register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outb_reg0(dep, reg, data)  (outb(dep->de_dp8390_port + reg, data))
-
-/** Read 1 byte from the first page register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inb_reg1(dep, reg)  (inb(dep->de_dp8390_port + reg))
-
-/** Write 1 byte first page register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outb_reg1(dep, reg, data)  (outb(dep->de_dp8390_port + reg, data))
-
-#define SENDQ_NR     1  /* Maximum size of the send queue */
-#define SENDQ_PAGES  6  /* 6 * DP_PAGESIZE >= 1514 bytes */
-
-typedef struct dpeth {
-	/*
-	 * The de_base_port field is the starting point of the probe.
-	 * The conf routine also fills de_irq. If the probe
-	 * routine knows the irq and/or memory address because they are
-	 * hardwired in the board, the probe should modify these fields.
-	 */
-	port_t de_base_port;
-	int de_irq;
-	
-	ether_addr_t de_address;
-	port_t de_dp8390_port;
-	port_t de_data_port;
-	int de_16bit;
-	long de_ramsize;
-	int de_offset_page;
-	int de_startpage;
-	int de_stoppage;
-	
-	/* Do it yourself send queue */
-	struct sendq {
-		int sq_filled;    /* this buffer contains a packet */
-		int sq_size;      /* with this size */
-		int sq_sendpage;  /* starting page of the buffer */
-	} de_sendq[SENDQ_NR];
-	
-	int de_sendq_nr;
-	int de_sendq_head;  /* Enqueue at the head */
-	int de_sendq_tail;  /* Dequeue at the tail */
-	
-	/* Fields for internal use by the dp8390 driver. */
-	eth_stat_t de_stat;
-	
-	/* Driver flags */
-	bool up;
-	bool enabled;
-	bool stopped;
-	bool sending;
-	bool send_avail;
-} dpeth_t;
-
-#endif
-
-/** @}
- */
Index: pace/srv/hw/netif/dp8390/dp8390_drv.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_drv.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,72 +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 dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface driver interface.
- */
-
-#ifndef __NET_NETIF_DP8390_DRIVER_H__
-#define __NET_NETIF_DP8390_DRIVER_H__
-
-#include "dp8390.h"
-
-int do_init(dpeth_t *dep);
-
-/** Stops the network interface.
- *  @param[in,out] dep The network interface structure.
- */
-void do_stop(dpeth_t *dep);
-
-/** Processes the interrupt.
- *  @param[in,out] dep The network interface structure.
- */
-void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, uint8_t isr);
-
-/** Probes and initializes the network interface.
- *  @param[in,out] dep The network interface structure.
- *  @returns EOK on success.
- *  @returns EXDEV if the network interface was not recognized.
- */
-int do_probe(dpeth_t * dep);
-
-/** Sends a packet.
- *  @param[in,out] dep The network interface structure.
- *  @param[in] packet The packet t be sent.
- *  @param[in] from_int The value indicating whether the sending is initialized from the interrupt handler.
- *  @returns
- */
-int do_pwrite(dpeth_t * dep, packet_t *packet, int from_int);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hw/netif/dp8390/dp8390_module.c
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_module.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,424 +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 dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface implementation.
- */
-
-#include <assert.h>
-#include <async.h>
-#include <ddi.h>
-#include <errno.h>
-#include <err.h>
-#include <malloc.h>
-#include <sysinfo.h>
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-#include <ipc/irc.h>
-#include <net/modules.h>
-#include <packet_client.h>
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <nil_interface.h>
-#include <netif_interface.h>
-#include <netif_local.h>
-#include "dp8390.h"
-#include "dp8390_drv.h"
-#include "dp8390_port.h"
-
-/** DP8390 module name.
- */
-#define NAME  "dp8390"
-
-/** Return the device from the interrupt call.
- *
- *  @param[in] call The interrupt call.
- *
- */
-#define IRQ_GET_DEVICE(call)  ((device_id_t) IPC_GET_IMETHOD(call))
-
-/** Return the ISR from the interrupt call.
- *
- *  @param[in] call The interrupt call.
- *
- */
-#define IRQ_GET_ISR(call)  ((int) IPC_GET_ARG2(call))
-
-static int irc_service = 0;
-static int irc_phone = -1;
-
-/** DP8390 kernel interrupt command sequence.
- */
-static irq_cmd_t dp8390_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_BTEST,
-		.value = 0x7f,
-		.srcarg = 2,
-		.dstarg = 3,
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 2,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_PIO_WRITE_A_8,
-		.addr = NULL,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-/** DP8390 kernel interrupt code.
- */
-static irq_code_t dp8390_code = {
-	sizeof(dp8390_cmds) / sizeof(irq_cmd_t),
-	dp8390_cmds
-};
-
-/** Handles the interrupt messages.
- *  This is the interrupt handler callback function.
- *  @param[in] iid The interrupt message identifier.
- *  @param[in] call The interrupt message.
- */
-static void irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	device_id_t device_id = IRQ_GET_DEVICE(*call);
-	netif_device_t *device;
-	int nil_phone;
-	dpeth_t *dep;
-	
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	
-	if (find_device(device_id, &device) == EOK) {
-		nil_phone = device->nil_phone;
-		dep = (dpeth_t *) device->specific;
-	} else
-		dep = NULL;
-	
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	if ((dep != NULL) && (dep->up)) {
-		assert(dep->enabled);
-		dp_check_ints(nil_phone, device_id, dep, IRQ_GET_ISR(*call));
-	}
-}
-
-/** Change the network interface state.
- *
- *  @param[in,out] device The network interface.
- *  @param[in]     state  The new state.
- *
- *  @return The new state.
- *
- */
-static int change_state(netif_device_t *device, device_state_t state)
-{
-	if (device->state != state) {
-		device->state = state;
-		
-		printf("%s: State changed to %s\n", NAME,
-		    (state == NETIF_ACTIVE) ? "active" : "stopped");
-		
-		return state;
-	}
-	
-	return EOK;
-}
-
-int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
-{
-	return ENOTSUP;
-}
-
-int netif_get_device_stats(device_id_t device_id, device_stats_t *stats)
-{
-	netif_device_t * device;
-	eth_stat_t * de_stat;
-	int rc;
-	
-	if (!stats)
-		return EBADMEM;
-	
-	rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	de_stat = &((dpeth_t *) device->specific)->de_stat;
-	
-	null_device_stats(stats);
-	stats->receive_errors = de_stat->ets_recvErr;
-	stats->send_errors = de_stat->ets_sendErr;
-	stats->receive_crc_errors = de_stat->ets_CRCerr;
-	stats->receive_frame_errors = de_stat->ets_frameAll;
-	stats->receive_missed_errors = de_stat->ets_missedP;
-	stats->receive_packets = de_stat->ets_packetR;
-	stats->send_packets = de_stat->ets_packetT;
-	stats->collisions = de_stat->ets_collision;
-	stats->send_aborted_errors = de_stat->ets_transAb;
-	stats->send_carrier_errors = de_stat->ets_carrSense;
-	stats->send_heartbeat_errors = de_stat->ets_CDheartbeat;
-	stats->send_window_errors = de_stat->ets_OWC;
-	
-	return EOK;
-}
-
-int netif_get_addr_message(device_id_t device_id, measured_string_t *address)
-{
-	netif_device_t *device;
-	int rc;
-	
-	if (!address)
-		return EBADMEM;
-	
-	rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	address->value = (uint8_t *) &((dpeth_t *) device->specific)->de_address;
-	address->length = sizeof(ether_addr_t);
-	return EOK;
-}
-
-int netif_probe_message(device_id_t device_id, int irq, uintptr_t io)
-{
-	netif_device_t *device;
-	dpeth_t *dep;
-	int rc;
-	
-	device = (netif_device_t *) malloc(sizeof(netif_device_t));
-	if (!device)
-		return ENOMEM;
-	
-	dep = (dpeth_t *) malloc(sizeof(dpeth_t));
-	if (!dep) {
-		free(device);
-		return ENOMEM;
-	}
-	
-	bzero(device, sizeof(netif_device_t));
-	bzero(dep, sizeof(dpeth_t));
-	device->device_id = device_id;
-	device->nil_phone = -1;
-	device->specific = (void *) dep;
-	device->state = NETIF_STOPPED;
-	dep->de_irq = irq;
-	dep->up = false;
-	
-	//TODO address?
-	rc = pio_enable((void *) io, DP8390_IO_SIZE, (void **) &dep->de_base_port);
-	if (rc != EOK) {
-		free(dep);
-		free(device);
-		return rc;
-	}
-	
-	rc = do_probe(dep);
-	if (rc != EOK) {
-		free(dep);
-		free(device);
-		return rc;
-	}
-	
-	rc = netif_device_map_add(&netif_globals.device_map, device->device_id, device);
-	if (rc != EOK) {
-		free(dep);
-		free(device);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-int netif_send_message(device_id_t device_id, packet_t *packet,
-    services_t sender)
-{
-	netif_device_t *device;
-	dpeth_t *dep;
-	packet_t *next;
-	int rc;
-	
-	rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	if (device->state != NETIF_ACTIVE) {
-		netif_pq_release(packet_get_id(packet));
-		return EFORWARD;
-	}
-	
-	dep = (dpeth_t *) device->specific;
-	
-	/* Process packet queue */
-	do {
-		next = pq_detach(packet);
-		
-		if (do_pwrite(dep, packet, false) != EBUSY)
-			netif_pq_release(packet_get_id(packet));
-		
-		packet = next;
-	} while (packet);
-	
-	return EOK;
-}
-
-int netif_start_message(netif_device_t * device)
-{
-	dpeth_t *dep;
-	int rc;
-	
-	if (device->state != NETIF_ACTIVE) {
-		dep = (dpeth_t *) device->specific;
-		dp8390_cmds[0].addr = (void *) (uintptr_t) (dep->de_dp8390_port + DP_ISR);
-		dp8390_cmds[3].addr = dp8390_cmds[0].addr;
-		
-		rc = ipc_register_irq(dep->de_irq, device->device_id, device->device_id, &dp8390_code);
-		if (rc != EOK)
-			return rc;
-		
-		rc = do_init(dep);
-		if (rc != EOK) {
-			ipc_unregister_irq(dep->de_irq, device->device_id);
-			return rc;
-		}
-		
-		rc = change_state(device, NETIF_ACTIVE);
-		
-		if (irc_service)
-			async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, dep->de_irq);
-		
-		return rc;
-	}
-	
-	return EOK;
-}
-
-int netif_stop_message(netif_device_t * device)
-{
-	dpeth_t *dep;
-	
-	if (device->state != NETIF_STOPPED) {
-		dep = (dpeth_t *) device->specific;
-		do_stop(dep);
-		ipc_unregister_irq(dep->de_irq, device->device_id);
-		return change_state(device, NETIF_STOPPED);
-	}
-	
-	return EOK;
-}
-
-int netif_initialize(void)
-{
-	sysarg_t apic;
-	sysarg_t i8259;
-	
-	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 = ipc_connect_me_to_blocking(PHONE_NS, irc_service,
-			    0, 0);
-		}
-	}
-	
-	async_set_interrupt_received(irq_handler);
-	
-	sysarg_t phonehash;
-	return ipc_connect_to_me(PHONE_NS, SERVICE_DP8390, 0, 0, &phonehash);
-}
-
-/** Default thread for new connections.
- *
- *  @param[in] iid The initial message identifier.
- *  @param[in] icall The initial message call structure.
- *
- */
-static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	ipc_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		int answer_count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &answer_count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = netif_module_message(NAME, callid, &call, &answer,
-		    &answer_count);
-		
-		/* End if said to either by the message or the processing result */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, answer_count);
-	}
-}
-
-/** Start the module.
- *
- *  @param argc The count of the command line arguments. Ignored parameter.
- *  @param argv The command line parameters. Ignored parameter.
- *
- *  @returns EOK on success.
- *  @returns Other error codes as defined for each specific module start function.
- *
- */
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return netif_module_start(netif_client_connection);
-}
-
-/** @}
- */
Index: pace/srv/hw/netif/dp8390/dp8390_port.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_port.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,146 +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 dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface types and structures ports.
- */
-
-#ifndef __NET_NETIF_DP8390_PORT_H__
-#define __NET_NETIF_DP8390_PORT_H__
-
-#include <errno.h>
-#include <mem.h>
-#include <stdio.h>
-#include <libarch/ddi.h>
-#include <sys/types.h>
-
-/** Reads 1 byte.
- *  @param[in] port The address to be read.
- *  @returns The read value.
- */
-#define inb(port)  pio_read_8((ioport8_t *) (port))
-
-/** Reads 1 word (2 bytes).
- *  @param[in] port The address to be read.
- *  @returns The read value.
- */
-#define inw(port)  pio_read_16((ioport16_t *) (port))
-
-/** Writes 1 byte.
- *  @param[in] port The address to be written.
- *  @param[in] value The value to be written.
- */
-#define outb(port, value)  pio_write_8((ioport8_t *) (port), (value))
-
-/** Writes 1 word (2 bytes).
- *  @param[in] port The address to be written.
- *  @param[in] value The value to be written.
- */
-#define outw(port, value)  pio_write_16((ioport16_t *) (port), (value))
-
-/** Type definition of a port.
- */
-typedef long port_t;
-
-/** Ethernet statistics.
- */
-typedef struct eth_stat {
-	/** Number of receive errors.
-	 */
-	unsigned long ets_recvErr;
-	/** Number of send error.
-	 */
-	unsigned long ets_sendErr;
-	/** Number of buffer overwrite warnings.
-	 */
-	unsigned long ets_OVW;
-	/** Number of crc errors of read.
-	 */
-	unsigned long ets_CRCerr;
-	/** Number of frames not alligned (number of bits % 8 != 0).
-	 */
-	unsigned long ets_frameAll;
-	/** Number of packets missed due to slow processing.
-	 */
-	unsigned long ets_missedP;
-	/** Number of packets received.
-	 */
-	unsigned long ets_packetR;
-	/** Number of packets transmitted.
-	 */
-	unsigned long ets_packetT;
-	/** Number of transmission defered (Tx was busy).
-	 */
-	unsigned long ets_transDef;
-	/** Number of collissions.
-	 */
-	unsigned long ets_collision;
-	/** Number of Tx aborted due to excess collisions.
-	 */
-	unsigned long ets_transAb;
-	/** Number of carrier sense lost.
-	 */
-	unsigned long ets_carrSense;
-	/** Number of FIFO underruns (processor too busy).
-	 */
-	unsigned long ets_fifoUnder;
-	/** Number of FIFO overruns (processor too busy).
-	 */
-	unsigned long ets_fifoOver;
-	/** Number of times unable to transmit collision sig.
-	 */
-	unsigned long ets_CDheartbeat;
-	/** Number of times out of window collision.
-	 */
-	unsigned long ets_OWC;
-} eth_stat_t;
-
-/** Minimum Ethernet packet size in bytes.
- */
-#define ETH_MIN_PACK_SIZE  60
-
-/** Maximum Ethernet packet size in bytes.
- */
-#define ETH_MAX_PACK_SIZE_TAGGED  1518
-
-/** Ethernet address type definition.
- */
-typedef struct ether_addr {
-	/** Address data.
-	 */
-	uint8_t ea_addr[6];
-} ether_addr_t;
-
-#endif
-
-/** @}
- */
Index: pace/srv/hw/netif/dp8390/ne2000.c
===================================================================
--- uspace/srv/hw/netif/dp8390/ne2000.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,299 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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.
- */
-
-/*
- * This code is based upon the NE2000 driver for MINIX,
- * distributed according to a BSD-style license.
- *
- * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
- * Copyright (c) 1992, 1994 Philip Homburg
- * Copyright (c) 1996 G. Falzoni
- *
- */
-
-/** @addtogroup ne2k
- *  @{
- */
-
-/** @file
- *  NE1000 and NE2000 network interface initialization and probe functions implementation.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include "dp8390_port.h"
-#include "dp8390.h"
-#include "ne2000.h"
-
-/** Number of bytes to transfer */
-#define N  100
-
-typedef int (*testf_t)(dpeth_t *dep, int pos, uint8_t *pat);
-
-/** Data patterns */
-uint8_t pat0[] = {0x00, 0x00, 0x00, 0x00};
-uint8_t pat1[] = {0xFF, 0xFF, 0xFF, 0xFF};
-uint8_t pat2[] = {0xA5, 0x5A, 0x69, 0x96};
-uint8_t pat3[] = {0x96, 0x69, 0x5A, 0xA5};
-
-/** Tests 8 bit NE2000 network interface.
- *  @param[in,out] dep The network interface structure.
- *  @param[in] pos The starting position.
- *  @param[in] pat The data pattern to be written.
- *  @returns True on success.
- *  @returns false otherwise.
- */
-static int test_8(dpeth_t *dep, int pos, uint8_t *pat);
-
-/** Tests 16 bit NE2000 network interface.
- *  @param[in,out] dep The network interface structure.
- *  @param[in] pos The starting position.
- *  @param[in] pat The data pattern to be written.
- *  @returns True on success.
- *  @returns false otherwise.
- */
-static int test_16(dpeth_t *dep, int pos, uint8_t *pat);
-
-int ne_probe(dpeth_t *dep)
-{
-	int byte;
-	int i;
-	int loc1, loc2;
-	testf_t f;
-	
-	dep->de_dp8390_port = dep->de_base_port + NE_DP8390;
-	
-	/*
-	 * We probe for an ne1000 or an ne2000 by testing whether the
-	 * on board is reachable through the dp8390. Note that the
-	 * ne1000 is an 8bit card and has a memory region distict from
-	 * the 16bit ne2000
-	 */
-	
-	for (dep->de_16bit = 0; dep->de_16bit < 2; dep->de_16bit++) {
-		/* Reset the ethernet card */
-		byte= inb_ne(dep, NE_RESET);
-		usleep(2000);
-		outb_ne(dep, NE_RESET, byte);
-		usleep(2000);
-		
-		/* Reset the dp8390 */
-		outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
-		for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
-			; /* Do nothing */
-		
-		/* Check if the dp8390 is really there */
-		if ((inb_reg0(dep, DP_CR) & (CR_STP | CR_DM_ABORT)) !=
-		    (CR_STP | CR_DM_ABORT))
-			return 0;
-		
-		/* Disable the receiver and init TCR and DCR. */
-		outb_reg0(dep, DP_RCR, RCR_MON);
-		outb_reg0(dep, DP_TCR, TCR_NORMAL);
-		if (dep->de_16bit) {
-			outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
-			    DCR_BMS);
-		} else {
-			outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
-			    DCR_BMS);
-		}
-		
-		if (dep->de_16bit) {
-			loc1 = NE2000_START;
-			loc2 = NE2000_START + NE2000_SIZE - 4;
-			f = test_16;
-		} else {
-			loc1 = NE1000_START;
-			loc2 = NE1000_START + NE1000_SIZE - 4;
-			f = test_8;
-		}
-		
-		if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
-		    f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
-		    f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
-		    f(dep, loc2, pat2) && f(dep, loc2, pat3)) {
-			return 1;
-		}
-	}
-	
-	return 0;
-}
-
-/** Initializes the NE2000 network interface.
- *
- *  @param[in,out] dep The network interface structure.
- *
- */
-void ne_init(dpeth_t *dep)
-{
-	int i;
-	int word, sendq_nr;
-	
-	/* Setup a transfer to get the ethernet address. */
-	if (dep->de_16bit)
-		outb_reg0(dep, DP_RBCR0, 6*2);
-	else
-		outb_reg0(dep, DP_RBCR0, 6);
-	
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, 0);
-	outb_reg0(dep, DP_RSAR1, 0);
-	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < 6; i++) {
-		if (dep->de_16bit) {
-			word = inw_ne(dep, NE_DATA);
-			dep->de_address.ea_addr[i] = word;
-		} else
-			dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
-	}
-	
-	dep->de_data_port= dep->de_base_port + NE_DATA;
-	if (dep->de_16bit) {
-		dep->de_ramsize = NE2000_SIZE;
-		dep->de_offset_page = NE2000_START / DP_PAGESIZE;
-	} else {
-		dep->de_ramsize = NE1000_SIZE;
-		dep->de_offset_page = NE1000_START / DP_PAGESIZE;
-	}
-	
-	/* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
-	sendq_nr = dep->de_ramsize / 0x2000;
-	
-	if (sendq_nr < 1)
-		sendq_nr = 1;
-	else if (sendq_nr > SENDQ_NR)
-		sendq_nr = SENDQ_NR;
-	
-	dep->de_sendq_nr = sendq_nr;
-	for (i = 0; i < sendq_nr; i++)
-		dep->de_sendq[i].sq_sendpage = dep->de_offset_page + i * SENDQ_PAGES;
-	
-	dep->de_startpage = dep->de_offset_page + i * SENDQ_PAGES;
-	dep->de_stoppage = dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
-	
-	printf("Novell NE%d000 ethernet card at I/O address "
-	    "%#lx, memory size %#lx, irq %d\n",
-	    dep->de_16bit ? 2 : 1, dep->de_base_port, dep->de_ramsize,
-	    dep->de_irq);
-}
-
-static int test_8(dpeth_t *dep, int pos, uint8_t *pat)
-{
-	uint8_t buf[4];
-	int i;
-	
-	outb_reg0(dep, DP_ISR, 0xff);
-	
-	/* Setup a transfer to put the pattern. */
-	outb_reg0(dep, DP_RBCR0, 4);
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, pos & 0xff);
-	outb_reg0(dep, DP_RSAR1, pos >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < 4; i++)
-		outb_ne(dep, NE_DATA, pat[i]);
-	
-	for (i = 0; i < N; i++) {
-		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
-			break;
-	}
-	
-	if (i == N) {
-		printf("NE1000 remote DMA test failed\n");
-		return 0;
-	}
-	
-	outb_reg0(dep, DP_RBCR0, 4);
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, pos & 0xff);
-	outb_reg0(dep, DP_RSAR1, pos >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < 4; i++)
-		buf[i] = inb_ne(dep, NE_DATA);
-	
-	return (bcmp(buf, pat, 4) == 0);
-}
-
-static int test_16(dpeth_t *dep, int pos, uint8_t *pat)
-{
-	uint8_t buf[4];
-	int i;
-	
-	outb_reg0(dep, DP_ISR, 0xff);
-	
-	/* Setup a transfer to put the pattern. */
-	outb_reg0(dep, DP_RBCR0, 4);
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, pos & 0xff);
-	outb_reg0(dep, DP_RSAR1, pos >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < 4; i += 2)
-		outw_ne(dep, NE_DATA, *(uint16_t *)(pat + i));
-	
-	for (i = 0; i < N; i++) {
-		if (inb_reg0(dep, DP_ISR) &ISR_RDC)
-			break;
-	}
-	
-	if (i == N) {
-		printf("NE2000 remote DMA test failed\n");
-		return 0;
-	}
-	
-	outb_reg0(dep, DP_RBCR0, 4);
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, pos & 0xff);
-	outb_reg0(dep, DP_RSAR1, pos >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < 4; i += 2)
-		*(uint16_t *)(buf + i) = inw_ne(dep, NE_DATA);
-	
-	return (bcmp(buf, pat, 4) == 0);
-}
-
-/** Stop the NE2000 network interface.
- *
- *  @param[in,out] dep The network interface structure.
- *
- */
-void ne_stop(dpeth_t *dep)
-{
-	/* Reset the ethernet card */
-	int byte = inb_ne(dep, NE_RESET);
-	usleep(2000);
-	outb_ne(dep, NE_RESET, byte);
-}
-
-/** @}
- */
Index: pace/srv/hw/netif/dp8390/ne2000.h
===================================================================
--- uspace/srv/hw/netif/dp8390/ne2000.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,119 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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.
- */
-
-/*
- * This code is based upon the NE2000 driver for MINIX,
- * distributed according to a BSD-style license.
- *
- * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
- * Copyright (c) 1992, 1994 Philip Homburg
- * Copyright (c) 1996 G. Falzoni
- *
- */
-
-/** @addtogroup ne2k
- *  @{
- */
-
-/** @file
- *  NE1000 and NE2000 network interface definitions.
- */
-
-#ifndef __NET_NETIF_NE2000_H__
-#define __NET_NETIF_NE2000_H__
-
-#include <libarch/ddi.h>
-#include "dp8390_port.h"
-
-/** DP8390 register offset.
- */
-#define NE_DP8390  0x00
-
-/** Data register.
- */
-#define NE_DATA  0x10
-
-/** Reset register.
- */
-#define NE_RESET  0x1f
-
-/** NE1000 data start.
- */
-#define NE1000_START  0x2000
-
-/** NE1000 data size.
- */
-#define NE1000_SIZE  0x2000
-
-/** NE2000 data start.
- */
-#define NE2000_START  0x4000
-
-/** NE2000 data size.
- */
-#define NE2000_SIZE  0x4000
-
-/** Reads 1 byte register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inb_ne(dep, reg)  (inb(dep->de_base_port + reg))
-
-/** Writes 1 byte register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outb_ne(dep, reg, data)  (outb(dep->de_base_port + reg, data))
-
-/** Reads 1 word (2 bytes) register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inw_ne(dep, reg)  (inw(dep->de_base_port + reg))
-
-/** Writes 1 word (2 bytes) register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outw_ne(dep, reg, data)  (outw(dep->de_base_port + reg, data))
-
-struct dpeth;
-
-extern int ne_probe(struct dpeth *);
-extern void ne_init(struct dpeth *);
-extern void ne_stop(struct dpeth *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/hw/netif/ne2000/Makefile
===================================================================
--- uspace/srv/hw/netif/ne2000/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/srv/hw/netif/ne2000/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,47 @@
+#
+# 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 = ../../../..
+ROOT_PATH = $(USPACE_PREFIX)/..
+LIBS = $(LIBNET_PREFIX)/libnet.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
+
+COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
+CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
+
+-include $(COMMON_MAKEFILE)
+-include $(CONFIG_MAKEFILE)
+
+BINARY = ne2000
+
+SOURCES = \
+	dp8390.c \
+	ne2000.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hw/netif/ne2000/dp8390.c
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/srv/hw/netif/ne2000/dp8390.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,653 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * 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.
+ */
+
+/*
+ * This code is based upon the NE2000 driver for MINIX,
+ * distributed according to a BSD-style license.
+ *
+ * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
+ * Copyright (c) 1992, 1994 Philip Homburg
+ * Copyright (c) 1996 G. Falzoni
+ *
+ */
+
+/** @addtogroup ne2000
+ *  @{
+ */
+
+/** @file
+ *
+ * NE2000 (based on DP8390) network interface core implementation.
+ * Only the basic NE2000 PIO (ISA) interface is supported, remote
+ * DMA is completely absent from this code for simplicity.
+ *
+ */
+
+#include <assert.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <libarch/ddi.h>
+#include <net/packet.h>
+#include <packet_client.h>
+#include "dp8390.h"
+
+/** Page size */
+#define DP_PAGE  256
+
+/** 6 * DP_PAGE >= 1514 bytes */
+#define SQ_PAGES  6
+
+/* NE2000 implementation. */
+
+/** NE2000 Data Register */
+#define NE2K_DATA  0x0010
+
+/** NE2000 Reset register */
+#define NE2K_RESET  0x001f
+
+/** NE2000 data start */
+#define NE2K_START  0x4000
+
+/** NE2000 data size */
+#define NE2K_SIZE  0x4000
+
+/** NE2000 retry count */
+#define NE2K_RETRY  0x1000
+
+/** NE2000 error messages rate limiting */
+#define NE2K_ERL  10
+
+/** Minimum Ethernet packet size in bytes */
+#define ETH_MIN_PACK_SIZE  60
+
+/** Maximum Ethernet packet size in bytes */
+#define ETH_MAX_PACK_SIZE_TAGGED  1518
+
+/** Type definition of the receive header
+ *
+ */
+typedef struct {
+	/** Copy of RSR */
+	uint8_t status;
+	
+	/** Pointer to next packet */
+	uint8_t next;
+	
+	/** Receive Byte Count Low */
+	uint8_t rbcl;
+	
+	/** Receive Byte Count High */
+	uint8_t rbch;
+} recv_header_t;
+
+/** Read a memory block word by word.
+ *
+ * @param[in]  port Source address.
+ * @param[out] buf  Destination buffer.
+ * @param[in]  size Memory block size in bytes.
+ *
+ */
+static void pio_read_buf_16(void *port, void *buf, size_t size)
+{
+	size_t i;
+	
+	for (i = 0; (i << 1) < size; i++)
+		*((uint16_t *) buf + i) = pio_read_16((ioport16_t *) (port));
+}
+
+/** Write a memory block word by word.
+ *
+ * @param[in] port Destination address.
+ * @param[in] buf  Source buffer.
+ * @param[in] size Memory block size in bytes.
+ *
+ */
+static void pio_write_buf_16(void *port, void *buf, size_t size)
+{
+	size_t i;
+	
+	for (i = 0; (i << 1) < size; i++)
+		pio_write_16((ioport16_t *) port, *((uint16_t *) buf + i));
+}
+
+static void ne2k_download(ne2k_t *ne2k, void *buf, size_t addr, size_t size)
+{
+	size_t esize = size & ~1;
+	
+	pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff);
+	pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff);
+	pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff);
+	pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff);
+	pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+	
+	if (esize != 0) {
+		pio_read_buf_16(ne2k->data_port, buf, esize);
+		size -= esize;
+		buf += esize;
+	}
+	
+	if (size) {
+		assert(size == 1);
+		
+		uint16_t word = pio_read_16(ne2k->data_port);
+		memcpy(buf, &word, 1);
+	}
+}
+
+static void ne2k_upload(ne2k_t *ne2k, void *buf, size_t addr, size_t size)
+{
+	size_t esize = size & ~1;
+	
+	pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff);
+	pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff);
+	pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff);
+	pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff);
+	pio_write_8(ne2k->port + DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+	
+	if (esize != 0) {
+		pio_write_buf_16(ne2k->data_port, buf, esize);
+		size -= esize;
+		buf += esize;
+	}
+	
+	if (size) {
+		assert(size == 1);
+		
+		uint16_t word = 0;
+		
+		memcpy(&word, buf, 1);
+		pio_write_16(ne2k->data_port, word);
+	}
+}
+
+static void ne2k_init(ne2k_t *ne2k)
+{
+	unsigned int i;
+	
+	/* Reset the ethernet card */
+	uint8_t val = pio_read_8(ne2k->port + NE2K_RESET);
+	usleep(2000);
+	pio_write_8(ne2k->port + NE2K_RESET, val);
+	usleep(2000);
+	
+	/* Reset the DP8390 */
+	pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
+	for (i = 0; i < NE2K_RETRY; i++) {
+		if (pio_read_8(ne2k->port + DP_ISR) != 0)
+			break;
+	}
+}
+
+/** Probe and initialize the network interface.
+ *
+ * @param[in,out] ne2k Network interface structure.
+ * @param[in]     port Device address.
+ * @param[in]     irq  Device interrupt vector.
+ *
+ * @return EOK on success.
+ * @return EXDEV if the network interface was not recognized.
+ *
+ */
+int ne2k_probe(ne2k_t *ne2k, void *port, int irq)
+{
+	unsigned int i;
+	
+	/* General initialization */
+	ne2k->port = port;
+	ne2k->data_port = ne2k->port + NE2K_DATA;
+	ne2k->irq = irq;
+	ne2k->probed = false;
+	ne2k->up = false;
+	
+	ne2k_init(ne2k);
+	
+	/* Check if the DP8390 is really there */
+	uint8_t val = pio_read_8(ne2k->port + DP_CR);
+	if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
+		return EXDEV;
+	
+	/* Disable the receiver and init TCR and DCR */
+	pio_write_8(ne2k->port + DP_RCR, RCR_MON);
+	pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
+	pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
+	
+	/* Setup a transfer to get the MAC address */
+	pio_write_8(ne2k->port + DP_RBCR0, ETH_ADDR << 1);
+	pio_write_8(ne2k->port + DP_RBCR1, 0);
+	pio_write_8(ne2k->port + DP_RSAR0, 0);
+	pio_write_8(ne2k->port + DP_RSAR1, 0);
+	pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+	
+	for (i = 0; i < ETH_ADDR; i++)
+		ne2k->mac[i] = pio_read_16(ne2k->data_port);
+	
+	ne2k->probed = true;
+	return EOK;
+}
+
+/** Start the network interface.
+ *
+ * @param[in,out] ne2k Network interface structure.
+ *
+ * @return EOK on success.
+ * @return EXDEV if the network interface is disabled.
+ *
+ */
+int ne2k_up(ne2k_t *ne2k)
+{
+	if (!ne2k->probed)
+		return EXDEV;
+	
+	ne2k_init(ne2k);
+	
+	/*
+	 * Setup send queue. Use the first
+	 * SQ_PAGES of NE2000 memory for the send
+	 * buffer.
+	 */
+	ne2k->sq.dirty = false;
+	ne2k->sq.page = NE2K_START / DP_PAGE;
+	fibril_mutex_initialize(&ne2k->sq_mutex);
+	fibril_condvar_initialize(&ne2k->sq_cv);
+	
+	/*
+	 * Setup receive ring buffer. Use all the rest
+	 * of the NE2000 memory (except the first SQ_PAGES
+	 * reserved for the send buffer) for the receive
+	 * ring buffer.
+	 */
+	ne2k->start_page = ne2k->sq.page + SQ_PAGES;
+	ne2k->stop_page = ne2k->sq.page + NE2K_SIZE / DP_PAGE;
+	
+	/*
+	 * Initialization of the DP8390 following the mandatory procedure
+	 * in reference manual ("DP8390D/NS32490D NIC Network Interface
+	 * Controller", National Semiconductor, July 1995, Page 29).
+	 */
+	
+	/* Step 1: */
+	pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
+	
+	/* Step 2: */
+	pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
+	
+	/* Step 3: */
+	pio_write_8(ne2k->port + DP_RBCR0, 0);
+	pio_write_8(ne2k->port + DP_RBCR1, 0);
+	
+	/* Step 4: */
+	pio_write_8(ne2k->port + DP_RCR, RCR_AB);
+	
+	/* Step 5: */
+	pio_write_8(ne2k->port + DP_TCR, TCR_INTERNAL);
+	
+	/* Step 6: */
+	pio_write_8(ne2k->port + DP_BNRY, ne2k->start_page);
+	pio_write_8(ne2k->port + DP_PSTART, ne2k->start_page);
+	pio_write_8(ne2k->port + DP_PSTOP, ne2k->stop_page);
+	
+	/* Step 7: */
+	pio_write_8(ne2k->port + DP_ISR, 0xff);
+	
+	/* Step 8: */
+	pio_write_8(ne2k->port + DP_IMR,
+	    IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
+	
+	/* Step 9: */
+	pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
+	
+	pio_write_8(ne2k->port + DP_PAR0, ne2k->mac[0]);
+	pio_write_8(ne2k->port + DP_PAR1, ne2k->mac[1]);
+	pio_write_8(ne2k->port + DP_PAR2, ne2k->mac[2]);
+	pio_write_8(ne2k->port + DP_PAR3, ne2k->mac[3]);
+	pio_write_8(ne2k->port + DP_PAR4, ne2k->mac[4]);
+	pio_write_8(ne2k->port + DP_PAR5, ne2k->mac[5]);
+	
+	pio_write_8(ne2k->port + DP_MAR0, 0xff);
+	pio_write_8(ne2k->port + DP_MAR1, 0xff);
+	pio_write_8(ne2k->port + DP_MAR2, 0xff);
+	pio_write_8(ne2k->port + DP_MAR3, 0xff);
+	pio_write_8(ne2k->port + DP_MAR4, 0xff);
+	pio_write_8(ne2k->port + DP_MAR5, 0xff);
+	pio_write_8(ne2k->port + DP_MAR6, 0xff);
+	pio_write_8(ne2k->port + DP_MAR7, 0xff);
+	
+	pio_write_8(ne2k->port + DP_CURR, ne2k->start_page + 1);
+	
+	/* Step 10: */
+	pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA);
+	
+	/* Step 11: */
+	pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
+	
+	/* Reset counters by reading */
+	pio_read_8(ne2k->port + DP_CNTR0);
+	pio_read_8(ne2k->port + DP_CNTR1);
+	pio_read_8(ne2k->port + DP_CNTR2);
+	
+	/* Finish the initialization */
+	ne2k->up = true;
+	return EOK;
+}
+
+/** Stop the network interface.
+ *
+ * @param[in,out] ne2k Network interface structure.
+ *
+ */
+void ne2k_down(ne2k_t *ne2k)
+{
+	if ((ne2k->probed) && (ne2k->up)) {
+		pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
+		ne2k_init(ne2k);
+		ne2k->up = false;
+	}
+}
+
+/** Send a frame.
+ *
+ * @param[in,out] ne2k   Network interface structure.
+ * @param[in]     packet Frame to be sent.
+ *
+ */
+void ne2k_send(ne2k_t *ne2k, packet_t *packet)
+{
+	assert(ne2k->probed);
+	assert(ne2k->up);
+	
+	fibril_mutex_lock(&ne2k->sq_mutex);
+	
+	while (ne2k->sq.dirty)
+		fibril_condvar_wait(&ne2k->sq_cv, &ne2k->sq_mutex);
+	
+	void *buf = packet_get_data(packet);
+	size_t size = packet_get_data_length(packet);
+	
+	if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) {
+		fprintf(stderr, "%s: Frame dropped (invalid size %zu bytes)\n",
+		    NAME, size);
+		return;
+	}
+	
+	/* Upload the frame to the ethernet card */
+	ne2k_upload(ne2k, buf, ne2k->sq.page * DP_PAGE, size);
+	ne2k->sq.dirty = true;
+	ne2k->sq.size = size;
+	
+	/* Initialize the transfer */
+	pio_write_8(ne2k->port + DP_TPSR, ne2k->sq.page);
+	pio_write_8(ne2k->port + DP_TBCR0, size & 0xff);
+	pio_write_8(ne2k->port + DP_TBCR1, (size >> 8) & 0xff);
+	pio_write_8(ne2k->port + DP_CR, CR_TXP | CR_STA);
+	
+	fibril_mutex_unlock(&ne2k->sq_mutex);
+}
+
+static void ne2k_reset(ne2k_t *ne2k)
+{
+	unsigned int i;
+	
+	/* Stop the chip */
+	pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
+	pio_write_8(ne2k->port + DP_RBCR0, 0);
+	pio_write_8(ne2k->port + DP_RBCR1, 0);
+	
+	for (i = 0; i < NE2K_RETRY; i++) {
+		if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0)
+			break;
+	}
+	
+	pio_write_8(ne2k->port + DP_TCR, TCR_1EXTERNAL | TCR_OFST);
+	pio_write_8(ne2k->port + DP_CR, CR_STA | CR_DM_ABORT);
+	pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
+	
+	/* Acknowledge the ISR_RDC (remote DMA) interrupt */
+	for (i = 0; i < NE2K_RETRY; i++) {
+		if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0)
+			break;
+	}
+	
+	uint8_t val = pio_read_8(ne2k->port + DP_ISR);
+	pio_write_8(ne2k->port + DP_ISR, val & ~ISR_RDC);
+	
+	/*
+	 * Reset the transmit ring. If we were transmitting a frame,
+	 * we pretend that the packet is processed. Higher layers will
+	 * retransmit if the packet wasn't actually sent.
+	 */
+	fibril_mutex_lock(&ne2k->sq_mutex);
+	ne2k->sq.dirty = false;
+	fibril_mutex_unlock(&ne2k->sq_mutex);
+}
+
+static frame_t *ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length)
+{
+	frame_t *frame = (frame_t *) malloc(sizeof(frame_t));
+	if (frame == NULL)
+		return NULL;
+	
+	link_initialize(&frame->link);
+	
+	frame->packet = netif_packet_get_1(length);
+	if (frame->packet == NULL) {
+		free(frame);
+		return NULL;
+	}
+	
+	void *buf = packet_suffix(frame->packet, length);
+	bzero(buf, length);
+	uint8_t last = page + length / DP_PAGE;
+	
+	if (last >= ne2k->stop_page) {
+		size_t left = (ne2k->stop_page - page) * DP_PAGE
+		    - sizeof(recv_header_t);
+		
+		ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
+		    left);
+		ne2k_download(ne2k, buf + left, ne2k->start_page * DP_PAGE,
+		    length - left);
+	} else
+		ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
+		    length);
+	
+	ne2k->stats.receive_packets++;
+	return frame;
+}
+
+static link_t *ne2k_receive(ne2k_t *ne2k)
+{
+	/*
+	 * Allocate memory for the list of received frames.
+	 * If the allocation fails here we still receive the
+	 * frames from the network, but they will be lost.
+	 */
+	link_t *frames = (link_t *) malloc(sizeof(link_t));
+	if (frames != NULL)
+		list_initialize(frames);
+	
+	while (true) {
+		uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1;
+		
+		if (boundary == ne2k->stop_page)
+			boundary = ne2k->start_page;
+		
+		pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_STA);
+		uint8_t current = pio_read_8(ne2k->port + DP_CURR);
+		pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA);
+		
+		if (current == boundary)
+			/* No more frames to process */
+			break;
+		
+		recv_header_t header;
+		size_t size = sizeof(header);
+		size_t offset = boundary * DP_PAGE;
+		
+		/* Get the frame header */
+		pio_write_8(ne2k->port + DP_RBCR0, size & 0xff);
+		pio_write_8(ne2k->port + DP_RBCR1, (size >> 8) & 0xff);
+		pio_write_8(ne2k->port + DP_RSAR0, offset & 0xff);
+		pio_write_8(ne2k->port + DP_RSAR1, (offset >> 8) & 0xff);
+		pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+		
+		pio_read_buf_16(ne2k->data_port, (void *) &header, size);
+		
+		size_t length =
+		    (((size_t) header.rbcl) | (((size_t) header.rbch) << 8)) - size;
+		uint8_t next = header.next;
+		
+		if ((length < ETH_MIN_PACK_SIZE)
+		    || (length > ETH_MAX_PACK_SIZE_TAGGED)) {
+			fprintf(stderr, "%s: Rant frame (%zu bytes)\n", NAME, length);
+			next = current;
+		} else if ((header.next < ne2k->start_page)
+		    || (header.next > ne2k->stop_page)) {
+			fprintf(stderr, "%s: Malformed next frame %u\n", NAME,
+			    header.next);
+			next = current;
+		} else if (header.status & RSR_FO) {
+			/*
+			 * This is very serious, so we issue a warning and
+			 * reset the buffers.
+			 */
+			fprintf(stderr, "%s: FIFO overrun\n", NAME);
+			ne2k->overruns++;
+			next = current;
+		} else if ((header.status & RSR_PRX) && (ne2k->up)) {
+			if (frames != NULL) {
+				frame_t *frame = ne2k_receive_frame(ne2k, boundary, length);
+				if (frame != NULL)
+					list_append(&frame->link, frames);
+			}
+		}
+		
+		/*
+		 * Update the boundary pointer
+		 * to the value of the page
+		 * prior to the next packet to
+		 * be processed.
+		 */
+		if (next == ne2k->start_page)
+			next = ne2k->stop_page - 1;
+		else
+			next--;
+		
+		pio_write_8(ne2k->port + DP_BNRY, next);
+	}
+	
+	return frames;
+}
+
+link_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
+{
+	/* List of received frames */
+	link_t *frames = NULL;
+	
+	if (isr & (ISR_PTX | ISR_TXE)) {
+		if (isr & ISR_TXE)
+			ne2k->stats.send_errors++;
+		else {
+			if (tsr & TSR_PTX)
+				ne2k->stats.send_packets++;
+			
+			if (tsr & TSR_COL)
+				ne2k->stats.collisions++;
+			
+			if (tsr & TSR_ABT)
+				ne2k->stats.send_aborted_errors++;
+			
+			if (tsr & TSR_CRS)
+				ne2k->stats.send_carrier_errors++;
+			
+			if (tsr & TSR_FU) {
+				ne2k->underruns++;
+				if (ne2k->underruns < NE2K_ERL)
+					fprintf(stderr, "%s: FIFO underrun\n", NAME);
+			}
+			
+			if (tsr & TSR_CDH) {
+				ne2k->stats.send_heartbeat_errors++;
+				if (ne2k->stats.send_heartbeat_errors < NE2K_ERL)
+					fprintf(stderr, "%s: CD heartbeat failure\n", NAME);
+			}
+			
+			if (tsr & TSR_OWC)
+				ne2k->stats.send_window_errors++;
+		}
+		
+		fibril_mutex_lock(&ne2k->sq_mutex);
+		
+		if (ne2k->sq.dirty) {
+			/* Prepare the buffer for next packet */
+			ne2k->sq.dirty = false;
+			ne2k->sq.size = 0;
+			
+			/* Signal a next frame to be sent */
+			fibril_condvar_broadcast(&ne2k->sq_cv);
+		} else {
+			ne2k->misses++;
+			if (ne2k->misses < NE2K_ERL)
+				fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);
+		}
+		
+		fibril_mutex_unlock(&ne2k->sq_mutex);
+	}
+	
+	if (isr & ISR_RXE)
+		ne2k->stats.receive_errors++;
+	
+	if (isr & ISR_CNT) {
+		ne2k->stats.receive_crc_errors +=
+		    pio_read_8(ne2k->port + DP_CNTR0);
+		ne2k->stats.receive_frame_errors +=
+		    pio_read_8(ne2k->port + DP_CNTR1);
+		ne2k->stats.receive_missed_errors +=
+		    pio_read_8(ne2k->port + DP_CNTR2);
+	}
+	
+	if (isr & ISR_PRX)
+		frames = ne2k_receive(ne2k);
+	
+	if (isr & ISR_RST) {
+		/*
+		 * The chip is stopped, and all arrived
+		 * frames are delivered.
+		 */
+		ne2k_reset(ne2k);
+	}
+	
+	/* Unmask interrupts to be processed in the next round */
+	pio_write_8(ne2k->port + DP_IMR,
+	    IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
+	
+	return frames;
+}
+
+/** @}
+ */
Index: uspace/srv/hw/netif/ne2000/dp8390.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/srv/hw/netif/ne2000/dp8390.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * 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.
+ */
+
+/*
+ * This code is based upon the NE2000 driver for MINIX,
+ * distributed according to a BSD-style license.
+ *
+ * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
+ * Copyright (c) 1992, 1994 Philip Homburg
+ * Copyright (c) 1996 G. Falzoni
+ *
+ */
+
+/** @addtogroup ne2000
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface definitions.
+ */
+
+#ifndef __NET_NETIF_DP8390_H__
+#define __NET_NETIF_DP8390_H__
+
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <net/packet.h>
+#include <netif_skel.h>
+
+/** Module name */
+#define NAME  "ne2000"
+
+/** Input/output size */
+#define NE2K_IO_SIZE  0x0020
+
+/** Ethernet address length */
+#define ETH_ADDR  6
+
+/* National Semiconductor DP8390 Network Interface Controller. */
+
+/** Page 0, for reading */
+#define DP_CR     0x00  /**< Command Register */
+#define DP_CLDA0  0x01  /**< Current Local DMA Address 0 */
+#define DP_CLDA1  0x02  /**< Current Local DMA Address 1 */
+#define DP_BNRY   0x03  /**< Boundary Pointer */
+#define DP_TSR    0x04  /**< Transmit Status Register */
+#define DP_NCR    0x05  /**< Number of Collisions Register */
+#define DP_FIFO   0x06  /**< FIFO */
+#define DP_ISR    0x07  /**< Interrupt Status Register */
+#define DP_CRDA0  0x08  /**< Current Remote DMA Address 0 */
+#define DP_CRDA1  0x09  /**< Current Remote DMA Address 1 */
+#define DP_RSR    0x0c  /**< Receive Status Register */
+#define DP_CNTR0  0x0d  /**< Tally Counter 0 */
+#define DP_CNTR1  0x0e  /**< Tally Counter 1 */
+#define DP_CNTR2  0x0f  /**< Tally Counter 2 */
+
+/** Page 0, for writing */
+#define DP_PSTART  0x01  /**< Page Start Register*/
+#define DP_PSTOP   0x02  /**< Page Stop Register */
+#define DP_TPSR    0x04  /**< Transmit Page Start Register */
+#define DP_TBCR0   0x05  /**< Transmit Byte Count Register 0 */
+#define DP_TBCR1   0x06  /**< Transmit Byte Count Register 1 */
+#define DP_RSAR0   0x08  /**< Remote Start Address Register 0 */
+#define DP_RSAR1   0x09  /**< Remote Start Address Register 1 */
+#define DP_RBCR0   0x0a  /**< Remote Byte Count Register 0 */
+#define DP_RBCR1   0x0b  /**< Remote Byte Count Register 1 */
+#define DP_RCR     0x0c  /**< Receive Configuration Register */
+#define DP_TCR     0x0d  /**< Transmit Configuration Register */
+#define DP_DCR     0x0e  /**< Data Configuration Register */
+#define DP_IMR     0x0f  /**< Interrupt Mask Register */
+
+/** Page 1, read/write */
+#define DP_PAR0  0x01  /**< Physical Address Register 0 */
+#define DP_PAR1  0x02  /**< Physical Address Register 1 */
+#define DP_PAR2  0x03  /**< Physical Address Register 2 */
+#define DP_PAR3  0x04  /**< Physical Address Register 3 */
+#define DP_PAR4  0x05  /**< Physical Address Register 4 */
+#define DP_PAR5  0x06  /**< Physical Address Register 5 */
+#define DP_CURR  0x07  /**< Current Page Register */
+#define DP_MAR0  0x08  /**< Multicast Address Register 0 */
+#define DP_MAR1  0x09  /**< Multicast Address Register 1 */
+#define DP_MAR2  0x0a  /**< Multicast Address Register 2 */
+#define DP_MAR3  0x0b  /**< Multicast Address Register 3 */
+#define DP_MAR4  0x0c  /**< Multicast Address Register 4 */
+#define DP_MAR5  0x0d  /**< Multicast Address Register 5 */
+#define DP_MAR6  0x0e  /**< Multicast Address Register 6 */
+#define DP_MAR7  0x0f  /**< Multicast Address Register 7 */
+
+/* Bits in Command Register */
+#define CR_STP       0x01  /**< Stop (software reset) */
+#define CR_STA       0x02  /**< Start (activate NIC) */
+#define CR_TXP       0x04  /**< Transmit Packet */
+#define CR_DMA       0x38  /**< Mask for DMA control */
+#define CR_DM_NOP    0x00  /**< DMA: No Operation */
+#define CR_DM_RR     0x08  /**< DMA: Remote Read */
+#define CR_DM_RW     0x10  /**< DMA: Remote Write */
+#define CR_DM_SP     0x18  /**< DMA: Send Packet */
+#define CR_DM_ABORT  0x20  /**< DMA: Abort Remote DMA Operation */
+#define CR_PS        0xc0  /**< Mask for Page Select */
+#define CR_PS_P0     0x00  /**< Register Page 0 */
+#define CR_PS_P1     0x40  /**< Register Page 1 */
+#define CR_PS_P2     0x80  /**< Register Page 2 */
+#define CR_PS_T1     0xc0  /**< Test Mode Register Map */
+
+/* Bits in Interrupt State Register */
+#define ISR_PRX  0x01  /**< Packet Received with no errors */
+#define ISR_PTX  0x02  /**< Packet Transmitted with no errors */
+#define ISR_RXE  0x04  /**< Receive Error */
+#define ISR_TXE  0x08  /**< Transmit Error */
+#define ISR_OVW  0x10  /**< Overwrite Warning */
+#define ISR_CNT  0x20  /**< Counter Overflow */
+#define ISR_RDC  0x40  /**< Remote DMA Complete */
+#define ISR_RST  0x80  /**< Reset Status */
+
+/* Bits in Interrupt Mask Register */
+#define IMR_PRXE  0x01  /**< Packet Received Interrupt Enable */
+#define IMR_PTXE  0x02  /**< Packet Transmitted Interrupt Enable */
+#define IMR_RXEE  0x04  /**< Receive Error Interrupt Enable */
+#define IMR_TXEE  0x08  /**< Transmit Error Interrupt Enable */
+#define IMR_OVWE  0x10  /**< Overwrite Warning Interrupt Enable */
+#define IMR_CNTE  0x20  /**< Counter Overflow Interrupt Enable */
+#define IMR_RDCE  0x40  /**< DMA Complete Interrupt Enable */
+
+/* Bits in Data Configuration Register */
+#define DCR_WTS        0x01  /**< Word Transfer Select */
+#define DCR_BYTEWIDE   0x00  /**< WTS: byte wide transfers */
+#define DCR_WORDWIDE   0x01  /**< WTS: word wide transfers */
+#define DCR_BOS        0x02  /**< Byte Order Select */
+#define DCR_LTLENDIAN  0x00  /**< BOS: Little Endian */
+#define DCR_BIGENDIAN  0x02  /**< BOS: Big Endian */
+#define DCR_LAS        0x04  /**< Long Address Select */
+#define DCR_BMS        0x08  /**< Burst Mode Select */
+#define DCR_AR         0x10  /**< Autoinitialize Remote */
+#define DCR_FTS        0x60  /**< Fifo Threshold Select */
+#define DCR_2BYTES     0x00  /**< 2 bytes */
+#define DCR_4BYTES     0x40  /**< 4 bytes */
+#define DCR_8BYTES     0x20  /**< 8 bytes */
+#define DCR_12BYTES    0x60  /**< 12 bytes */
+
+/* Bits in Transmit Configuration Register */
+#define TCR_CRC        0x01  /**< Inhibit CRC */
+#define TCR_ELC        0x06  /**< Encoded Loopback Control */
+#define TCR_NORMAL     0x00  /**< ELC: Normal Operation */
+#define TCR_INTERNAL   0x02  /**< ELC: Internal Loopback */
+#define TCR_0EXTERNAL  0x04  /**< ELC: External Loopback LPBK=0 */
+#define TCR_1EXTERNAL  0x06  /**< ELC: External Loopback LPBK=1 */
+#define TCR_ATD        0x08  /**< Auto Transmit Disable */
+#define TCR_OFST       0x10  /**< Collision Offset Enable (be nice) */
+
+/* Bits in Interrupt Status Register */
+#define TSR_PTX  0x01  /**< Packet Transmitted (without error) */
+#define TSR_DFR  0x02  /**< Transmit Deferred (reserved) */
+#define TSR_COL  0x04  /**< Transmit Collided */
+#define TSR_ABT  0x08  /**< Transmit Aborted */
+#define TSR_CRS  0x10  /**< Carrier Sense Lost */
+#define TSR_FU   0x20  /**< FIFO Underrun */
+#define TSR_CDH  0x40  /**< CD Heartbeat */
+#define TSR_OWC  0x80  /**< Out of Window Collision */
+
+/* Bits in Receive Configuration Register */
+#define RCR_SEP  0x01  /**< Save Errored Packets */
+#define RCR_AR   0x02  /**< Accept Runt Packets */
+#define RCR_AB   0x04  /**< Accept Broadcast */
+#define RCR_AM   0x08  /**< Accept Multicast */
+#define RCR_PRO  0x10  /**< Physical Promiscuous */
+#define RCR_MON  0x20  /**< Monitor Mode */
+
+/* Bits in Receive Status Register */
+#define RSR_PRX  0x01  /**< Packet Received Intact */
+#define RSR_CRC  0x02  /**< CRC Error */
+#define RSR_FAE  0x04  /**< Frame Alignment Error */
+#define RSR_FO   0x08  /**< FIFO Overrun */
+#define RSR_MPA  0x10  /**< Missed Packet */
+#define RSR_PHY  0x20  /**< Multicast Address Match */
+#define RSR_DIS  0x40  /**< Receiver Disabled */
+#define RSR_DFR  0x80  /**< In later manuals: Deferring */
+
+typedef struct {
+	/* Device configuration */
+	void *port;
+	void *data_port;
+	int irq;
+	uint8_t mac[ETH_ADDR];
+	
+	uint8_t start_page;  /**< Ring buffer start page */
+	uint8_t stop_page;   /**< Ring buffer stop page */
+	
+	/* Send queue */
+	struct {
+		bool dirty;    /**< Buffer contains a packet */
+		size_t size;   /**< Packet size */
+		uint8_t page;  /**< Starting page of the buffer */
+	} sq;
+	fibril_mutex_t sq_mutex;
+	fibril_condvar_t sq_cv;
+	
+	/* Driver run-time variables */
+	bool probed;
+	bool up;
+	
+	/* Device statistics */
+	device_stats_t stats;
+	uint64_t misses;     /**< Receive frame misses */
+	uint64_t underruns;  /**< FIFO underruns */
+	uint64_t overruns;   /**< FIFO overruns */
+} ne2k_t;
+
+typedef struct {
+	link_t link;
+	packet_t *packet;
+} frame_t;
+
+extern int ne2k_probe(ne2k_t *, void *, int);
+extern int ne2k_up(ne2k_t *);
+extern void ne2k_down(ne2k_t *);
+extern void ne2k_send(ne2k_t *, packet_t *);
+extern link_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hw/netif/ne2000/dp8390_drv.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390_drv.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/srv/hw/netif/ne2000/dp8390_drv.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,72 @@
+/*
+ * 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 dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface driver interface.
+ */
+
+#ifndef __NET_NETIF_DP8390_DRIVER_H__
+#define __NET_NETIF_DP8390_DRIVER_H__
+
+#include "dp8390.h"
+
+int do_init(dpeth_t *dep);
+
+/** Stops the network interface.
+ *  @param[in,out] dep The network interface structure.
+ */
+void do_stop(dpeth_t *dep);
+
+/** Processes the interrupt.
+ *  @param[in,out] dep The network interface structure.
+ */
+void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, uint8_t isr);
+
+/** Probes and initializes the network interface.
+ *  @param[in,out] dep The network interface structure.
+ *  @returns EOK on success.
+ *  @returns EXDEV if the network interface was not recognized.
+ */
+int do_probe(dpeth_t * dep);
+
+/** Sends a packet.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] packet The packet t be sent.
+ *  @param[in] from_int The value indicating whether the sending is initialized from the interrupt handler.
+ *  @returns
+ */
+int do_pwrite(dpeth_t * dep, packet_t *packet, int from_int);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hw/netif/ne2000/dp8390_port.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390_port.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/srv/hw/netif/ne2000/dp8390_port.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,146 @@
+/*
+ * 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 dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface types and structures ports.
+ */
+
+#ifndef __NET_NETIF_DP8390_PORT_H__
+#define __NET_NETIF_DP8390_PORT_H__
+
+#include <errno.h>
+#include <mem.h>
+#include <stdio.h>
+#include <libarch/ddi.h>
+#include <sys/types.h>
+
+/** Reads 1 byte.
+ *  @param[in] port The address to be read.
+ *  @returns The read value.
+ */
+#define inb(port)  pio_read_8((ioport8_t *) (port))
+
+/** Reads 1 word (2 bytes).
+ *  @param[in] port The address to be read.
+ *  @returns The read value.
+ */
+#define inw(port)  pio_read_16((ioport16_t *) (port))
+
+/** Writes 1 byte.
+ *  @param[in] port The address to be written.
+ *  @param[in] value The value to be written.
+ */
+#define outb(port, value)  pio_write_8((ioport8_t *) (port), (value))
+
+/** Writes 1 word (2 bytes).
+ *  @param[in] port The address to be written.
+ *  @param[in] value The value to be written.
+ */
+#define outw(port, value)  pio_write_16((ioport16_t *) (port), (value))
+
+/** Type definition of a port.
+ */
+typedef long port_t;
+
+/** Ethernet statistics.
+ */
+typedef struct eth_stat {
+	/** Number of receive errors.
+	 */
+	unsigned long ets_recvErr;
+	/** Number of send error.
+	 */
+	unsigned long ets_sendErr;
+	/** Number of buffer overwrite warnings.
+	 */
+	unsigned long ets_OVW;
+	/** Number of crc errors of read.
+	 */
+	unsigned long ets_CRCerr;
+	/** Number of frames not alligned (number of bits % 8 != 0).
+	 */
+	unsigned long ets_frameAll;
+	/** Number of packets missed due to slow processing.
+	 */
+	unsigned long ets_missedP;
+	/** Number of packets received.
+	 */
+	unsigned long ets_packetR;
+	/** Number of packets transmitted.
+	 */
+	unsigned long ets_packetT;
+	/** Number of transmission defered (Tx was busy).
+	 */
+	unsigned long ets_transDef;
+	/** Number of collissions.
+	 */
+	unsigned long ets_collision;
+	/** Number of Tx aborted due to excess collisions.
+	 */
+	unsigned long ets_transAb;
+	/** Number of carrier sense lost.
+	 */
+	unsigned long ets_carrSense;
+	/** Number of FIFO underruns (processor too busy).
+	 */
+	unsigned long ets_fifoUnder;
+	/** Number of FIFO overruns (processor too busy).
+	 */
+	unsigned long ets_fifoOver;
+	/** Number of times unable to transmit collision sig.
+	 */
+	unsigned long ets_CDheartbeat;
+	/** Number of times out of window collision.
+	 */
+	unsigned long ets_OWC;
+} eth_stat_t;
+
+/** Minimum Ethernet packet size in bytes.
+ */
+#define ETH_MIN_PACK_SIZE  60
+
+/** Maximum Ethernet packet size in bytes.
+ */
+#define ETH_MAX_PACK_SIZE_TAGGED  1518
+
+/** Ethernet address type definition.
+ */
+typedef struct ether_addr {
+	/** Address data.
+	 */
+	uint8_t ea_addr[6];
+} ether_addr_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hw/netif/ne2000/ne2000.c
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/srv/hw/netif/ne2000/ne2000.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * 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 ne2000
+ *  @{
+ */
+
+/** @file
+ *  NE2000 network interface implementation.
+ */
+
+#include <assert.h>
+#include <async.h>
+#include <ddi.h>
+#include <errno.h>
+#include <err.h>
+#include <malloc.h>
+#include <sysinfo.h>
+#include <ipc/services.h>
+#include <ipc/ns.h>
+#include <ipc/irc.h>
+#include <net/modules.h>
+#include <packet_client.h>
+#include <adt/measured_strings.h>
+#include <net/device.h>
+#include <netif_skel.h>
+#include <nil_remote.h>
+#include "dp8390.h"
+
+/** Return the device from the interrupt call.
+ *
+ *  @param[in] call The interrupt call.
+ *
+ */
+#define IRQ_GET_DEVICE(call)  ((device_id_t) IPC_GET_IMETHOD(call))
+
+/** Return the ISR from the interrupt call.
+ *
+ * @param[in] call The interrupt call.
+ *
+ */
+#define IRQ_GET_ISR(call)  ((int) IPC_GET_ARG2(call))
+
+/** Return the TSR from the interrupt call.
+ *
+ * @param[in] call The interrupt call.
+ *
+ */
+#define IRQ_GET_TSR(call)  ((int) IPC_GET_ARG3(call))
+
+static int irc_service = 0;
+static int irc_phone = -1;
+
+/** NE2000 kernel interrupt command sequence.
+ *
+ */
+static irq_cmd_t ne2k_cmds[] = {
+	{
+		/* Read Interrupt Status Register */
+		.cmd = CMD_PIO_READ_8,
+		.addr = NULL,
+		.dstarg = 2
+	},
+	{
+		/* Mask supported interrupt causes */
+		.cmd = CMD_BTEST,
+		.value = (ISR_PRX | ISR_PTX | ISR_RXE | ISR_TXE | ISR_OVW |
+		    ISR_CNT | ISR_RDC),
+		.srcarg = 2,
+		.dstarg = 3,
+	},
+	{
+		/* Predicate for accepting the interrupt */
+		.cmd = CMD_PREDICATE,
+		.value = 4,
+		.srcarg = 3
+	},
+	{
+		/*
+		 * Mask future interrupts via
+		 * Interrupt Mask Register
+		 */
+		.cmd = CMD_PIO_WRITE_8,
+		.addr = NULL,
+		.value = 0
+	},
+	{
+		/* Acknowledge the current interrupt */
+		.cmd = CMD_PIO_WRITE_A_8,
+		.addr = NULL,
+		.srcarg = 3
+	},
+	{
+		/* Read Transmit Status Register */
+		.cmd = CMD_PIO_READ_8,
+		.addr = NULL,
+		.dstarg = 3
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+/** NE2000 kernel interrupt code.
+ *
+ */
+static irq_code_t ne2k_code = {
+	sizeof(ne2k_cmds) / sizeof(irq_cmd_t),
+	ne2k_cmds
+};
+
+/** Handle the interrupt notification.
+ *
+ * This is the interrupt notification function. It is quarantied
+ * that there is only a single instance of this notification
+ * function running at one time until the return from the
+ * ne2k_interrupt() function (where the interrupts are unmasked
+ * again).
+ *
+ * @param[in] iid  Interrupt notification identifier.
+ * @param[in] call Interrupt notification.
+ *
+ */
+static void irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	device_id_t device_id = IRQ_GET_DEVICE(*call);
+	netif_device_t *device;
+	int nil_phone;
+	ne2k_t *ne2k;
+	
+	fibril_rwlock_read_lock(&netif_globals.lock);
+	
+	if (find_device(device_id, &device) == EOK) {
+		nil_phone = device->nil_phone;
+		ne2k = (ne2k_t *) device->specific;
+	} else
+		ne2k = NULL;
+	
+	fibril_rwlock_read_unlock(&netif_globals.lock);
+	
+	if (ne2k != NULL) {
+		link_t *frames =
+		    ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call));
+		
+		if (frames != NULL) {
+			while (!list_empty(frames)) {
+				frame_t *frame =
+				    list_get_instance(frames->next, frame_t, link);
+				
+				list_remove(&frame->link);
+				nil_received_msg(nil_phone, device_id, frame->packet,
+				    SERVICE_NONE);
+				free(frame);
+			}
+			
+			free(frames);
+		}
+	}
+}
+
+/** Change the network interface state.
+ *
+ * @param[in,out] device Network interface.
+ * @param[in]     state  New state.
+ *
+ */
+static void change_state(netif_device_t *device, device_state_t state)
+{
+	if (device->state != state) {
+		device->state = state;
+		
+		const char *desc;
+		switch (state) {
+		case NETIF_ACTIVE:
+			desc = "active";
+			break;
+		case NETIF_STOPPED:
+			desc = "stopped";
+			break;
+		default:
+			desc = "unknown";
+		}
+		
+		printf("%s: State changed to %s\n", NAME, desc);
+	}
+}
+
+int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, size_t *count)
+{
+	return ENOTSUP;
+}
+
+int netif_get_device_stats(device_id_t device_id, device_stats_t *stats)
+{
+	if (!stats)
+		return EBADMEM;
+	
+	netif_device_t *device;
+	int rc = find_device(device_id, &device);
+	if (rc != EOK)
+		return rc;
+	
+	ne2k_t *ne2k = (ne2k_t *) device->specific;
+	
+	memcpy(stats, &ne2k->stats, sizeof(device_stats_t));
+	return EOK;
+}
+
+int netif_get_addr_message(device_id_t device_id, measured_string_t *address)
+{
+	if (!address)
+		return EBADMEM;
+	
+	netif_device_t *device;
+	int rc = find_device(device_id, &device);
+	if (rc != EOK)
+		return rc;
+	
+	ne2k_t *ne2k = (ne2k_t *) device->specific;
+	
+	address->value = ne2k->mac;
+	address->length = ETH_ADDR;
+	return EOK;
+}
+
+int netif_probe_message(device_id_t device_id, int irq, void *io)
+{
+	netif_device_t *device =
+	    (netif_device_t *) malloc(sizeof(netif_device_t));
+	if (!device)
+		return ENOMEM;
+	
+	ne2k_t *ne2k = (ne2k_t *) malloc(sizeof(ne2k_t));
+	if (!ne2k) {
+		free(device);
+		return ENOMEM;
+	}
+	
+	void *port;
+	int rc = pio_enable((void *) io, NE2K_IO_SIZE, &port);
+	if (rc != EOK) {
+		free(ne2k);
+		free(device);
+		return rc;
+	}
+	
+	bzero(device, sizeof(netif_device_t));
+	bzero(ne2k, sizeof(ne2k_t));
+	
+	device->device_id = device_id;
+	device->nil_phone = -1;
+	device->specific = (void *) ne2k;
+	device->state = NETIF_STOPPED;
+	
+	rc = ne2k_probe(ne2k, port, irq);
+	if (rc != EOK) {
+		printf("%s: No ethernet card found at I/O address %p\n",
+		    NAME, port);
+		free(ne2k);
+		free(device);
+		return rc;
+	}
+	
+	rc = netif_device_map_add(&netif_globals.device_map, device->device_id, device);
+	if (rc != EOK) {
+		free(ne2k);
+		free(device);
+		return rc;
+	}
+	
+	printf("%s: Ethernet card at I/O address %p, IRQ %d, MAC ",
+	    NAME, port, irq);
+	
+	unsigned int i;
+	for (i = 0; i < ETH_ADDR; i++)
+		printf("%02x%c", ne2k->mac[i], i < 5 ? ':' : '\n');
+	
+	return EOK;
+}
+
+int netif_start_message(netif_device_t *device)
+{
+	if (device->state != NETIF_ACTIVE) {
+		ne2k_t *ne2k = (ne2k_t *) device->specific;
+		
+		ne2k_cmds[0].addr = ne2k->port + DP_ISR;
+		ne2k_cmds[3].addr = ne2k->port + DP_IMR;
+		ne2k_cmds[4].addr = ne2k_cmds[0].addr;
+		ne2k_cmds[5].addr = ne2k->port + DP_TSR;
+		
+		int rc = register_irq(ne2k->irq, device->device_id,
+		    device->device_id, &ne2k_code);
+		if (rc != EOK)
+			return rc;
+		
+		rc = ne2k_up(ne2k);
+		if (rc != EOK) {
+			unregister_irq(ne2k->irq, device->device_id);
+			return rc;
+		}
+		
+		change_state(device, NETIF_ACTIVE);
+		
+		if (irc_service)
+			async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq);
+	}
+	
+	return device->state;
+}
+
+int netif_stop_message(netif_device_t *device)
+{
+	if (device->state != NETIF_STOPPED) {
+		ne2k_t *ne2k = (ne2k_t *) device->specific;
+		
+		ne2k_down(ne2k);
+		unregister_irq(ne2k->irq, device->device_id);
+		change_state(device, NETIF_STOPPED);
+	}
+	
+	return device->state;
+}
+
+int netif_send_message(device_id_t device_id, packet_t *packet,
+    services_t sender)
+{
+	netif_device_t *device;
+	int rc = find_device(device_id, &device);
+	if (rc != EOK)
+		return rc;
+	
+	if (device->state != NETIF_ACTIVE) {
+		netif_pq_release(packet_get_id(packet));
+		return EFORWARD;
+	}
+	
+	ne2k_t *ne2k = (ne2k_t *) device->specific;
+	
+	/*
+	 * Process the packet queue
+	 */
+	
+	do {
+		packet_t *next = pq_detach(packet);
+		ne2k_send(ne2k, packet);
+		netif_pq_release(packet_get_id(packet));
+		packet = next;
+	} while (packet);
+	
+	return EOK;
+}
+
+int netif_initialize(void)
+{
+	sysarg_t apic;
+	sysarg_t i8259;
+	
+	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);
+	}
+	
+	async_set_interrupt_received(irq_handler);
+	
+	return async_connect_to_me(PHONE_NS, SERVICE_NE2000, 0, 0, NULL);
+}
+
+int main(int argc, char *argv[])
+{
+	/* Start the module */
+	return netif_module_start();
+}
+
+/** @}
+ */
Index: uspace/srv/hw/netif/ne2000/ne2000.h
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
+++ uspace/srv/hw/netif/ne2000/ne2000.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * 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.
+ */
+
+/*
+ * This code is based upon the NE2000 driver for MINIX,
+ * distributed according to a BSD-style license.
+ *
+ * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
+ * Copyright (c) 1992, 1994 Philip Homburg
+ * Copyright (c) 1996 G. Falzoni
+ *
+ */
+
+/** @addtogroup ne2k
+ *  @{
+ */
+
+/** @file
+ *  NE1000 and NE2000 network interface definitions.
+ */
+
+#ifndef __NET_NETIF_NE2000_H__
+#define __NET_NETIF_NE2000_H__
+
+#include <libarch/ddi.h>
+#include "dp8390_port.h"
+
+/** DP8390 register offset.
+ */
+#define NE_DP8390  0x00
+
+/** Data register.
+ */
+#define NE_DATA  0x10
+
+/** Reset register.
+ */
+#define NE_RESET  0x1f
+
+/** NE1000 data start.
+ */
+#define NE1000_START  0x2000
+
+/** NE1000 data size.
+ */
+#define NE1000_SIZE  0x2000
+
+/** NE2000 data start.
+ */
+#define NE2000_START  0x4000
+
+/** NE2000 data size.
+ */
+#define NE2000_SIZE  0x4000
+
+/** Reads 1 byte register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @returns The read value.
+ */
+#define inb_ne(dep, reg)  (inb(dep->de_base_port + reg))
+
+/** Writes 1 byte register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @param[in] data The value to be written.
+ */
+#define outb_ne(dep, reg, data)  (outb(dep->de_base_port + reg, data))
+
+/** Reads 1 word (2 bytes) register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @returns The read value.
+ */
+#define inw_ne(dep, reg)  (inw(dep->de_base_port + reg))
+
+/** Writes 1 word (2 bytes) register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @param[in] data The value to be written.
+ */
+#define outw_ne(dep, reg, data)  (outw(dep->de_base_port + reg, data))
+
+struct dpeth;
+
+extern int ne_probe(struct dpeth *);
+extern void ne_init(struct dpeth *);
+extern void ne_stop(struct dpeth *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/loader/arch/amd64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/amd64/_link.ld.in	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/loader/arch/amd64/_link.ld.in	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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,30 @@
 		_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/ia32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia32/_link.ld.in	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/loader/arch/ia32/_link.ld.in	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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;
 }
 
@@ -53,6 +55,18 @@
 	
 	. = ALIGN(0x1000);
+	_heap = .;
 	
-	_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/elf_load.c
===================================================================
--- uspace/srv/loader/elf_load.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/loader/elf_load.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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:
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/loader/main.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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/cfg/ne2k
===================================================================
--- uspace/srv/net/cfg/ne2k	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/cfg/ne2k	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -3,5 +3,5 @@
 NAME=ne2k
 
-NETIF=dp8390
+NETIF=ne2000
 NIL=eth
 IL=ip
@@ -17,8 +17,8 @@
 IP_ADDR=10.0.2.15
 IP_ROUTING=yes
-IP_NETMASK=255.255.255.240
+IP_NETMASK=255.255.255.0
 IP_BROADCAST=10.0.2.255
 IP_GATEWAY=10.0.2.2
 ARP=arp
 
-MTU=1492
+MTU=1500
Index: uspace/srv/net/il/arp/Makefile
===================================================================
--- uspace/srv/net/il/arp/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/il/arp/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -34,6 +34,5 @@
 
 SOURCES = \
-	arp.c \
-	arp_module.c
+	arp.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/il/arp/arp.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -36,36 +36,30 @@
  */
 
-#include "arp.h"
-#include "arp_header.h"
-#include "arp_oc.h"
-#include "arp_module.h"
-
 #include <async.h>
 #include <malloc.h>
 #include <mem.h>
 #include <fibril_synch.h>
+#include <assert.h>
 #include <stdio.h>
 #include <str.h>
 #include <task.h>
 #include <adt/measured_strings.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
 #include <ipc/arp.h>
 #include <ipc/il.h>
+#include <ipc/nil.h>
 #include <byteorder.h>
 #include <errno.h>
-
 #include <net/modules.h>
 #include <net/device.h>
 #include <net/packet.h>
-
-#include <nil_interface.h>
+#include <nil_remote.h>
 #include <protocol_map.h>
 #include <packet_client.h>
 #include <packet_remote.h>
-#include <il_interface.h>
-#include <il_local.h>
-
+#include <il_remote.h>
+#include <il_skel.h>
+#include "arp.h"
 
 /** ARP module name. */
@@ -73,5 +67,43 @@
 
 /** Number of microseconds to wait for an ARP reply. */
-#define ARP_TRANS_WAIT	1000000
+#define ARP_TRANS_WAIT  1000000
+
+/** @name ARP operation codes definitions */
+/*@{*/
+
+/** REQUEST operation code. */
+#define ARPOP_REQUEST  1
+
+/** REPLY operation code. */
+#define ARPOP_REPLY  2
+
+/*@}*/
+
+/** Type definition of an ARP protocol header.
+ * @see arp_header
+ */
+typedef struct arp_header arp_header_t;
+
+/** ARP protocol header. */
+struct arp_header {
+	/**
+	 * Hardware type identifier.
+	 * @see hardware.h
+	 */
+	uint16_t hardware;
+	
+	/** Protocol identifier. */
+	uint16_t protocol;
+	/** Hardware address length in bytes. */
+	uint8_t hardware_length;
+	/** Protocol address length in bytes. */
+	uint8_t protocol_length;
+	
+	/**
+	 * ARP packet type.
+	 * @see arp_oc.h
+	 */
+	uint16_t operation;
+} __attribute__ ((packed));
 
 /** ARP global data. */
@@ -88,4 +120,5 @@
 		trans->hw_addr = NULL;
 	}
+	
 	fibril_condvar_broadcast(&trans->cv);
 }
@@ -94,8 +127,8 @@
 {
 	int count;
-	arp_trans_t *trans;
-
+	
 	for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
-		trans = arp_addr_items_get_index(&addresses->values, count);
+		arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
+		    count);
 		if (trans)
 			arp_clear_trans(trans);
@@ -103,26 +136,29 @@
 }
 
-
-/** Clears the device specific data.
- *
- * @param[in] device	The device specific data.
+/** Clear the device specific data.
+ *
+ * @param[in] device Device specific data.
  */
 static void arp_clear_device(arp_device_t *device)
 {
 	int count;
-	arp_proto_t *proto;
-
+	
 	for (count = arp_protos_count(&device->protos) - 1; count >= 0;
 	    count--) {
-		proto = arp_protos_get_index(&device->protos, count);
+		arp_proto_t *proto = arp_protos_get_index(&device->protos,
+		    count);
+		
 		if (proto) {
 			if (proto->addr)
 				free(proto->addr);
+			
 			if (proto->addr_data)
 				free(proto->addr_data);
+			
 			arp_clear_addr(&proto->addresses);
 			arp_addr_destroy(&proto->addresses);
 		}
 	}
+	
 	arp_protos_clear(&device->protos);
 }
@@ -131,21 +167,24 @@
 {
 	int count;
-	arp_device_t *device;
-
+	
 	fibril_mutex_lock(&arp_globals.lock);
 	for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
 	    count--) {
-		device = arp_cache_get_index(&arp_globals.cache, count);
+		arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
+		    count);
+		
 		if (device) {
 			arp_clear_device(device);
 			if (device->addr_data)
 				free(device->addr_data);
+			
 			if (device->broadcast_data)
 				free(device->broadcast_data);
 		}
 	}
+	
 	arp_cache_clear(&arp_globals.cache);
 	fibril_mutex_unlock(&arp_globals.lock);
-	printf("Cache cleaned\n");
+	
 	return EOK;
 }
@@ -154,59 +193,60 @@
     services_t protocol, measured_string_t *address)
 {
-	arp_device_t *device;
-	arp_proto_t *proto;
-	arp_trans_t *trans;
-
 	fibril_mutex_lock(&arp_globals.lock);
-	device = arp_cache_find(&arp_globals.cache, device_id);
+	
+	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
 	if (!device) {
 		fibril_mutex_unlock(&arp_globals.lock);
 		return ENOENT;
 	}
-	proto = arp_protos_find(&device->protos, protocol);
+	
+	arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
 	if (!proto) {
 		fibril_mutex_unlock(&arp_globals.lock);
 		return ENOENT;
 	}
-	trans = arp_addr_find(&proto->addresses, address->value, address->length);
+	
+	arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
+	    address->length);
 	if (trans)
 		arp_clear_trans(trans);
+	
 	arp_addr_exclude(&proto->addresses, address->value, address->length);
+	
 	fibril_mutex_unlock(&arp_globals.lock);
 	return EOK;
 }
 
-
 static int arp_clear_device_req(int arp_phone, device_id_t device_id)
 {
-	arp_device_t *device;
-
 	fibril_mutex_lock(&arp_globals.lock);
-	device = arp_cache_find(&arp_globals.cache, device_id);
+	
+	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
 	if (!device) {
 		fibril_mutex_unlock(&arp_globals.lock);
 		return ENOENT;
 	}
+	
 	arp_clear_device(device);
-	printf("Device %d cleared\n", device_id);
+	
 	fibril_mutex_unlock(&arp_globals.lock);
 	return EOK;
 }
 
-/** Creates new protocol specific data.
- *
- * Allocates and returns the needed memory block as the proto parameter.
- *
- * @param[out] proto	The allocated protocol specific data.
- * @param[in] service	The protocol module service.
- * @param[in] address	The actual protocol device address.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
+/** Create new protocol specific data.
+ *
+ * Allocate and return the needed memory block as the proto parameter.
+ *
+ * @param[out] proto   Allocated protocol specific data.
+ * @param[in]  service Protocol module service.
+ * @param[in]  address Actual protocol device address.
+ *
+ * @return EOK on success.
+ * @return ENOMEM if there is not enough memory left.
+ *
  */
 static int arp_proto_create(arp_proto_t **proto, services_t service,
     measured_string_t *address)
 {
-	int rc;
-
 	*proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
 	if (!*proto)
@@ -217,5 +257,5 @@
 	(*proto)->addr_data = address->value;
 	
-	rc = arp_addr_initialize(&(*proto)->addresses);
+	int rc = arp_addr_initialize(&(*proto)->addresses);
 	if (rc != EOK) {
 		free(*proto);
@@ -226,245 +266,40 @@
 }
 
-/** Registers the device.
- *
- * Creates new device entry in the cache or updates the protocol address if the
- * device with the device identifier and the driver service exists.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] service	The device driver service.
- * @param[in] protocol	The protocol service.
- * @param[in] address	The actual device protocol address.
- * @return		EOK on success.
- * @return		EEXIST if another device with the same device identifier
- *			and different driver service exists.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			measured_strings_return() function.
- */
-static int arp_device_message(device_id_t device_id, services_t service,
-    services_t protocol, measured_string_t *address)
-{
-	arp_device_t *device;
-	arp_proto_t *proto;
-	hw_type_t hardware;
-	int index;
+/** Process the received ARP packet.
+ *
+ * Update the source hardware address if the source entry exists or the packet
+ * is targeted to my protocol address.
+ *
+ * Respond to the ARP request if the packet is the ARP request and is
+ * targeted to my address.
+ *
+ * @param[in]     device_id Source device identifier.
+ * @param[in,out] packet    Received packet.
+ *
+ * @return EOK on success and the packet is no longer needed.
+ * @return One on success and the packet has been reused.
+ * @return EINVAL if the packet is too small to carry an ARP
+ *         packet.
+ * @return EINVAL if the received address lengths differs from
+ *         the registered values.
+ * @return ENOENT if the device is not found in the cache.
+ * @return ENOENT if the protocol for the device is not found in
+ *         the cache.
+ * @return ENOMEM if there is not enough memory left.
+ *
+ */
+static int arp_receive_message(device_id_t device_id, packet_t *packet)
+{
 	int rc;
-
-	fibril_mutex_lock(&arp_globals.lock);
-
-	/* An existing device? */
-	device = arp_cache_find(&arp_globals.cache, device_id);
-
-	if (device) {
-		if (device->service != service) {
-			printf("Device %d already exists\n", device->device_id);
-			fibril_mutex_unlock(&arp_globals.lock);
-			return EEXIST;
-		}
-		proto = arp_protos_find(&device->protos, protocol);
-		if (proto) {
-			free(proto->addr);
-			free(proto->addr_data);
-			proto->addr = address;
-			proto->addr_data = address->value;
-		} else {
-			rc = arp_proto_create(&proto, protocol, address);
-			if (rc != EOK) {
-				fibril_mutex_unlock(&arp_globals.lock);
-				return rc;
-			}
-			index = arp_protos_add(&device->protos, proto->service,
-			    proto);
-			if (index < 0) {
-				fibril_mutex_unlock(&arp_globals.lock);
-				free(proto);
-				return index;
-			}
-			printf("New protocol added:\n\tdevice id\t= "
-			    "%d\n\tproto\t= %d", device_id, protocol);
-		}
-	} else {
-		hardware = hardware_map(service);
-		if (!hardware)
-			return ENOENT;
-		
-		/* Create a new device */
-		device = (arp_device_t *) malloc(sizeof(arp_device_t));
-		if (!device) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			return ENOMEM;
-		}
-		device->hardware = hardware;
-		device->device_id = device_id;
-		rc = arp_protos_initialize(&device->protos);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			free(device);
-			return rc;
-		}
-		rc = arp_proto_create(&proto, protocol, address);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			free(device);
-			return rc;
-		}
-		index = arp_protos_add(&device->protos, proto->service, proto);
-		if (index < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos);
-			free(device);
-			return index;
-		}
-		device->service = service;
-		
-		/* Bind the new one */
-		device->phone = nil_bind_service(device->service,
-		    (sysarg_t) device->device_id, SERVICE_ARP,
-		    arp_globals.client_connection);
-		if (device->phone < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos);
-			free(device);
-			return EREFUSED;
-		}
-		
-		/* Get packet dimensions */
-		rc = nil_packet_size_req(device->phone, device_id,
-		    &device->packet_dimension);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos);
-			free(device);
-			return rc;
-		}
-		
-		/* Get hardware address */
-		rc = nil_get_addr_req(device->phone, device_id, &device->addr,
-		    &device->addr_data);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos);
-			free(device);
-			return rc;
-		}
-		
-		/* Get broadcast address */
-		rc = nil_get_broadcast_addr_req(device->phone, device_id,
-		    &device->broadcast_addr, &device->broadcast_data);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			free(device->addr);
-			free(device->addr_data);
-			arp_protos_destroy(&device->protos);
-			free(device);
-			return rc;
-		}
-		
-		rc = arp_cache_add(&arp_globals.cache, device->device_id,
-		    device);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			free(device->addr);
-			free(device->addr_data);
-			free(device->broadcast_addr);
-			free(device->broadcast_data);
-			arp_protos_destroy(&device->protos);
-			free(device);
-			return rc;
-		}
-		printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
-		    " proto: %d)\n", NAME, device->device_id, device->hardware,
-		    device->service, protocol);
-	}
-	fibril_mutex_unlock(&arp_globals.lock);
-	
-	return EOK;
-}
-
-/** Initializes the ARP module.
- *
- *  @param[in] client_connection The client connection processing function.
- *			The module skeleton propagates its own one.
- *  @return		EOK on success.
- *  @return		ENOMEM if there is not enough memory left.
- */
-int arp_initialize(async_client_conn_t client_connection)
-{
-	int rc;
-
-	fibril_mutex_initialize(&arp_globals.lock);
-	fibril_mutex_lock(&arp_globals.lock);
-	arp_globals.client_connection = client_connection;
-	rc = arp_cache_initialize(&arp_globals.cache);
-	fibril_mutex_unlock(&arp_globals.lock);
-	
-	return rc;
-}
-
-/** Updates the device content length according to the new MTU value.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] mtu	The new mtu value.
- * @return		ENOENT if device is not found.
- * @return		EOK on success.
- */
-static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
-{
-	arp_device_t *device;
-
-	fibril_mutex_lock(&arp_globals.lock);
-	device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-	device->packet_dimension.content = mtu;
-	fibril_mutex_unlock(&arp_globals.lock);
-	printf("arp - device %d changed mtu to %zu\n\n", device_id, mtu);
-	return EOK;
-}
-
-/** Processes the received ARP packet.
- *
- * Updates the source hardware address if the source entry exists or the packet
- * is targeted to my protocol address.
- * Responses to the ARP request if the packet is the ARP request and is
- * targeted to my address.
- *
- * @param[in] device_id	The source device identifier.
- * @param[in,out] packet The received packet.
- * @return		EOK on success and the packet is no longer needed.
- * @return		One on success and the packet has been reused.
- * @return		EINVAL if the packet is too small to carry an ARP
- *			packet.
- * @return		EINVAL if the received address lengths differs from
- *			the registered values.
- * @return		ENOENT if the device is not found in the cache.
- * @return		ENOENT if the protocol for the device is not found in
- *			the cache.
- * @return		ENOMEM if there is not enough memory left.
- */
-static int arp_receive_message(device_id_t device_id, packet_t *packet)
-{
-	size_t length;
-	arp_header_t *header;
-	arp_device_t *device;
-	arp_proto_t *proto;
-	arp_trans_t *trans;
-	uint8_t *src_hw;
-	uint8_t *src_proto;
-	uint8_t *des_hw;
-	uint8_t *des_proto;
-	int rc;
-
-	length = packet_get_data_length(packet);
+	
+	size_t length = packet_get_data_length(packet);
 	if (length <= sizeof(arp_header_t))
 		return EINVAL;
-
-	device = arp_cache_find(&arp_globals.cache, device_id);
+	
+	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
 	if (!device)
 		return ENOENT;
-
-	header = (arp_header_t *) packet_get_data(packet);
+	
+	arp_header_t *header = (arp_header_t *) packet_get_data(packet);
 	if ((ntohs(header->hardware) != device->hardware) ||
 	    (length < sizeof(arp_header_t) + header->hardware_length * 2U +
@@ -472,22 +307,26 @@
 		return EINVAL;
 	}
-
-	proto = arp_protos_find(&device->protos,
+	
+	arp_proto_t *proto = arp_protos_find(&device->protos,
 	    protocol_unmap(device->service, ntohs(header->protocol)));
 	if (!proto)
 		return ENOENT;
-
-	src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
-	src_proto = src_hw + header->hardware_length;
-	des_hw = src_proto + header->protocol_length;
-	des_proto = des_hw + header->hardware_length;
-	trans = arp_addr_find(&proto->addresses, src_proto,
+	
+	uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
+	uint8_t *src_proto = src_hw + header->hardware_length;
+	uint8_t *des_hw = src_proto + header->protocol_length;
+	uint8_t *des_proto = des_hw + header->hardware_length;
+	
+	arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
 	    header->protocol_length);
-	/* Exists? */
-	if (trans && trans->hw_addr) {
+	
+	if ((trans) && (trans->hw_addr)) {
+		/* Translation exists */
 		if (trans->hw_addr->length != header->hardware_length)
 			return EINVAL;
+		
 		memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
 	}
+	
 	/* Is my protocol address? */
 	if (proto->addr->length != header->protocol_length)
@@ -495,9 +334,10 @@
 	
 	if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
-		/* Not already updated? */
 		if (!trans) {
+			/* Update the translation */
 			trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
 			if (!trans)
 				return ENOMEM;
+			
 			trans->hw_addr = NULL;
 			fibril_condvar_initialize(&trans->cv);
@@ -509,4 +349,5 @@
 			}
 		}
+		
 		if (!trans->hw_addr) {
 			trans->hw_addr = measured_string_create_bulk(src_hw,
@@ -518,4 +359,5 @@
 			fibril_condvar_broadcast(&trans->cv);
 		}
+		
 		if (ntohs(header->operation) == ARPOP_REQUEST) {
 			header->operation = htons(ARPOP_REPLY);
@@ -538,82 +380,283 @@
 		}
 	}
-
+	
 	return EOK;
 }
 
-
-/** Returns the hardware address for the given protocol address.
- *
- * Sends the ARP request packet if the hardware address is not found in the
- * cache.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] protocol	The protocol service.
- * @param[in] target	The target protocol address.
- * @param[out] translation Where the hardware address of the target is stored.
- * @return		EOK on success.
- * @return		EAGAIN if the caller should try again.
- * @return		Other error codes in case of error.
- */
-static int
-arp_translate_message(device_id_t device_id, services_t protocol,
-    measured_string_t *target, measured_string_t **translation)
-{
-	arp_device_t *device;
-	arp_proto_t *proto;
-	arp_trans_t *trans;
-	size_t length;
+/** Update the device content length according to the new MTU value.
+ *
+ * @param[in] device_id Device identifier.
+ * @param[in] mtu       New MTU value.
+ *
+ * @return ENOENT if device is not found.
+ * @return EOK on success.
+ *
+ */
+static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
+{
+	fibril_mutex_lock(&arp_globals.lock);
+	
+	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
+	if (!device) {
+		fibril_mutex_unlock(&arp_globals.lock);
+		return ENOENT;
+	}
+	
+	device->packet_dimension.content = mtu;
+	
+	fibril_mutex_unlock(&arp_globals.lock);
+	
+	printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
+	
+	return EOK;
+}
+
+/** Process IPC messages from the registered device driver modules
+ *
+ * @param[in]     iid   Message identifier.
+ * @param[in,out] icall Message parameters.
+ *
+ */
+static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
+{
 	packet_t *packet;
-	arp_header_t *header;
-	bool retry = false;
 	int rc;
-
-restart:
-	if (!target || !translation)
-		return EBADMEM;
-
-	device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device)
-		return ENOENT;
-
-	proto = arp_protos_find(&device->protos, protocol);
-	if (!proto || (proto->addr->length != target->length))
-		return ENOENT;
-
-	trans = arp_addr_find(&proto->addresses, target->value, target->length);
-	if (trans) {
-		if (trans->hw_addr) {
-			*translation = trans->hw_addr;
-			return EOK;
-		}
-		if (retry)
-			return EAGAIN;
-		rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
-		    ARP_TRANS_WAIT);
-		if (rc == ETIMEOUT)
+	
+	while (true) {
+		switch (IPC_GET_IMETHOD(*icall)) {
+		case NET_IL_DEVICE_STATE:
+			/* Do nothing - keep the cache */
+			async_answer_0(iid, (sysarg_t) EOK);
+			break;
+		
+		case NET_IL_RECEIVED:
+			rc = packet_translate_remote(arp_globals.net_phone, &packet,
+			    IPC_GET_PACKET(*icall));
+			if (rc == EOK) {
+				fibril_mutex_lock(&arp_globals.lock);
+				do {
+					packet_t *next = pq_detach(packet);
+					rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
+					if (rc != 1) {
+						pq_release_remote(arp_globals.net_phone,
+						    packet_get_id(packet));
+					}
+					
+					packet = next;
+				} while (packet);
+				fibril_mutex_unlock(&arp_globals.lock);
+			}
+			async_answer_0(iid, (sysarg_t) rc);
+			break;
+		
+		case NET_IL_MTU_CHANGED:
+			rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
+			    IPC_GET_MTU(*icall));
+			async_answer_0(iid, (sysarg_t) rc);
+			break;
+		
+		default:
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
+		}
+		
+		iid = async_get_call(icall);
+	}
+}
+
+/** Register the device.
+ *
+ * Create new device entry in the cache or update the protocol address if the
+ * device with the device identifier and the driver service exists.
+ *
+ * @param[in] device_id Device identifier.
+ * @param[in] service   Device driver service.
+ * @param[in] protocol  Protocol service.
+ * @param[in] address   Actual device protocol address.
+ *
+ * @return EOK on success.
+ * @return EEXIST if another device with the same device identifier
+ *         and different driver service exists.
+ * @return ENOMEM if there is not enough memory left.
+ * @return Other error codes as defined for the
+ *         measured_strings_return() function.
+ *
+ */
+static int arp_device_message(device_id_t device_id, services_t service,
+    services_t protocol, measured_string_t *address)
+{
+	int index;
+	int rc;
+	
+	fibril_mutex_lock(&arp_globals.lock);
+	
+	/* An existing device? */
+	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
+	if (device) {
+		if (device->service != service) {
+			printf("%s: Device %d already exists\n", NAME,
+			    device->device_id);
+			fibril_mutex_unlock(&arp_globals.lock);
+			return EEXIST;
+		}
+		
+		arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
+		if (proto) {
+			free(proto->addr);
+			free(proto->addr_data);
+			proto->addr = address;
+			proto->addr_data = address->value;
+		} else {
+			rc = arp_proto_create(&proto, protocol, address);
+			if (rc != EOK) {
+				fibril_mutex_unlock(&arp_globals.lock);
+				return rc;
+			}
+			
+			index = arp_protos_add(&device->protos, proto->service,
+			    proto);
+			if (index < 0) {
+				fibril_mutex_unlock(&arp_globals.lock);
+				free(proto);
+				return index;
+			}
+			
+			printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
+			    device_id, protocol);
+		}
+	} else {
+		hw_type_t hardware = hardware_map(service);
+		if (!hardware)
 			return ENOENT;
-		retry = true;
-		goto restart;
-	}
-	if (retry)
-		return EAGAIN;
-
+		
+		/* Create new device */
+		device = (arp_device_t *) malloc(sizeof(arp_device_t));
+		if (!device) {
+			fibril_mutex_unlock(&arp_globals.lock);
+			return ENOMEM;
+		}
+		
+		device->hardware = hardware;
+		device->device_id = device_id;
+		rc = arp_protos_initialize(&device->protos);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&arp_globals.lock);
+			free(device);
+			return rc;
+		}
+		
+		arp_proto_t *proto;
+		rc = arp_proto_create(&proto, protocol, address);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&arp_globals.lock);
+			free(device);
+			return rc;
+		}
+		
+		index = arp_protos_add(&device->protos, proto->service, proto);
+		if (index < 0) {
+			fibril_mutex_unlock(&arp_globals.lock);
+			arp_protos_destroy(&device->protos);
+			free(device);
+			return index;
+		}
+		
+		device->service = service;
+		
+		/* Bind */
+		device->phone = nil_bind_service(device->service,
+		    (sysarg_t) device->device_id, SERVICE_ARP,
+		    arp_receiver);
+		if (device->phone < 0) {
+			fibril_mutex_unlock(&arp_globals.lock);
+			arp_protos_destroy(&device->protos);
+			free(device);
+			return EREFUSED;
+		}
+		
+		/* Get packet dimensions */
+		rc = nil_packet_size_req(device->phone, device_id,
+		    &device->packet_dimension);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&arp_globals.lock);
+			arp_protos_destroy(&device->protos);
+			free(device);
+			return rc;
+		}
+		
+		/* Get hardware address */
+		rc = nil_get_addr_req(device->phone, device_id, &device->addr,
+		    &device->addr_data);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&arp_globals.lock);
+			arp_protos_destroy(&device->protos);
+			free(device);
+			return rc;
+		}
+		
+		/* Get broadcast address */
+		rc = nil_get_broadcast_addr_req(device->phone, device_id,
+		    &device->broadcast_addr, &device->broadcast_data);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&arp_globals.lock);
+			free(device->addr);
+			free(device->addr_data);
+			arp_protos_destroy(&device->protos);
+			free(device);
+			return rc;
+		}
+		
+		rc = arp_cache_add(&arp_globals.cache, device->device_id,
+		    device);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&arp_globals.lock);
+			free(device->addr);
+			free(device->addr_data);
+			free(device->broadcast_addr);
+			free(device->broadcast_data);
+			arp_protos_destroy(&device->protos);
+			free(device);
+			return rc;
+		}
+		printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
+		    " proto: %d)\n", NAME, device->device_id, device->hardware,
+		    device->service, protocol);
+	}
+	
+	fibril_mutex_unlock(&arp_globals.lock);
+	return EOK;
+}
+
+int il_initialize(int net_phone)
+{
+	fibril_mutex_initialize(&arp_globals.lock);
+	
+	fibril_mutex_lock(&arp_globals.lock);
+	arp_globals.net_phone = net_phone;
+	int rc = arp_cache_initialize(&arp_globals.cache);
+	fibril_mutex_unlock(&arp_globals.lock);
+	
+	return rc;
+}
+
+static int arp_send_request(device_id_t device_id, services_t protocol,
+    measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
+{
 	/* ARP packet content size = header + (address + translation) * 2 */
-	length = 8 + 2 * (proto->addr->length + device->addr->length);
+	size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
 	if (length > device->packet_dimension.content)
 		return ELIMIT;
-
-	packet = packet_get_4_remote(arp_globals.net_phone,
+	
+	packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
 	    device->packet_dimension.addr_len, device->packet_dimension.prefix,
 	    length, device->packet_dimension.suffix);
 	if (!packet)
 		return ENOMEM;
-
-	header = (arp_header_t *) packet_suffix(packet, length);
+	
+	arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
 	if (!header) {
 		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
 		return ENOMEM;
 	}
-
+	
 	header->hardware = htons(device->hardware);
 	header->hardware_length = (uint8_t) device->addr->length;
@@ -621,5 +664,7 @@
 	header->protocol_length = (uint8_t) proto->addr->length;
 	header->operation = htons(ARPOP_REQUEST);
+	
 	length = sizeof(arp_header_t);
+	
 	memcpy(((uint8_t *) header) + length, device->addr->value,
 	    device->addr->length);
@@ -631,6 +676,6 @@
 	length += device->addr->length;
 	memcpy(((uint8_t *) header) + length, target->value, target->length);
-
-	rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
+	
+	int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
 	    (uint8_t *) device->broadcast_addr->value, device->addr->length);
 	if (rc != EOK) {
@@ -638,12 +683,112 @@
 		return rc;
 	}
-
+	
 	nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
-
+	return EOK;
+}
+
+/** Return the hardware address for the given protocol address.
+ *
+ * Send the ARP request packet if the hardware address is not found in the
+ * cache.
+ *
+ * @param[in]  device_id   Device identifier.
+ * @param[in]  protocol    Protocol service.
+ * @param[in]  target      Target protocol address.
+ * @param[out] translation Where the hardware address of the target is stored.
+ *
+ * @return EOK on success.
+ * @return EAGAIN if the caller should try again.
+ * @return Other error codes in case of error.
+ *
+ */
+static int arp_translate_message(device_id_t device_id, services_t protocol,
+    measured_string_t *target, measured_string_t **translation)
+{
+	bool retry = false;
+	int rc;
+
+	assert(fibril_mutex_is_locked(&arp_globals.lock));
+	
+restart:
+	if ((!target) || (!translation))
+		return EBADMEM;
+	
+	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
+	if (!device)
+		return ENOENT;
+	
+	arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
+	if ((!proto) || (proto->addr->length != target->length))
+		return ENOENT;
+	
+	arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
+	    target->length);
+	if (trans) {
+		if (trans->hw_addr) {
+			/* The translation is in place. */
+			*translation = trans->hw_addr;
+			return EOK;
+		}
+		
+		if (retry) {
+			/*
+			 * We may get here as a result of being signalled for
+			 * some reason while waiting for the translation (e.g.
+			 * translation becoming available, record being removed
+			 * from the table) and then losing the race for
+			 * the arp_globals.lock with someone else who modified
+			 * the table.
+			 *
+			 * Remove the incomplete record so that it is possible
+			 * to make new ARP requests.
+			 */
+			arp_clear_trans(trans);
+			arp_addr_exclude(&proto->addresses, target->value,
+			    target->length);
+			return EAGAIN;
+		}
+		
+		/*
+		 * We are a random passer-by who merely joins an already waiting
+		 * fibril in waiting for the translation.
+		 */
+		rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
+		    ARP_TRANS_WAIT);
+		if (rc == ETIMEOUT)
+			return ENOENT;
+		
+		/*
+		 * Need to recheck because we did not hold the lock while
+		 * sleeping on the condition variable.
+		 */
+		retry = true;
+		goto restart;
+	}
+	
+	if (retry)
+		return EAGAIN;
+
+	/*
+	 * We are under the protection of arp_globals.lock, so we can afford to
+	 * first send the ARP request and then insert an incomplete ARP record.
+	 * The incomplete record is used to tell any other potential waiter
+	 * that this fibril has already sent the request and that it is waiting
+	 * for the answer. Lastly, any fibril which sees the incomplete request
+	 * can perform a timed wait on its condition variable to wait for the
+	 * ARP reply to arrive.
+	 */
+
+	rc = arp_send_request(device_id, protocol, target, device, proto);
+	if (rc != EOK)
+		return rc;
+	
 	trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
 	if (!trans)
 		return ENOMEM;
+	
 	trans->hw_addr = NULL;
 	fibril_condvar_initialize(&trans->cv);
+	
 	rc = arp_addr_add(&proto->addresses, target->value, target->length,
 	    trans);
@@ -655,36 +800,49 @@
 	rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
 	    ARP_TRANS_WAIT);
-	if (rc == ETIMEOUT)
+	if (rc == ETIMEOUT) {
+		/*
+		 * Remove the incomplete record so that it is possible to make 
+		 * new ARP requests.
+		 */
+		arp_clear_trans(trans);
+		arp_addr_exclude(&proto->addresses, target->value,
+		    target->length);
 		return ENOENT;
+	}
+	
+	/*
+	 * We need to recheck that the translation has indeed become available,
+	 * because we dropped the arp_globals.lock while sleeping on the
+	 * condition variable and someone else might have e.g. removed the
+	 * translation before we managed to lock arp_globals.lock again.
+	 */
+
 	retry = true;
 	goto restart;
 }
 
-
-/** Processes the ARP 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.
+/** Process the ARP 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.
  *
  * @see arp_interface.h
  * @see IS_NET_ARP_MESSAGE()
- */
-int
-arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
+ *
+ */
+int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
+    size_t *count)
 {
 	measured_string_t *address;
 	measured_string_t *translation;
 	uint8_t *data;
-	packet_t *packet;
-	packet_t *next;
 	int rc;
 	
-	*answer_count = 0;
+	*count = 0;
 	switch (IPC_GET_IMETHOD(*call)) {
 	case IPC_M_PHONE_HUNGUP:
@@ -696,10 +854,11 @@
 			return rc;
 		
-		rc = arp_device_message(IPC_GET_DEVICE(call),
-		    IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address);
+		rc = arp_device_message(IPC_GET_DEVICE(*call),
+		    IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
 		if (rc != EOK) {
 			free(address);
 			free(data);
 		}
+		
 		return rc;
 	
@@ -710,23 +869,26 @@
 		
 		fibril_mutex_lock(&arp_globals.lock);
-		rc = arp_translate_message(IPC_GET_DEVICE(call),
-		    IPC_GET_SERVICE(call), address, &translation);
+		rc = arp_translate_message(IPC_GET_DEVICE(*call),
+		    IPC_GET_SERVICE(*call), address, &translation);
 		free(address);
 		free(data);
+		
 		if (rc != EOK) {
 			fibril_mutex_unlock(&arp_globals.lock);
 			return rc;
 		}
+		
 		if (!translation) {
 			fibril_mutex_unlock(&arp_globals.lock);
 			return ENOENT;
 		}
+		
 		rc = measured_strings_reply(translation, 1);
 		fibril_mutex_unlock(&arp_globals.lock);
 		return rc;
-
+	
 	case NET_ARP_CLEAR_DEVICE:
-		return arp_clear_device_req(0, IPC_GET_DEVICE(call));
-
+		return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
+	
 	case NET_ARP_CLEAR_ADDRESS:
 		rc = measured_strings_receive(&address, &data, 1);
@@ -734,6 +896,6 @@
 			return rc;
 		
-		arp_clear_address_req(0, IPC_GET_DEVICE(call),
-		    IPC_GET_SERVICE(call), address);
+		arp_clear_address_req(0, IPC_GET_DEVICE(*call),
+		    IPC_GET_SERVICE(*call), address);
 		free(address);
 		free(data);
@@ -742,33 +904,4 @@
 	case NET_ARP_CLEAN_CACHE:
 		return arp_clean_cache_req(0);
-	
-	case NET_IL_DEVICE_STATE:
-		/* Do nothing - keep the cache */
-		return EOK;
-	
-	case NET_IL_RECEIVED:
-		
-		rc = packet_translate_remote(arp_globals.net_phone, &packet,
-		    IPC_GET_PACKET(call));
-		if (rc != EOK)
-			return rc;
-		
-		fibril_mutex_lock(&arp_globals.lock);
-		do {
-			next = pq_detach(packet);
-			rc = arp_receive_message(IPC_GET_DEVICE(call), packet);
-			if (rc != 1) {
-				pq_release_remote(arp_globals.net_phone,
-				    packet_get_id(packet));
-			}
-			packet = next;
-		} while (packet);
-		fibril_mutex_unlock(&arp_globals.lock);
-		
-		return EOK;
-	
-	case NET_IL_MTU_CHANGED:
-		return arp_mtu_changed_message(IPC_GET_DEVICE(call),
-		    IPC_GET_MTU(call));
 	}
 	
@@ -776,61 +909,10 @@
 }
 
-/** Default thread for new connections.
- *
- * @param[in] iid	The initial message identifier.
- * @param[in] icall	The initial message call structure.
- */
-static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	ipc_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		int answer_count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &answer_count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = il_module_message_standalone(callid, &call, &answer,
-		    &answer_count);
-		
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, answer_count);
-	}
-}
-
-/** Starts the module.
- *
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- *			start function.
- */
 int main(int argc, char *argv[])
 {
-	int rc;
-	
 	/* Start the module */
-	rc = il_module_start_standalone(il_client_connection);
-	return rc;
+	return il_module_start(SERVICE_ARP);
 }
 
 /** @}
  */
-
Index: uspace/srv/net/il/arp/arp.h
===================================================================
--- uspace/srv/net/il/arp/arp.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/il/arp/arp.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -39,8 +39,5 @@
 
 #include <fibril_synch.h>
-
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <net/packet.h>
@@ -125,10 +122,4 @@
 	arp_cache_t cache;
 	
-	/**
-	 * The client connection processing function.
-	 * The module skeleton propagates its own one.
-	 */
-	async_client_conn_t client_connection;
-	
 	/** Networking module phone. */
 	int net_phone;
Index: pace/srv/net/il/arp/arp_header.h
===================================================================
--- uspace/srv/net/il/arp/arp_header.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,73 +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 arp
- *  @{
- */
-
-/** @file
- * ARP protocol header.
- * Based on the RFC 826.
- */
-
-#ifndef NET_ARP_HEADER_H_
-#define NET_ARP_HEADER_H_
-
-#include <sys/types.h>
-
-/** Type definition of an ARP protocol header.
- * @see arp_header
- */
-typedef struct arp_header arp_header_t;
-
-/** ARP protocol header. */
-struct arp_header {
-	/**
-	 * Hardware type identifier.
-	 * @see hardware.h
-	 */
-	uint16_t hardware;
-	
-	/** Protocol identifier. */
-	uint16_t protocol;
-	/** Hardware address length in bytes. */
-	uint8_t hardware_length;
-	/** Protocol address length in bytes. */
-	uint8_t protocol_length;
-	
-	/**
-	 * ARP packet type.
-	 * @see arp_oc.h
-	 */
-	uint16_t operation;
-} __attribute__ ((packed));
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/il/arp/arp_module.c
===================================================================
--- uspace/srv/net/il/arp/arp_module.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,93 +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 arp
- *  @{
- */
-
-/** @file
- * ARP standalone module implementation.
- * Contains skeleton module functions mapping.
- * The functions are used by the module skeleton as module specific entry
- * points.
- * @see module.c
- */
-
-#include <async.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-
-#include <net/modules.h>
-#include <net_interface.h>
-#include <net/packet.h>
-#include <il_local.h>
-
-#include "arp.h"
-#include "arp_module.h"
-
-/** ARP module global data. */
-extern arp_globals_t arp_globals;
-
-int il_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
-{
-	return arp_message_standalone(callid, call, answer, answer_count);
-}
-
-int il_module_start_standalone(async_client_conn_t client_connection)
-{
-	sysarg_t phonehash;
-	int rc;
-	
-	async_set_client_connection(client_connection);
-	arp_globals.net_phone = net_connect_module();
-	
-	rc = pm_init();
-	if (rc != EOK)
-		return rc;
-	
-	rc = arp_initialize(client_connection);
-	if (rc != EOK)
-		goto out;
-	
-	rc = ipc_connect_to_me(PHONE_NS, SERVICE_ARP, 0, 0, &phonehash);
-	if (rc != EOK)
-		goto out;
-	
-	async_manager();
-
-out:
-	pm_destroy();
-	return rc;
-}
-
-/** @}
- */
Index: pace/srv/net/il/arp/arp_module.h
===================================================================
--- uspace/srv/net/il/arp/arp_module.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,51 +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 arp
- * @{
- */
-
-/** @file
- * ARP module functions.
- * The functions are used as ARP module entry points.
- */
-
-#ifndef NET_ARP_MODULE_H_
-#define NET_ARP_MODULE_H_
-
-#include <ipc/ipc.h>
-#include <async.h>
-
-extern int arp_initialize(async_client_conn_t);
-extern int arp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
-    int *);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/il/arp/arp_oc.h
===================================================================
--- uspace/srv/net/il/arp/arp_oc.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,57 +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 arp
- *  @{
- */
-
-/** @file
- * ARP operation codes according to the on-line IANA - Address Resolution
- * Protocol (ARP) Parameters
- * http://www.iana.org/assignments/arp-parameters/arp-parameters.xml
- * cited January 14 2009.
- */
-
-#ifndef NET_ARP_ARPOP_H_
-#define NET_ARP_ARPOP_H_
-
-/** @name ARP operation codes definitions */
-/*@{*/
-
-/** REQUEST operation code. */
-#define ARPOP_REQUEST	1
-
-/** REPLY operation code. */
-#define ARPOP_REPLY	2
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/il/ip/Makefile
===================================================================
--- uspace/srv/net/il/ip/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/il/ip/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -34,6 +34,5 @@
 
 SOURCES = \
-	ip.c \
-	ip_module.c
+	ip.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/il/ip/ip.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -36,7 +36,4 @@
  */
 
-#include "ip.h"
-#include "ip_module.h"
-
 #include <async.h>
 #include <errno.h>
@@ -44,5 +41,4 @@
 #include <stdio.h>
 #include <str.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -52,4 +48,5 @@
 #include <sys/types.h>
 #include <byteorder.h>
+#include "ip.h"
 
 #include <adt/measured_strings.h>
@@ -69,14 +66,14 @@
 #include <net_checksum.h>
 #include <icmp_client.h>
-#include <icmp_interface.h>
-#include <il_interface.h>
+#include <icmp_remote.h>
 #include <ip_client.h>
 #include <ip_interface.h>
 #include <ip_header.h>
 #include <net_interface.h>
-#include <nil_interface.h>
-#include <tl_interface.h>
+#include <nil_remote.h>
+#include <tl_remote.h>
 #include <packet_remote.h>
-#include <il_local.h>
+#include <il_remote.h>
+#include <il_skel.h>
 
 /** IP module name. */
@@ -122,4 +119,6 @@
 INT_MAP_IMPLEMENT(ip_protos, ip_proto_t);
 GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
+
+static void ip_receiver(ipc_callid_t, ipc_call_t *);
 
 /** Releases the packet and returns the result.
@@ -244,19 +243,12 @@
 }
 
-/** Initializes the IP module.
- *
- * @param[in] client_connection The client connection processing function. The
- *			module skeleton propagates its own one.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- */
-int ip_initialize(async_client_conn_t client_connection)
-{
-	int rc;
-
+int il_initialize(int net_phone)
+{
 	fibril_rwlock_initialize(&ip_globals.lock);
 	fibril_rwlock_write_lock(&ip_globals.lock);
 	fibril_rwlock_initialize(&ip_globals.protos_lock);
 	fibril_rwlock_initialize(&ip_globals.netifs_lock);
+	
+	ip_globals.net_phone = net_phone;
 	ip_globals.packet_counter = 0;
 	ip_globals.gateway.address.s_addr = 0;
@@ -264,7 +256,6 @@
 	ip_globals.gateway.gateway.s_addr = 0;
 	ip_globals.gateway.netif = NULL;
-	ip_globals.client_connection = client_connection;
-	
-	rc = ip_netifs_initialize(&ip_globals.netifs);
+	
+	int rc = ip_netifs_initialize(&ip_globals.netifs);
 	if (rc != EOK)
 		goto out;
@@ -431,5 +422,5 @@
 	ip_netif->phone = nil_bind_service(ip_netif->service,
 	    (sysarg_t) ip_netif->device_id, SERVICE_IP,
-	    ip_globals.client_connection);
+	    ip_receiver);
 	if (ip_netif->phone < 0) {
 		printf("Failed to contact the nil service %d\n",
@@ -477,4 +468,9 @@
 		ip_globals.gateway.gateway.s_addr = gateway.s_addr;
 		ip_globals.gateway.netif = ip_netif;
+		
+		char defgateway[INET_ADDRSTRLEN];
+		inet_ntop(AF_INET, (uint8_t *) &gateway.s_addr,
+		    defgateway, INET_ADDRSTRLEN);
+		printf("%s: Default gateway (%s)\n", NAME, defgateway);
 	}
 
@@ -482,75 +478,140 @@
 }
 
-/** Updates the device content length according to the new MTU value.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] mtu	The new mtu value.
- * @return		EOK on success.
- * @return		ENOENT if device is not found.
- */
-static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
-{
+static int ip_device_req_local(int il_phone, device_id_t device_id,
+    services_t netif)
+{
+	ip_netif_t *ip_netif;
+	ip_route_t *route;
+	int index;
+	int rc;
+
+	ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
+	if (!ip_netif)
+		return ENOMEM;
+
+	rc = ip_routes_initialize(&ip_netif->routes);
+	if (rc != EOK) {
+		free(ip_netif);
+		return rc;
+	}
+
+	ip_netif->device_id = device_id;
+	ip_netif->service = netif;
+	ip_netif->state = NETIF_STOPPED;
+
+	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
+
+	rc = ip_netif_initialize(ip_netif);
+	if (rc != EOK) {
+		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+		ip_routes_destroy(&ip_netif->routes);
+		free(ip_netif);
+		return rc;
+	}
+	if (ip_netif->arp)
+		ip_netif->arp->usage++;
+
+	// print the settings
+	printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
+	    NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
+	    ip_netif->dhcp ? "dhcp" : "static");
+	
+	// TODO ipv6 addresses
+	
+	char address[INET_ADDRSTRLEN];
+	char netmask[INET_ADDRSTRLEN];
+	char gateway[INET_ADDRSTRLEN];
+	
+	for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
+		route = ip_routes_get_index(&ip_netif->routes, index);
+		if (route) {
+			inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
+			    address, INET_ADDRSTRLEN);
+			inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
+			    netmask, INET_ADDRSTRLEN);
+			inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
+			    gateway, INET_ADDRSTRLEN);
+			printf("%s: Route %d (address: %s, netmask: %s, "
+			    "gateway: %s)\n", NAME, index, address, netmask,
+			    gateway);
+		}
+	}
+	
+	inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
+	    INET_ADDRSTRLEN);
+	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+
+	printf("%s: Broadcast (%s)\n", NAME, address);
+
+	return EOK;
+}
+
+/** Searches the network interfaces if there is a suitable route.
+ *
+ * @param[in] netif	The network interface to be searched for routes. May be
+ *			NULL.
+ * @param[in] destination The destination address.
+ * @return		The found route.
+ * @return		NULL if no route was found.
+ */
+static ip_route_t *ip_netif_find_route(ip_netif_t *netif,
+    in_addr_t destination)
+{
+	int index;
+	ip_route_t *route;
+	
+	if (!netif)
+		return NULL;
+	
+	/* Start with the first one (the direct route) */
+	for (index = 0; index < ip_routes_count(&netif->routes); index++) {
+		route = ip_routes_get_index(&netif->routes, index);
+		if ((route) &&
+		    ((route->address.s_addr & route->netmask.s_addr) ==
+		    (destination.s_addr & route->netmask.s_addr)))
+			return route;
+	}
+
+	return NULL;
+}
+
+/** Searches all network interfaces if there is a suitable route.
+ *
+ * @param[in] destination The destination address.
+ * @return		The found route.
+ * @return		NULL if no route was found.
+ */
+static ip_route_t *ip_find_route(in_addr_t destination) {
+	int index;
+	ip_route_t *route;
 	ip_netif_t *netif;
 
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-	netif = ip_netifs_find(&ip_globals.netifs, device_id);
-	if (!netif) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOENT;
-	}
-	netif->packet_dimension.content = mtu;
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-
-	printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
-
-	return EOK;
-}
-
-/** Updates the device state.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] state	The new state value.
- * @return		EOK on success.
- * @return		ENOENT if device is not found.
- */
-static int ip_device_state_message(device_id_t device_id, device_state_t state)
-{
-	ip_netif_t *netif;
-
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-	// find the device
-	netif = ip_netifs_find(&ip_globals.netifs, device_id);
-	if (!netif) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOENT;
-	}
-	netif->state = state;
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-
-	printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
-
-	return EOK;
-}
-
-
-/** Prefixes a middle fragment header based on the last fragment header to the
- * packet.
- *
- * @param[in] packet	The packet to be prefixed.
- * @param[in] last	The last header to be copied.
- * @return		The prefixed middle header.
- * @return		NULL on error.
- */
-static ip_header_t *
-ip_create_middle_header(packet_t *packet, ip_header_t *last)
-{
-	ip_header_t *middle;
-
-	middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
-	if (!middle)
-		return NULL;
-	memcpy(middle, last, IP_HEADER_LENGTH(last));
-	middle->flags |= IPFLAG_MORE_FRAGMENTS;
-	return middle;
+	// start with the last netif - the newest one
+	index = ip_netifs_count(&ip_globals.netifs) - 1;
+	while (index >= 0) {
+		netif = ip_netifs_get_index(&ip_globals.netifs, index);
+		if (netif && (netif->state == NETIF_ACTIVE)) {
+			route = ip_netif_find_route(netif, destination);
+			if (route)
+				return route;
+		}
+		index--;
+	}
+
+	return &ip_globals.gateway;
+}
+
+/** Returns the network interface's IP address.
+ *
+ * @param[in] netif	The network interface.
+ * @return		The IP address.
+ * @return		NULL if no IP address was found.
+ */
+static in_addr_t *ip_netif_address(ip_netif_t *netif)
+{
+	ip_route_t *route;
+
+	route = ip_routes_get_index(&netif->routes, 0);
+	return route ? &route->address : NULL;
 }
 
@@ -621,7 +682,6 @@
  *			function.
  */
-static int
-ip_prepare_packet(in_addr_t *source, in_addr_t dest, packet_t *packet,
-    measured_string_t *destination)
+static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,
+    packet_t *packet, measured_string_t *destination)
 {
 	size_t length;
@@ -752,6 +812,5 @@
  *			function.
  */
-static int
-ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
+static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
     ip_header_t *header, ip_header_t *new_header, size_t length,
     const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
@@ -787,4 +846,25 @@
 
 	return pq_insert_after(packet, new_packet);
+}
+
+/** Prefixes a middle fragment header based on the last fragment header to the
+ * packet.
+ *
+ * @param[in] packet	The packet to be prefixed.
+ * @param[in] last	The last header to be copied.
+ * @return		The prefixed middle header.
+ * @return		NULL on error.
+ */
+static ip_header_t *ip_create_middle_header(packet_t *packet,
+    ip_header_t *last)
+{
+	ip_header_t *middle;
+
+	middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
+	if (!middle)
+		return NULL;
+	memcpy(middle, last, IP_HEADER_LENGTH(last));
+	middle->flags |= IPFLAG_MORE_FRAGMENTS;
+	return middle;
 }
 
@@ -991,7 +1071,6 @@
  *			function.
  */
-static int
-ip_send_route(packet_t *packet, ip_netif_t *netif, ip_route_t *route,
-    in_addr_t *src, in_addr_t dest, services_t error)
+static int ip_send_route(packet_t *packet, ip_netif_t *netif,
+    ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error)
 {
 	measured_string_t destination;
@@ -1056,196 +1135,6 @@
 }
 
-/** Searches the network interfaces if there is a suitable route.
- *
- * @param[in] netif	The network interface to be searched for routes. May be
- *			NULL.
- * @param[in] destination The destination address.
- * @return		The found route.
- * @return		NULL if no route was found.
- */
-static ip_route_t *
-ip_netif_find_route(ip_netif_t *netif, in_addr_t destination)
-{
-	int index;
-	ip_route_t *route;
-
-	if (!netif)
-		return NULL;
-
-	// start with the first one - the direct route
-	for (index = 0; index < ip_routes_count(&netif->routes); index++) {
-		route = ip_routes_get_index(&netif->routes, index);
-		if (route &&
-		    ((route->address.s_addr & route->netmask.s_addr) ==
-		    (destination.s_addr & route->netmask.s_addr))) {
-			return route;
-		}
-	}
-
-	return NULL;
-}
-
-/** Searches all network interfaces if there is a suitable route.
- *
- * @param[in] destination The destination address.
- * @return		The found route.
- * @return		NULL if no route was found.
- */
-static ip_route_t *ip_find_route(in_addr_t destination) {
-	int index;
-	ip_route_t *route;
-	ip_netif_t *netif;
-
-	// start with the last netif - the newest one
-	index = ip_netifs_count(&ip_globals.netifs) - 1;
-	while (index >= 0) {
-		netif = ip_netifs_get_index(&ip_globals.netifs, index);
-		if (netif && (netif->state == NETIF_ACTIVE)) {
-			route = ip_netif_find_route(netif, destination);
-			if (route)
-				return route;
-		}
-		index--;
-	}
-
-	return &ip_globals.gateway;
-}
-
-/** Returns the network interface's IP address.
- *
- * @param[in] netif	The network interface.
- * @return		The IP address.
- * @return		NULL if no IP address was found.
- */
-static in_addr_t *ip_netif_address(ip_netif_t *netif)
-{
-	ip_route_t *route;
-
-	route = ip_routes_get_index(&netif->routes, 0);
-	return route ? &route->address : NULL;
-}
-
-/** Registers the transport layer protocol.
- *
- * The traffic of this protocol will be supplied using either the receive
- * function or IPC message.
- *
- * @param[in] protocol	The transport layer module protocol.
- * @param[in] service	The transport layer module service.
- * @param[in] phone	The transport layer module phone.
- * @param[in] received_msg The receiving function.
- * @return		EOK on success.
- * @return		EINVAL if the protocol parameter and/or the service
- *			parameter is zero.
- * @return		EINVAL if the phone parameter is not a positive number
- *			and the tl_receive_msg is NULL.
- * @return		ENOMEM if there is not enough memory left.
- */
-static int
-ip_register(int protocol, services_t service, int phone,
-    tl_received_msg_t received_msg)
-{
-	ip_proto_t *proto;
-	int index;
-
-	if (!protocol || !service || ((phone < 0) && !received_msg))
-		return EINVAL;
-
-	proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
-	if (!proto)
-		return ENOMEM;
-
-	proto->protocol = protocol;
-	proto->service = service;
-	proto->phone = phone;
-	proto->received_msg = received_msg;
-
-	fibril_rwlock_write_lock(&ip_globals.protos_lock);
-	index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
-	if (index < 0) {
-		fibril_rwlock_write_unlock(&ip_globals.protos_lock);
-		free(proto);
-		return index;
-	}
-	fibril_rwlock_write_unlock(&ip_globals.protos_lock);
-
-	printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
-	    NAME, proto->protocol, proto->phone);
-
-	return EOK;
-}
-
-static int
-ip_device_req_local(int il_phone, device_id_t device_id, services_t netif)
-{
-	ip_netif_t *ip_netif;
-	ip_route_t *route;
-	int index;
-	int rc;
-
-	ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
-	if (!ip_netif)
-		return ENOMEM;
-
-	rc = ip_routes_initialize(&ip_netif->routes);
-	if (rc != EOK) {
-		free(ip_netif);
-		return rc;
-	}
-
-	ip_netif->device_id = device_id;
-	ip_netif->service = netif;
-	ip_netif->state = NETIF_STOPPED;
-
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-
-	rc = ip_netif_initialize(ip_netif);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		ip_routes_destroy(&ip_netif->routes);
-		free(ip_netif);
-		return rc;
-	}
-	if (ip_netif->arp)
-		ip_netif->arp->usage++;
-
-	// print the settings
-	printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
-	    NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
-	    ip_netif->dhcp ? "dhcp" : "static");
-	
-	// TODO ipv6 addresses
-	
-	char address[INET_ADDRSTRLEN];
-	char netmask[INET_ADDRSTRLEN];
-	char gateway[INET_ADDRSTRLEN];
-	
-	for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
-		route = ip_routes_get_index(&ip_netif->routes, index);
-		if (route) {
-			inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
-			    address, INET_ADDRSTRLEN);
-			inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
-			    netmask, INET_ADDRSTRLEN);
-			inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
-			    gateway, INET_ADDRSTRLEN);
-			printf("%s: Route %d (address: %s, netmask: %s, "
-			    "gateway: %s)\n", NAME, index, address, netmask,
-			    gateway);
-		}
-	}
-	
-	inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
-	    INET_ADDRSTRLEN);
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-
-	printf("%s: Broadcast (%s)\n", NAME, address);
-
-	return EOK;
-}
-
-static int
-ip_send_msg_local(int il_phone, device_id_t device_id, packet_t *packet,
-    services_t sender, services_t error)
+static int ip_send_msg_local(int il_phone, device_id_t device_id,
+    packet_t *packet, services_t sender, services_t error)
 {
 	int addrlen;
@@ -1288,5 +1177,5 @@
 	if (device_id > 0) {
 		netif = ip_netifs_find(&ip_globals.netifs, device_id);
-		route = ip_netif_find_route(netif, * dest);
+		route = ip_netif_find_route(netif, *dest);
 		if (netif && !route && (ip_globals.gateway.netif == netif))
 			route = &ip_globals.gateway;
@@ -1318,5 +1207,5 @@
 		}
 	}
-
+	
 	// if the local host is the destination
 	if ((route->address.s_addr == dest->s_addr) &&
@@ -1351,4 +1240,256 @@
 }
 
+/** Updates the device state.
+ *
+ * @param[in] device_id	The device identifier.
+ * @param[in] state	The new state value.
+ * @return		EOK on success.
+ * @return		ENOENT if device is not found.
+ */
+static int ip_device_state_message(device_id_t device_id, device_state_t state)
+{
+	ip_netif_t *netif;
+
+	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
+	// find the device
+	netif = ip_netifs_find(&ip_globals.netifs, device_id);
+	if (!netif) {
+		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+		return ENOENT;
+	}
+	netif->state = state;
+	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+
+	printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
+
+	return EOK;
+}
+
+/** Returns the packet destination address from the IP header.
+ *
+ * @param[in] header	The packet IP header to be read.
+ * @return		The packet destination address.
+ */
+static in_addr_t ip_get_destination(ip_header_t *header)
+{
+	in_addr_t destination;
+
+	// TODO search set ipopt route?
+	destination.s_addr = header->destination_address;
+	return destination;
+}
+
+/** Delivers the packet to the local host.
+ *
+ * The packet is either passed to another module or released on error.
+ * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
+ * found.
+ *
+ * @param[in] device_id	The source device identifier.
+ * @param[in] packet	The packet to be delivered.
+ * @param[in] header	The first packet IP header. May be NULL.
+ * @param[in] error	The packet error service.
+ * @return		EOK on success.
+ * @return		ENOTSUP if the packet is a fragment.
+ * @return		EAFNOSUPPORT if the address family is not supported.
+ * @return		ENOENT if the target protocol is not found.
+ * @return		Other error codes as defined for the packet_set_addr()
+ *			function.
+ * @return		Other error codes as defined for the packet_trim()
+ *			function.
+ * @return		Other error codes as defined for the protocol specific
+ *			tl_received_msg() function.
+ */
+static int ip_deliver_local(device_id_t device_id, packet_t *packet,
+    ip_header_t *header, services_t error)
+{
+	ip_proto_t *proto;
+	int phone;
+	services_t service;
+	tl_received_msg_t received_msg;
+	struct sockaddr *src;
+	struct sockaddr *dest;
+	struct sockaddr_in src_in;
+	struct sockaddr_in dest_in;
+	socklen_t addrlen;
+	int rc;
+
+	if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
+	    IP_FRAGMENT_OFFSET(header)) {
+		// TODO fragmented
+		return ENOTSUP;
+	}
+	
+	switch (header->version) {
+	case IPVERSION:
+		addrlen = sizeof(src_in);
+		bzero(&src_in, addrlen);
+		src_in.sin_family = AF_INET;
+		memcpy(&dest_in, &src_in, addrlen);
+		memcpy(&src_in.sin_addr.s_addr, &header->source_address,
+		    sizeof(header->source_address));
+		memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
+		    sizeof(header->destination_address));
+		src = (struct sockaddr *) &src_in;
+		dest = (struct sockaddr *) &dest_in;
+		break;
+
+	default:
+		return ip_release_and_return(packet, EAFNOSUPPORT);
+	}
+
+	rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
+	    addrlen);
+	if (rc != EOK)
+		return ip_release_and_return(packet, rc);
+
+	// trim padding if present
+	if (!error &&
+	    (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
+		rc = packet_trim(packet, 0,
+		    packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
+		if (rc != EOK)
+			return ip_release_and_return(packet, rc);
+	}
+
+	fibril_rwlock_read_lock(&ip_globals.protos_lock);
+
+	proto = ip_protos_find(&ip_globals.protos, header->protocol);
+	if (!proto) {
+		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
+		phone = ip_prepare_icmp_and_get_phone(error, packet, header);
+		if (phone >= 0) {
+			// unreachable ICMP
+			icmp_destination_unreachable_msg(phone,
+			    ICMP_PROT_UNREACH, 0, packet);
+		}
+		return ENOENT;
+	}
+
+	if (proto->received_msg) {
+		service = proto->service;
+		received_msg = proto->received_msg;
+		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
+		rc = received_msg(device_id, packet, service, error);
+	} else {
+		rc = tl_received_msg(proto->phone, device_id, packet,
+		    proto->service, error);
+		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
+	}
+
+	return rc;
+}
+
+/** Processes the received packet.
+ *
+ * The packet is either passed to another module or released on error.
+ *
+ * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
+ * invalid.
+ * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
+ * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
+ * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
+ * another host and the routing is disabled.
+ *
+ * @param[in] device_id	The source device identifier.
+ * @param[in] packet	The received packet to be processed.
+ * @return		EOK on success.
+ * @return		EINVAL if the TTL is less than two.
+ * @return		EINVAL if the checksum is invalid.
+ * @return		EAFNOSUPPORT if the address family is not supported.
+ * @return		ENOENT if no route was found.
+ * @return		ENOENT if the packet is for another host and the routing
+ *			is disabled.
+ */
+static int ip_process_packet(device_id_t device_id, packet_t *packet)
+{
+	ip_header_t *header;
+	in_addr_t dest;
+	ip_route_t *route;
+	int phone;
+	struct sockaddr *addr;
+	struct sockaddr_in addr_in;
+	socklen_t addrlen;
+	int rc;
+	
+	header = (ip_header_t *) packet_get_data(packet);
+	if (!header)
+		return ip_release_and_return(packet, ENOMEM);
+
+	// checksum
+	if ((header->header_checksum) &&
+	    (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
+		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
+		if (phone >= 0) {
+			// checksum error ICMP
+			icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
+			    ((size_t) ((void *) &header->header_checksum)) -
+			    ((size_t) ((void *) header)), packet);
+		}
+		return EINVAL;
+	}
+
+	if (header->ttl <= 1) {
+		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
+		if (phone >= 0) {
+			// ttl exceeded ICMP
+			icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
+		}
+		return EINVAL;
+	}
+	
+	// process ipopt and get destination
+	dest = ip_get_destination(header);
+
+	// set the addrination address
+	switch (header->version) {
+	case IPVERSION:
+		addrlen = sizeof(addr_in);
+		bzero(&addr_in, addrlen);
+		addr_in.sin_family = AF_INET;
+		memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
+		addr = (struct sockaddr *) &addr_in;
+		break;
+
+	default:
+		return ip_release_and_return(packet, EAFNOSUPPORT);
+	}
+
+	rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
+	if (rc != EOK)
+		return rc;
+	
+	route = ip_find_route(dest);
+	if (!route) {
+		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
+		if (phone >= 0) {
+			// unreachable ICMP
+			icmp_destination_unreachable_msg(phone,
+			    ICMP_HOST_UNREACH, 0, packet);
+		}
+		return ENOENT;
+	}
+
+	if (route->address.s_addr == dest.s_addr) {
+		// local delivery
+		return ip_deliver_local(device_id, packet, header, 0);
+	}
+
+	if (route->netif->routing) {
+		header->ttl--;
+		return ip_send_route(packet, route->netif, route, NULL, dest,
+		    0);
+	}
+
+	phone = ip_prepare_icmp_and_get_phone(0, packet, header);
+	if (phone >= 0) {
+		// unreachable ICMP if no routing
+		icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
+		    packet);
+	}
+	
+	return ENOENT;
+}
+
 /** Returns the device packet dimensions for sending.
  *
@@ -1362,7 +1503,6 @@
  * @return		EOK on success.
  */
-static int
-ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix,
-    size_t *content, size_t *suffix)
+static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
+    size_t *prefix, size_t *content, size_t *suffix)
 {
 	ip_netif_t *netif;
@@ -1414,231 +1554,126 @@
 }
 
-/** Returns the packet destination address from the IP header.
- *
- * @param[in] header	The packet IP header to be read.
- * @return		The packet destination address.
- */
-static in_addr_t ip_get_destination(ip_header_t *header)
-{
-	in_addr_t destination;
-
-	// TODO search set ipopt route?
-	destination.s_addr = header->destination_address;
-	return destination;
-}
-
-/** Delivers the packet to the local host.
- *
- * The packet is either passed to another module or released on error.
- * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
- * found.
- *
- * @param[in] device_id	The source device identifier.
- * @param[in] packet	The packet to be delivered.
- * @param[in] header	The first packet IP header. May be NULL.
- * @param[in] error	The packet error service.
+/** Updates the device content length according to the new MTU value.
+ *
+ * @param[in] device_id	The device identifier.
+ * @param[in] mtu	The new mtu value.
  * @return		EOK on success.
- * @return		ENOTSUP if the packet is a fragment.
- * @return		EAFNOSUPPORT if the address family is not supported.
- * @return		ENOENT if the target protocol is not found.
- * @return		Other error codes as defined for the packet_set_addr()
- *			function.
- * @return		Other error codes as defined for the packet_trim()
- *			function.
- * @return		Other error codes as defined for the protocol specific
- *			tl_received_msg() function.
+ * @return		ENOENT if device is not found.
+ */
+static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
+{
+	ip_netif_t *netif;
+
+	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
+	netif = ip_netifs_find(&ip_globals.netifs, device_id);
+	if (!netif) {
+		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+		return ENOENT;
+	}
+	netif->packet_dimension.content = mtu;
+	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+
+	printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
+
+	return EOK;
+}
+
+/** Process IPC messages from the registered device driver modules
+ *
+ * @param[in]     iid   Message identifier.
+ * @param[in,out] icall Message parameters.
+ *
+ */
+static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall)
+{
+	packet_t *packet;
+	int rc;
+	
+	while (true) {
+		switch (IPC_GET_IMETHOD(*icall)) {
+		case NET_IL_DEVICE_STATE:
+			rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
+			    IPC_GET_STATE(*icall));
+			async_answer_0(iid, (sysarg_t) rc);
+			break;
+		
+		case NET_IL_RECEIVED:
+			rc = packet_translate_remote(ip_globals.net_phone, &packet,
+			    IPC_GET_PACKET(*icall));
+			if (rc == EOK) {
+				do {
+					packet_t *next = pq_detach(packet);
+					ip_process_packet(IPC_GET_DEVICE(*icall), packet);
+					packet = next;
+				} while (packet);
+			}
+			
+			async_answer_0(iid, (sysarg_t) rc);
+			break;
+		
+		case NET_IL_MTU_CHANGED:
+			rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
+			    IPC_GET_MTU(*icall));
+			async_answer_0(iid, (sysarg_t) rc);
+			break;
+		
+		default:
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
+		}
+		
+		iid = async_get_call(icall);
+	}
+}
+
+/** Registers the transport layer protocol.
+ *
+ * The traffic of this protocol will be supplied using either the receive
+ * function or IPC message.
+ *
+ * @param[in] protocol	The transport layer module protocol.
+ * @param[in] service	The transport layer module service.
+ * @param[in] phone	The transport layer module phone.
+ * @param[in] received_msg The receiving function.
+ * @return		EOK on success.
+ * @return		EINVAL if the protocol parameter and/or the service
+ *			parameter is zero.
+ * @return		EINVAL if the phone parameter is not a positive number
+ *			and the tl_receive_msg is NULL.
+ * @return		ENOMEM if there is not enough memory left.
  */
 static int
-ip_deliver_local(device_id_t device_id, packet_t *packet, ip_header_t *header,
-    services_t error)
+ip_register(int protocol, services_t service, int phone,
+    tl_received_msg_t received_msg)
 {
 	ip_proto_t *proto;
-	int phone;
-	services_t service;
-	tl_received_msg_t received_msg;
-	struct sockaddr *src;
-	struct sockaddr *dest;
-	struct sockaddr_in src_in;
-	struct sockaddr_in dest_in;
-	socklen_t addrlen;
-	int rc;
-
-	if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
-	    IP_FRAGMENT_OFFSET(header)) {
-		// TODO fragmented
-		return ENOTSUP;
-	}
-	
-	switch (header->version) {
-	case IPVERSION:
-		addrlen = sizeof(src_in);
-		bzero(&src_in, addrlen);
-		src_in.sin_family = AF_INET;
-		memcpy(&dest_in, &src_in, addrlen);
-		memcpy(&src_in.sin_addr.s_addr, &header->source_address,
-		    sizeof(header->source_address));
-		memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
-		    sizeof(header->destination_address));
-		src = (struct sockaddr *) &src_in;
-		dest = (struct sockaddr *) &dest_in;
-		break;
-
-	default:
-		return ip_release_and_return(packet, EAFNOSUPPORT);
-	}
-
-	rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
-	    addrlen);
-	if (rc != EOK)
-		return ip_release_and_return(packet, rc);
-
-	// trim padding if present
-	if (!error &&
-	    (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
-		rc = packet_trim(packet, 0,
-		    packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
-		if (rc != EOK)
-			return ip_release_and_return(packet, rc);
-	}
-
-	fibril_rwlock_read_lock(&ip_globals.protos_lock);
-
-	proto = ip_protos_find(&ip_globals.protos, header->protocol);
-	if (!proto) {
-		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-		phone = ip_prepare_icmp_and_get_phone(error, packet, header);
-		if (phone >= 0) {
-			// unreachable ICMP
-			icmp_destination_unreachable_msg(phone,
-			    ICMP_PROT_UNREACH, 0, packet);
-		}
-		return ENOENT;
-	}
-
-	if (proto->received_msg) {
-		service = proto->service;
-		received_msg = proto->received_msg;
-		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-		rc = received_msg(device_id, packet, service, error);
-	} else {
-		rc = tl_received_msg(proto->phone, device_id, packet,
-		    proto->service, error);
-		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-	}
-
-	return rc;
-}
-
-/** Processes the received packet.
- *
- * The packet is either passed to another module or released on error.
- *
- * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
- * invalid.
- * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
- * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
- * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
- * another host and the routing is disabled.
- *
- * @param[in] device_id	The source device identifier.
- * @param[in] packet	The received packet to be processed.
- * @return		EOK on success.
- * @return		EINVAL if the TTL is less than two.
- * @return		EINVAL if the checksum is invalid.
- * @return		EAFNOSUPPORT if the address family is not supported.
- * @return		ENOENT if no route was found.
- * @return		ENOENT if the packet is for another host and the routing
- *			is disabled.
- */
-static int
-ip_process_packet(device_id_t device_id, packet_t *packet)
-{
-	ip_header_t *header;
-	in_addr_t dest;
-	ip_route_t *route;
-	int phone;
-	struct sockaddr *addr;
-	struct sockaddr_in addr_in;
-	socklen_t addrlen;
-	int rc;
-
-	header = (ip_header_t *) packet_get_data(packet);
-	if (!header)
-		return ip_release_and_return(packet, ENOMEM);
-
-	// checksum
-	if ((header->header_checksum) &&
-	    (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
-		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-		if (phone >= 0) {
-			// checksum error ICMP
-			icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
-			    ((size_t) ((void *) &header->header_checksum)) -
-			    ((size_t) ((void *) header)), packet);
-		}
+	int index;
+
+	if (!protocol || !service || ((phone < 0) && !received_msg))
 		return EINVAL;
-	}
-
-	if (header->ttl <= 1) {
-		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-		if (phone >= 0) {
-			// ttl exceeded ICMP
-			icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
-		}
-		return EINVAL;
-	}
-
-	// process ipopt and get destination
-	dest = ip_get_destination(header);
-
-	// set the addrination address
-	switch (header->version) {
-	case IPVERSION:
-		addrlen = sizeof(addr_in);
-		bzero(&addr_in, addrlen);
-		addr_in.sin_family = AF_INET;
-		memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
-		addr = (struct sockaddr *) &addr_in;
-		break;
-
-	default:
-		return ip_release_and_return(packet, EAFNOSUPPORT);
-	}
-
-	rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
-	if (rc != EOK)
-		return rc;
-
-	route = ip_find_route(dest);
-	if (!route) {
-		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-		if (phone >= 0) {
-			// unreachable ICMP
-			icmp_destination_unreachable_msg(phone,
-			    ICMP_HOST_UNREACH, 0, packet);
-		}
-		return ENOENT;
-	}
-
-	if (route->address.s_addr == dest.s_addr) {
-		// local delivery
-		return ip_deliver_local(device_id, packet, header, 0);
-	}
-
-	if (route->netif->routing) {
-		header->ttl--;
-		return ip_send_route(packet, route->netif, route, NULL, dest,
-		    0);
-	}
-
-	phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-	if (phone >= 0) {
-		// unreachable ICMP if no routing
-		icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
-		    packet);
-	}
-	
-	return ENOENT;
-}
+
+	proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
+	if (!proto)
+		return ENOMEM;
+
+	proto->protocol = protocol;
+	proto->service = service;
+	proto->phone = phone;
+	proto->received_msg = received_msg;
+
+	fibril_rwlock_write_lock(&ip_globals.protos_lock);
+	index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
+	if (index < 0) {
+		fibril_rwlock_write_unlock(&ip_globals.protos_lock);
+		free(proto);
+		return index;
+	}
+	fibril_rwlock_write_unlock(&ip_globals.protos_lock);
+
+	printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
+	    NAME, proto->protocol, proto->phone);
+
+	return EOK;
+}
+
 
 static int
@@ -1841,33 +1876,4 @@
 }
 
-/** Processes the received IP packet or the packet queue one by one.
- *
- * The packet is either passed to another module or released on error.
- *
- * @param[in] device_id	The source device identifier.
- * @param[in,out] packet The received packet.
- * @return		EOK on success and the packet is no longer needed.
- * @return		EINVAL if the packet is too small to carry the IP
- *			packet.
- * @return		EINVAL if the received address lengths differs from the
- *			registered values.
- * @return		ENOENT if the device is not found in the cache.
- * @return		ENOENT if the protocol for the device is not found in
- *			the cache.
- * @return		ENOMEM if there is not enough memory left.
- */
-static int ip_receive_message(device_id_t device_id, packet_t *packet)
-{
-	packet_t *next;
-
-	do {
-		next = pq_detach(packet);
-		ip_process_packet(device_id, packet);
-		packet = next;
-	} while (packet);
-
-	return EOK;
-}
-
 /** Processes the IP message.
  *
@@ -1881,19 +1887,18 @@
  *
  * @see ip_interface.h
- * @see il_interface.h
+ * @see il_remote.h
  * @see IS_NET_IP_MESSAGE()
  */
-int
-ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    int *answer_count)
+int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
+    size_t *answer_count)
 {
 	packet_t *packet;
 	struct sockaddr *addr;
+	void *header;
+	size_t headerlen;
 	size_t addrlen;
 	size_t prefix;
 	size_t suffix;
 	size_t content;
-	void *header;
-	size_t headerlen;
 	device_id_t device_id;
 	int rc;
@@ -1905,46 +1910,27 @@
 	
 	case IPC_M_CONNECT_TO_ME:
-		return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
-		    IPC_GET_PHONE(call), NULL);
-	
-	case NET_IL_DEVICE:
-		return ip_device_req_local(0, IPC_GET_DEVICE(call),
-		    IPC_GET_SERVICE(call));
-	
-	case NET_IL_SEND:
+		return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
+		    IPC_GET_PHONE(*call), NULL);
+	
+	case NET_IP_DEVICE:
+		return ip_device_req_local(0, IPC_GET_DEVICE(*call),
+		    IPC_GET_SERVICE(*call));
+	
+	case NET_IP_RECEIVED_ERROR:
 		rc = packet_translate_remote(ip_globals.net_phone, &packet,
-		    IPC_GET_PACKET(call));
+		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
-		return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0,
-		    IPC_GET_ERROR(call));
-	
-	case NET_IL_DEVICE_STATE:
-		return ip_device_state_message(IPC_GET_DEVICE(call),
-		    IPC_GET_STATE(call));
-	
-	case NET_IL_RECEIVED:
-		rc = packet_translate_remote(ip_globals.net_phone, &packet,
-		    IPC_GET_PACKET(call));
-		if (rc != EOK)
-			return rc;
-		return ip_receive_message(IPC_GET_DEVICE(call), packet);
-	
-	case NET_IP_RECEIVED_ERROR:
-		rc = packet_translate_remote(ip_globals.net_phone, &packet,
-		    IPC_GET_PACKET(call));
-		if (rc != EOK)
-			return rc;
-		return ip_received_error_msg_local(0, IPC_GET_DEVICE(call),
-		    packet, IPC_GET_TARGET(call), IPC_GET_ERROR(call));
+		return ip_received_error_msg_local(0, IPC_GET_DEVICE(*call),
+		    packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call));
 	
 	case NET_IP_ADD_ROUTE:
-		return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
-		    IP_GET_ADDRESS(call), IP_GET_NETMASK(call),
-		    IP_GET_GATEWAY(call));
+		return ip_add_route_req_local(0, IPC_GET_DEVICE(*call),
+		    IP_GET_ADDRESS(*call), IP_GET_NETMASK(*call),
+		    IP_GET_GATEWAY(*call));
 
 	case NET_IP_SET_GATEWAY:
-		return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
-		    IP_GET_GATEWAY(call));
+		return ip_set_gateway_req_local(0, IPC_GET_DEVICE(*call),
+		    IP_GET_GATEWAY(*call));
 
 	case NET_IP_GET_ROUTE:
@@ -1954,11 +1940,11 @@
 			return rc;
 		
-		rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(call), addr,
+		rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(*call), addr,
 		    (socklen_t) addrlen, &device_id, &header, &headerlen);
 		if (rc != EOK)
 			return rc;
 		
-		IPC_SET_DEVICE(answer, device_id);
-		IP_SET_HEADERLEN(answer, headerlen);
+		IPC_SET_DEVICE(*answer, device_id);
+		IP_SET_HEADERLEN(*answer, headerlen);
 		
 		*answer_count = 2;
@@ -1971,20 +1957,25 @@
 		return rc;
 	
-	case NET_IL_PACKET_SPACE:
-		rc = ip_packet_size_message(IPC_GET_DEVICE(call), &addrlen,
+	case NET_IP_PACKET_SPACE:
+		rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen,
 		    &prefix, &content, &suffix);
 		if (rc != EOK)
 			return rc;
 		
-		IPC_SET_ADDR(answer, addrlen);
-		IPC_SET_PREFIX(answer, prefix);
-		IPC_SET_CONTENT(answer, content);
-		IPC_SET_SUFFIX(answer, suffix);
+		IPC_SET_ADDR(*answer, addrlen);
+		IPC_SET_PREFIX(*answer, prefix);
+		IPC_SET_CONTENT(*answer, content);
+		IPC_SET_SUFFIX(*answer, suffix);
 		*answer_count = 4;
 		return EOK;
 	
-	case NET_IL_MTU_CHANGED:
-		return ip_mtu_changed_message(IPC_GET_DEVICE(call),
-		    IPC_GET_MTU(call));
+	case NET_IP_SEND:
+		rc = packet_translate_remote(ip_globals.net_phone, &packet,
+		    IPC_GET_PACKET(*call));
+		if (rc != EOK)
+			return rc;
+		
+		return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
+		    IPC_GET_ERROR(*call));
 	}
 	
@@ -1992,58 +1983,8 @@
 }
 
-/** Default thread for new connections.
- *
- * @param[in] iid	The initial message identifier.
- * @param[in] icall	The initial message call structure.
- */
-static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	ipc_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		int answer_count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &answer_count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = il_module_message_standalone(callid, &call, &answer,
-		    &answer_count);
-		
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP)) {
-			return;
-		}
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, answer_count);
-	}
-}
-
-/** Starts the module.
- *
- * @return EOK on success.
- * @return Other error codes as defined for each specific module start function.
- */
 int main(int argc, char *argv[])
 {
-	int rc;
-	
 	/* Start the module */
-	rc = il_module_start_standalone(il_client_connection);
-	return rc;
+	return il_module_start(SERVICE_IP);
 }
 
Index: uspace/srv/net/il/ip/ip.h
===================================================================
--- uspace/srv/net/il/ip/ip.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/il/ip/ip.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -39,7 +39,5 @@
 
 #include <fibril_synch.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <net/inet.h>
@@ -138,6 +136,4 @@
 /** IP global data. */
 struct ip_globals {
-	/** Default client connection function for support modules. */
-	async_client_conn_t client_connection;
 	/** Default gateway. */
 	ip_route_t gateway;
Index: pace/srv/net/il/ip/ip_module.c
===================================================================
--- uspace/srv/net/il/ip/ip_module.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,94 +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 ip
- * @{
- */
-
-/** @file
- * IP standalone module implementation.
- * Contains skeleton module functions mapping.
- * The functions are used by the module skeleton as module specific entry
- * points.
- *
- * @see module.c
- */
-
-#include <async.h>
-#include <stdio.h>
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-#include <errno.h>
-
-#include <net/modules.h>
-#include <net_interface.h>
-#include <net/packet.h>
-#include <il_local.h>
-
-#include "ip.h"
-#include "ip_module.h"
-
-/** IP module global data. */
-extern ip_globals_t ip_globals;
-
-int
-il_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
-{
-	return ip_message_standalone(callid, call, answer, answer_count);
-}
-
-int il_module_start_standalone(async_client_conn_t client_connection)
-{
-	sysarg_t phonehash;
-	int rc;
-	
-	async_set_client_connection(client_connection);
-	ip_globals.net_phone = net_connect_module();
-
-	rc = pm_init();
-	if (rc != EOK)
-		return rc;
-	
-	rc = ip_initialize(client_connection);
-	if (rc != EOK)
-		goto out;
-	
-	rc = ipc_connect_to_me(PHONE_NS, SERVICE_IP, 0, 0, &phonehash);
-	if (rc != EOK)
-		goto out;
-	
-	async_manager();
-
-out:
-	pm_destroy();
-	return rc;
-}
-
-/** @}
- */
Index: pace/srv/net/il/ip/ip_module.h
===================================================================
--- uspace/srv/net/il/ip/ip_module.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,50 +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 ip
- * @{
- */
-
-/** @file
- * IP module functions.
- * The functions are used as IP module entry points.
- */
-
-#ifndef NET_IP_MODULE_H_
-#define NET_IP_MODULE_H_
-
-#include <ipc/ipc.h>
-
-extern int ip_initialize(async_client_conn_t);
-extern int ip_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
-    int *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/net/net.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -45,10 +45,11 @@
 #include <stdio.h>
 #include <str.h>
-
-#include <ipc/ipc.h>
+#include <str_error.h>
+
 #include <ipc/services.h>
 #include <ipc/net.h>
 #include <ipc/net_net.h>
 #include <ipc/il.h>
+#include <ipc/nil.h>
 
 #include <net/modules.h>
@@ -62,5 +63,5 @@
 
 #include <netif_remote.h>
-#include <nil_interface.h>
+#include <nil_remote.h>
 #include <net_interface.h>
 #include <ip_interface.h>
@@ -288,6 +289,6 @@
 	if (rc != EOK)
 		return rc;
-	rc = add_module(NULL, &net_globals.modules, (uint8_t *) DP8390_NAME,
-	    (uint8_t *) DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service);
+	rc = add_module(NULL, &net_globals.modules, (uint8_t *) NE2000_NAME,
+	    (uint8_t *) NE2000_FILENAME, SERVICE_NE2000, 0, connect_to_service);
 	if (rc != EOK)
 		return rc;
@@ -324,5 +325,4 @@
 static int net_module_start(async_client_conn_t client_connection)
 {
-	sysarg_t phonehash;
 	int rc;
 	
@@ -332,10 +332,9 @@
 		return rc;
 	
-	
 	rc = net_initialize(client_connection);
 	if (rc != EOK)
 		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;
@@ -474,7 +473,7 @@
 	
 	setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IO, 0);
-	int io = setting ? strtol((char *) setting->value, NULL, 16) : 0;
-	
-	rc = netif_probe_req_remote(netif->driver->phone, netif->id, irq, io);
+	uintptr_t io = setting ? strtol((char *) setting->value, NULL, 16) : 0;
+	
+	rc = netif_probe_req(netif->driver->phone, netif->id, irq, (void *) io);
 	if (rc != EOK)
 		return rc;
@@ -511,5 +510,5 @@
 	}
 	
-	return netif_start_req_remote(netif->driver->phone, netif->id);
+	return netif_start_req(netif->driver->phone, netif->id);
 }
 
@@ -591,6 +590,9 @@
 		rc = start_device(netif);
 		if (rc != EOK) {
+			printf("%s: Error starting interface %s (%s)\n", NAME,
+			    netif->name, str_error(rc));
 			measured_strings_destroy(&netif->configuration);
 			netifs_exclude_index(&net_globals.netifs, index);
+			
 			return rc;
 		}
@@ -613,6 +615,6 @@
 /** Process the networking message.
  *
- * @param[in] callid        The message identifier.
- * @param[in] call          The message parameters.
+ * @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
@@ -627,5 +629,5 @@
  */
 int net_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    int *answer_count)
+    size_t *answer_count)
 {
 	measured_string_t *strings;
@@ -639,27 +641,27 @@
 	case NET_NET_GET_DEVICE_CONF:
 		rc = measured_strings_receive(&strings, &data,
-		    IPC_GET_COUNT(call));
+		    IPC_GET_COUNT(*call));
 		if (rc != EOK)
 			return rc;
-		net_get_device_conf_req(0, IPC_GET_DEVICE(call), &strings,
-		    IPC_GET_COUNT(call), NULL);
+		net_get_device_conf_req(0, IPC_GET_DEVICE(*call), &strings,
+		    IPC_GET_COUNT(*call), NULL);
 		
 		/* Strings should not contain received data anymore */
 		free(data);
 		
-		rc = measured_strings_reply(strings, IPC_GET_COUNT(call));
+		rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
 		free(strings);
 		return rc;
 	case NET_NET_GET_CONF:
 		rc = measured_strings_receive(&strings, &data,
-		    IPC_GET_COUNT(call));
+		    IPC_GET_COUNT(*call));
 		if (rc != EOK)
 			return rc;
-		net_get_conf_req(0, &strings, IPC_GET_COUNT(call), NULL);
+		net_get_conf_req(0, &strings, IPC_GET_COUNT(*call), NULL);
 		
 		/* Strings should not contain received data anymore */
 		free(data);
 		
-		rc = measured_strings_reply(strings, IPC_GET_COUNT(call));
+		rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
 		free(strings);
 		return rc;
@@ -683,10 +685,10 @@
 	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
 	 */
-	ipc_answer_0(iid, EOK);
+	async_answer_0(iid, EOK);
 	
 	while (true) {
 		/* Clear the answer structure */
 		ipc_call_t answer;
-		int answer_count;
+		size_t answer_count;
 		refresh_answer(&answer, &answer_count);
 		
@@ -709,13 +711,5 @@
 int main(int argc, char *argv[])
 {
-	int rc;
-	
-	rc = net_module_start(net_client_connection);
-	if (rc != EOK) {
-		fprintf(stderr, "%s: net_module_start error %i\n", NAME, rc);
-		return rc;
-	}
-	
-	return EOK;
+	return net_module_start(net_client_connection);
 }
 
Index: uspace/srv/net/net/net.h
===================================================================
--- uspace/srv/net/net/net.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/net/net.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -39,6 +39,4 @@
 #define NET_NET_H_
 
-#include <ipc/ipc.h>
-
 #include <net/device.h>
 #include <adt/char_map.h>
@@ -52,6 +50,6 @@
  */
 
-#define DP8390_FILENAME  "/srv/dp8390"
-#define DP8390_NAME      "dp8390"
+#define NE2000_FILENAME  "/srv/ne2000"
+#define NE2000_NAME      "ne2000"
 
 #define ETHERNET_FILENAME  "/srv/eth"
@@ -135,7 +133,7 @@
 extern int add_configuration(measured_strings_t *, const uint8_t *,
     const uint8_t *);
-extern int net_module_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, int *);
+extern int net_module_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, size_t *);
 extern int net_initialize_build(async_client_conn_t);
-extern int net_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, int *);
+extern int net_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, size_t *);
 
 #endif
Index: uspace/srv/net/net/net_standalone.c
===================================================================
--- uspace/srv/net/net/net_standalone.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/net/net_standalone.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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>
@@ -100,10 +99,10 @@
  */
 int net_module_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
+    ipc_call_t *answer, size_t *count)
 {
-	if (IS_NET_PACKET_MESSAGE(call))
-		return packet_server_message(callid, call, answer, answer_count);
+	if (IS_NET_PACKET_MESSAGE(*call))
+		return packet_server_message(callid, call, answer, count);
 	
-	return net_message(callid, call, answer, answer_count);
+	return net_message(callid, call, answer, count);
 }
 
Index: uspace/srv/net/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/netif/lo/lo.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -39,19 +39,12 @@
 #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>
 #include <packet_client.h>
 #include <net/device.h>
-#include <nil_interface.h>
-#include <netif_interface.h>
-#include <netif_local.h>
-
-/** Default hardware address. */
-#define DEFAULT_ADDR  0
+#include <netif_skel.h>
+#include <nil_remote.h>
 
 /** Default address length. */
@@ -61,9 +54,9 @@
 #define NAME  "lo"
 
-/** Network interface global data. */
-netif_globals_t netif_globals;
+static uint8_t default_addr[DEFAULT_ADDR_LEN] =
+    {0, 0, 0, 0, 0, 0};
 
 int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
+    ipc_call_t *answer, size_t *count)
 {
 	return ENOTSUP;
@@ -75,8 +68,5 @@
 		return EBADMEM;
 	
-	uint8_t *addr = (uint8_t *) malloc(DEFAULT_ADDR_LEN);
-	memset(addr, DEFAULT_ADDR, DEFAULT_ADDR_LEN);
-	
-	address->value = addr;
+	address->value = default_addr;
 	address->length = DEFAULT_ADDR_LEN;
 	
@@ -86,60 +76,67 @@
 int netif_get_device_stats(device_id_t device_id, device_stats_t *stats)
 {
-	netif_device_t *device;
-	int rc;
-
 	if (!stats)
 		return EBADMEM;
-
-	rc = find_device(device_id, &device);
+	
+	netif_device_t *device;
+	int rc = find_device(device_id, &device);
 	if (rc != EOK)
 		return rc;
-
+	
 	memcpy(stats, (device_stats_t *) device->specific,
 	    sizeof(device_stats_t));
-
-	return EOK;
-}
-
-/** Changes the loopback state.
- *
- * @param[in] device	The device structure.
- * @param[in] state	The new device state.
- * @return		The new state if changed.
- * @return		EOK otherwise.
- */
-static int change_state_message(netif_device_t *device, device_state_t state)
+	
+	return EOK;
+}
+
+/** Change the loopback state.
+ *
+ * @param[in] device The device structure.
+ * @param[in] state  The new device state.
+ *
+ * @return New state if changed.
+ * @return EOK otherwise.
+ *
+ */
+static void change_state_message(netif_device_t *device, device_state_t state)
 {
 	if (device->state != state) {
 		device->state = state;
 		
-		printf("%s: State changed to %s\n", NAME,
-		    (state == NETIF_ACTIVE) ? "active" : "stopped");
+		const char *desc;
+		switch (state) {
+		case NETIF_ACTIVE:
+			desc = "active";
+			break;
+		case NETIF_STOPPED:
+			desc = "stopped";
+			break;
+		default:
+			desc = "unknown";
+		}
 		
-		return state;
-	}
-	
-	return EOK;
-}
-
-/** Creates and returns the loopback network interface structure.
- *
- * @param[in] device_id	The new devce identifier.
- * @param[out] device	The device structure.
- * @return		EOK on success.
- * @return		EXDEV if one loopback network interface already exists.
- * @return		ENOMEM if there is not enough memory left.
- */
-static int create(device_id_t device_id, netif_device_t **device)
-{
-	int index;
-
+		printf("%s: State changed to %s\n", NAME, desc);
+	}
+}
+
+/** Create and return the loopback network interface structure.
+ *
+ * @param[in]  device_id New devce identifier.
+ * @param[out] device    Device structure.
+ *
+ * @return EOK on success.
+ * @return EXDEV if one loopback network interface already exists.
+ * @return ENOMEM if there is not enough memory left.
+ *
+ */
+static int lo_create(device_id_t device_id, netif_device_t **device)
+{
 	if (netif_device_map_count(&netif_globals.device_map) > 0)
 		return EXDEV;
-
+	
 	*device = (netif_device_t *) malloc(sizeof(netif_device_t));
 	if (!*device)
 		return ENOMEM;
-
+	
 	(*device)->specific = (device_stats_t *) malloc(sizeof(device_stats_t));
 	if (!(*device)->specific) {
@@ -147,12 +144,12 @@
 		return ENOMEM;
 	}
-
+	
 	null_device_stats((device_stats_t *) (*device)->specific);
 	(*device)->device_id = device_id;
 	(*device)->nil_phone = -1;
 	(*device)->state = NETIF_STOPPED;
-	index = netif_device_map_add(&netif_globals.device_map,
+	int index = netif_device_map_add(&netif_globals.device_map,
 	    (*device)->device_id, *device);
-
+	
 	if (index < 0) {
 		free(*device);
@@ -167,22 +164,16 @@
 int netif_initialize(void)
 {
-	sysarg_t phonehash;
-
-	return ipc_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, &phonehash);
-}
-
-int netif_probe_message(device_id_t device_id, int irq, uintptr_t io)
-{
+	return async_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, NULL);
+}
+
+int netif_probe_message(device_id_t device_id, int irq, void *io)
+{
+	/* Create a new device */
 	netif_device_t *device;
-	int rc;
-
-	/* Create a new device */
-	rc = create(device_id, &device);
+	int rc = lo_create(device_id, &device);
 	if (rc != EOK)
 		return rc;
-
-	/* Print the settings */
+	
 	printf("%s: Device created (id: %d)\n", NAME, device->device_id);
-
 	return EOK;
 }
@@ -191,33 +182,29 @@
 {
 	netif_device_t *device;
-	size_t length;
-	packet_t *next;
-	int phone;
-	int rc;
-
-	rc = find_device(device_id, &device);
+	int rc = find_device(device_id, &device);
 	if (rc != EOK)
 		return EOK;
-
+	
 	if (device->state != NETIF_ACTIVE) {
 		netif_pq_release(packet_get_id(packet));
 		return EFORWARD;
 	}
-
-	next = packet;
+	
+	packet_t *next = packet;
 	do {
 		((device_stats_t *) device->specific)->send_packets++;
 		((device_stats_t *) device->specific)->receive_packets++;
-		length = packet_get_data_length(next);
+		size_t length = packet_get_data_length(next);
 		((device_stats_t *) device->specific)->send_bytes += length;
 		((device_stats_t *) device->specific)->receive_bytes += length;
 		next = pq_next(next);
-	} while(next);
-
-	phone = device->nil_phone;
+	} while (next);
+	
+	int phone = device->nil_phone;
 	fibril_rwlock_write_unlock(&netif_globals.lock);
+	
 	nil_received_msg(phone, device_id, packet, sender);
+	
 	fibril_rwlock_write_lock(&netif_globals.lock);
-	
 	return EOK;
 }
@@ -225,60 +212,18 @@
 int netif_start_message(netif_device_t *device)
 {
-	return change_state_message(device, NETIF_ACTIVE);
+	change_state_message(device, NETIF_ACTIVE);
+	return device->state;
 }
 
 int netif_stop_message(netif_device_t *device)
 {
-	return change_state_message(device, NETIF_STOPPED);
-}
-
-/** Default thread for new connections.
- *
- * @param[in] iid	The initial message identifier.
- * @param[in] icall	The initial message call structure.
- */
-static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	ipc_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		int answer_count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &answer_count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = netif_module_message(NAME, callid, &call, &answer,
-		    &answer_count);
-		
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, answer_count);
-	}
+	change_state_message(device, NETIF_STOPPED);
+	return device->state;
 }
 
 int main(int argc, char *argv[])
 {
-	int rc;
-	
 	/* Start the module */
-	rc = netif_module_start(netif_client_connection);
-	return rc;
+	return netif_module_start();
 }
 
Index: uspace/srv/net/nil/eth/Makefile
===================================================================
--- uspace/srv/net/nil/eth/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/nil/eth/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -42,6 +42,5 @@
 
 SOURCES = \
-	eth.c \
-	eth_module.c
+	eth.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/nil/eth/eth.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -43,9 +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>
@@ -54,15 +52,13 @@
 #include <protocol_map.h>
 #include <net/device.h>
-#include <netif_interface.h>
+#include <netif_remote.h>
 #include <net_interface.h>
-#include <nil_interface.h>
-#include <il_interface.h>
+#include <il_remote.h>
 #include <adt/measured_strings.h>
 #include <packet_client.h>
 #include <packet_remote.h>
-#include <nil_local.h>
+#include <nil_skel.h>
 
 #include "eth.h"
-#include "eth_header.h"
 
 /** The module name. */
@@ -72,45 +68,44 @@
 #define ETH_PREFIX \
 	(sizeof(eth_header_t) + sizeof(eth_header_lsap_t) + \
-	sizeof(eth_header_snap_t))
+	    sizeof(eth_header_snap_t))
 
 /** Reserved packet suffix length. */
-#define ETH_SUFFIX \
-	sizeof(eth_fcs_t)
+#define ETH_SUFFIX  (sizeof(eth_fcs_t))
 
 /** Maximum packet content length. */
-#define ETH_MAX_CONTENT 1500u
+#define ETH_MAX_CONTENT  1500u
 
 /** Minimum packet content length. */
-#define ETH_MIN_CONTENT 46u
+#define ETH_MIN_CONTENT  46u
 
 /** Maximum tagged packet content length. */
 #define ETH_MAX_TAGGED_CONTENT(flags) \
 	(ETH_MAX_CONTENT - \
-	((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
-	sizeof(eth_header_lsap_t) : 0) - \
-	(IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
+	    ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
+	    sizeof(eth_header_lsap_t) : 0) - \
+	    (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
 
 /** Minimum tagged packet content length. */
 #define ETH_MIN_TAGGED_CONTENT(flags) \
 	(ETH_MIN_CONTENT - \
-	((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
-	sizeof(eth_header_lsap_t) : 0) - \
-	(IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
+	    ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
+	    sizeof(eth_header_lsap_t) : 0) - \
+	    (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
 
 /** Dummy flag shift value. */
-#define ETH_DUMMY_SHIFT	0
+#define ETH_DUMMY_SHIFT  0
 
 /** Mode flag shift value. */
-#define ETH_MODE_SHIFT	1
+#define ETH_MODE_SHIFT  1
 
 /** Dummy device flag.
  * Preamble and FCS are mandatory part of the packets.
  */
-#define ETH_DUMMY		(1 << ETH_DUMMY_SHIFT)
+#define ETH_DUMMY  (1 << ETH_DUMMY_SHIFT)
 
 /** Returns the dummy flag.
  * @see ETH_DUMMY
  */
-#define IS_DUMMY(flags)		((flags) & ETH_DUMMY)
+#define IS_DUMMY(flags)  ((flags) & ETH_DUMMY)
 
 /** Device mode flags.
@@ -119,35 +114,38 @@
  * @see ETH_8023_2_SNAP
  */
-#define ETH_MODE_MASK		(3 << ETH_MODE_SHIFT)
+#define ETH_MODE_MASK  (3 << ETH_MODE_SHIFT)
 
 /** DIX Ethernet mode flag. */
-#define ETH_DIX			(1 << ETH_MODE_SHIFT)
-
-/** Returns whether the DIX Ethernet mode flag is set.
- *
- * @param[in] flags	The ethernet flags.
+#define ETH_DIX  (1 << ETH_MODE_SHIFT)
+
+/** Return whether the DIX Ethernet mode flag is set.
+ *
+ * @param[in] flags Ethernet flags.
  * @see ETH_DIX
- */
-#define IS_DIX(flags)		(((flags) & ETH_MODE_MASK) == ETH_DIX)
+ *
+ */
+#define IS_DIX(flags)  (((flags) & ETH_MODE_MASK) == ETH_DIX)
 
 /** 802.3 + 802.2 + LSAP mode flag. */
-#define ETH_8023_2_LSAP		(2 << ETH_MODE_SHIFT)
-
-/** Returns whether the 802.3 + 802.2 + LSAP mode flag is set.
- *
- * @param[in] flags	The ethernet flags.
+#define ETH_8023_2_LSAP  (2 << ETH_MODE_SHIFT)
+
+/** Return whether the 802.3 + 802.2 + LSAP mode flag is set.
+ *
+ * @param[in] flags Ethernet flags.
  * @see ETH_8023_2_LSAP
- */
-#define IS_8023_2_LSAP(flags)	(((flags) & ETH_MODE_MASK) == ETH_8023_2_LSAP)
+ *
+ */
+#define IS_8023_2_LSAP(flags)  (((flags) & ETH_MODE_MASK) == ETH_8023_2_LSAP)
 
 /** 802.3 + 802.2 + LSAP + SNAP mode flag. */
-#define ETH_8023_2_SNAP		(3 << ETH_MODE_SHIFT)
-
-/** Returns whether the 802.3 + 802.2 + LSAP + SNAP mode flag is set.
- *
- * @param[in] flags	The ethernet flags.
+#define ETH_8023_2_SNAP  (3 << ETH_MODE_SHIFT)
+
+/** Return whether the 802.3 + 802.2 + LSAP + SNAP mode flag is set.
+ *
+ * @param[in] flags Ethernet flags.
  * @see ETH_8023_2_SNAP
- */
-#define IS_8023_2_SNAP(flags)	(((flags) & ETH_MODE_MASK) == ETH_8023_2_SNAP)
+ *
+ */
+#define IS_8023_2_SNAP(flags)  (((flags) & ETH_MODE_MASK) == ETH_8023_2_SNAP)
 
 /** Type definition of the ethernet address type.
@@ -239,19 +237,19 @@
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_NIL_DEVICE_STATE:
-			nil_device_state_msg_local(0, IPC_GET_DEVICE(icall),
-			    IPC_GET_STATE(icall));
-			ipc_answer_0(iid, EOK);
+			nil_device_state_msg_local(0, IPC_GET_DEVICE(*icall),
+			    IPC_GET_STATE(*icall));
+			async_answer_0(iid, EOK);
 			break;
 		case NET_NIL_RECEIVED:
 			rc = packet_translate_remote(eth_globals.net_phone,
-			    &packet, IPC_GET_PACKET(icall));
-			if (rc == EOK) {
+			    &packet, IPC_GET_PACKET(*icall));
+			if (rc == EOK)
 				rc = nil_received_msg_local(0,
-				    IPC_GET_DEVICE(icall), packet, 0);
-			}
-			ipc_answer_0(iid, (sysarg_t) rc);
+				    IPC_GET_DEVICE(*icall), packet, 0);
+			
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		default:
-			ipc_answer_0(iid, (sysarg_t) ENOTSUP);
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
 		}
 		
@@ -836,6 +834,6 @@
 }
 
-int nil_message_standalone(const char *name, ipc_callid_t callid,
-    ipc_call_t *call, ipc_call_t *answer, int *answer_count)
+int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, size_t *answer_count)
 {
 	measured_string_t *address;
@@ -853,26 +851,26 @@
 	
 	case NET_NIL_DEVICE:
-		return eth_device_message(IPC_GET_DEVICE(call),
-		    IPC_GET_SERVICE(call), IPC_GET_MTU(call));
+		return eth_device_message(IPC_GET_DEVICE(*call),
+		    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
 	case NET_NIL_SEND:
 		rc = packet_translate_remote(eth_globals.net_phone, &packet,
-		    IPC_GET_PACKET(call));
+		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
-		return eth_send_message(IPC_GET_DEVICE(call), packet,
-		    IPC_GET_SERVICE(call));
+		return eth_send_message(IPC_GET_DEVICE(*call), packet,
+		    IPC_GET_SERVICE(*call));
 	case NET_NIL_PACKET_SPACE:
-		rc = eth_packet_space_message(IPC_GET_DEVICE(call), &addrlen,
+		rc = eth_packet_space_message(IPC_GET_DEVICE(*call), &addrlen,
 		    &prefix, &content, &suffix);
 		if (rc != EOK)
 			return rc;
-		IPC_SET_ADDR(answer, addrlen);
-		IPC_SET_PREFIX(answer, prefix);
-		IPC_SET_CONTENT(answer, content);
-		IPC_SET_SUFFIX(answer, suffix);
+		IPC_SET_ADDR(*answer, addrlen);
+		IPC_SET_PREFIX(*answer, prefix);
+		IPC_SET_CONTENT(*answer, content);
+		IPC_SET_SUFFIX(*answer, suffix);
 		*answer_count = 4;
 		return EOK;
 	case NET_NIL_ADDR:
-		rc = eth_addr_message(IPC_GET_DEVICE(call), ETH_LOCAL_ADDR,
+		rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR,
 		    &address);
 		if (rc != EOK)
@@ -880,5 +878,5 @@
 		return measured_strings_reply(address, 1);
 	case NET_NIL_BROADCAST_ADDR:
-		rc = eth_addr_message(IPC_GET_DEVICE(call), ETH_BROADCAST_ADDR,
+		rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR,
 		    &address);
 		if (rc != EOK)
@@ -886,6 +884,6 @@
 		return measured_strings_reply(address, 1);
 	case IPC_M_CONNECT_TO_ME:
-		return eth_register_message(NIL_GET_PROTO(call),
-		    IPC_GET_PHONE(call));
+		return eth_register_message(NIL_GET_PROTO(*call),
+		    IPC_GET_PHONE(*call));
 	}
 	
@@ -893,52 +891,8 @@
 }
 
-/** Default thread for new connections.
- *
- * @param[in] iid	The initial message identifier.
- * @param[in] icall	The initial message call structure.
- */
-static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	ipc_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		int answer_count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &answer_count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = nil_module_message_standalone(NAME, callid, &call,
-		    &answer, &answer_count);
-		
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, answer_count);
-	}
-}
-
 int main(int argc, char *argv[])
 {
-	int rc;
-	
 	/* Start the module */
-	rc = nil_module_start_standalone(nil_client_connection);
-	return rc;
+	return nil_module_start(SERVICE_ETHERNET);
 }
 
Index: uspace/srv/net/nil/eth/eth.h
===================================================================
--- uspace/srv/net/nil/eth/eth.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/nil/eth/eth.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -44,4 +44,150 @@
 #include <adt/measured_strings.h>
 
+/** Ethernet address length. */
+#define ETH_ADDR  6
+
+/** Ethernet header preamble value. */
+#define ETH_PREAMBLE  0x55
+
+/** Ethernet header start of frame value. */
+#define ETH_SFD  0xD5
+
+/** IEEE 802.2 unordered information control field. */
+#define IEEE_8023_2_UI  0x03
+
+/** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions.
+ * @see eth_header_snap
+ */
+typedef struct eth_header_snap eth_header_snap_t;
+
+/** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions.
+ * @see eth_header_lsap
+ */
+typedef struct eth_header_lsap eth_header_lsap_t;
+
+/** Type definition of the Ethernet header LSAP extension.
+ * @see eth_ieee_lsap
+ */
+typedef struct eth_ieee_lsap eth_ieee_lsap_t;
+
+/** Type definition of the Ethernet header SNAP extension.
+ * @see eth_snap
+ */
+typedef struct eth_snap eth_snap_t;
+
+/** Type definition of the Ethernet header preamble.
+ * @see preamble
+ */
+typedef struct eth_preamble eth_preamble_t;
+
+/** Type definition of the Ethernet header.
+ * @see eth_header
+ */
+typedef struct eth_header eth_header_t;
+
+/** Ethernet header Link Service Access Point extension. */
+struct eth_ieee_lsap {
+	/**
+	 * Destination Service Access Point identifier.
+	 * The possible values are assigned by an IEEE committee.
+	 */
+	uint8_t dsap;
+	
+	/**
+	 * Source Service Access Point identifier.
+	 * The possible values are assigned by an IEEE committee.
+	 */
+	uint8_t ssap;
+	
+	/**
+	 * Control parameter.
+	 * The possible values are assigned by an IEEE committee.
+	 */
+	uint8_t ctrl;
+} __attribute__ ((packed));
+
+/** Ethernet header SNAP extension. */
+struct eth_snap {
+	/** Protocol identifier or organization code. */
+	uint8_t protocol[3];
+	
+	/**
+	 * Ethernet protocol identifier in the network byte order (big endian).
+	 * @see ethernet_protocols.h
+	 */
+	uint16_t ethertype;
+} __attribute__ ((packed));
+
+/** Ethernet header preamble.
+ *
+ * Used for dummy devices.
+ */
+struct eth_preamble {
+	/**
+	 * Controlling preamble used for the frame transmission synchronization.
+	 * All should be set to ETH_PREAMBLE.
+	 */
+	uint8_t preamble[7];
+	
+	/**
+	 * Start of Frame Delimiter used for the frame transmission
+	 * synchronization.
+	 * Should be set to ETH_SFD.
+	 */
+	uint8_t sfd;
+} __attribute__ ((packed));
+
+/** Ethernet header. */
+struct eth_header {
+	/** Destination host Ethernet address (MAC address). */
+	uint8_t destination_address[ETH_ADDR];
+	/** Source host Ethernet address (MAC address). */
+	uint8_t source_address[ETH_ADDR];
+	
+	/**
+	 * Ethernet protocol identifier in the network byte order (big endian).
+	 * @see ethernet_protocols.h
+	 */
+	uint16_t ethertype;
+} __attribute__ ((packed));
+
+/** Ethernet header IEEE 802.3 + 802.2 extension. */
+struct eth_header_lsap {
+	/** Ethernet header. */
+	eth_header_t header;
+	
+	/**
+	 * LSAP extension.
+	 * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being
+	 * used.
+	 * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet
+	 * without any extensions is being used and the frame content starts
+	 * rigth after the two fields.
+	 */
+	eth_ieee_lsap_t lsap;
+} __attribute__ ((packed));
+
+/** Ethernet header IEEE 802.3 + 802.2 + SNAP extensions. */
+struct eth_header_snap {
+	/** Ethernet header. */
+	eth_header_t header;
+	
+	/**
+	 * LSAP extension.
+	 * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being
+	 * used.
+	 * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet
+	 * without any extensions is being used and the frame content starts
+	 * rigth after the two fields.
+	 */
+	eth_ieee_lsap_t lsap;
+	
+	/** SNAP extension. */
+	eth_snap_t snap;
+} __attribute__ ((packed));
+
+/** Ethernet Frame Check Sequence. */
+typedef uint32_t eth_fcs_t;
+
 /** Type definition of the Ethernet global data.
  * @see eth_globals
Index: pace/srv/net/nil/eth/eth_header.h
===================================================================
--- uspace/srv/net/nil/eth/eth_header.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,192 +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 eth
- *  @{
- */
-
-/** @file
- * Ethernet protocol header definitions.
- * Based on the IEEE 802.3-2005
- */
-
-#ifndef NET_ETH_HEADER_H_
-#define NET_ETH_HEADER_H_
-
-#include <sys/types.h>
-
-/** Ethernet address length. */
-#define ETH_ADDR	6
-
-/** Ethernet header preamble value. */
-#define ETH_PREAMBLE	0x55
-
-/** Ethernet header start of frame value. */
-#define ETH_SFD		0xD5
-
-/** IEEE 802.2 unordered information control field. */
-#define IEEE_8023_2_UI	0x03
-
-/** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions.
- * @see eth_header_snap
- */
-typedef struct eth_header_snap eth_header_snap_t;
-
-/** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions.
- * @see eth_header_lsap
- */
-typedef struct eth_header_lsap eth_header_lsap_t;
-
-/** Type definition of the Ethernet header LSAP extension.
- * @see eth_ieee_lsap
- */
-typedef struct eth_ieee_lsap eth_ieee_lsap_t;
-
-/** Type definition of the Ethernet header SNAP extension.
- * @see eth_snap
- */
-typedef struct eth_snap eth_snap_t;
-
-/** Type definition of the Ethernet header preamble.
- * @see preamble
- */
-typedef struct eth_preamble eth_preamble_t;
-
-/** Type definition of the Ethernet header.
- * @see eth_header
- */
-typedef struct eth_header eth_header_t;
-
-/** Ethernet header Link Service Access Point extension. */
-struct eth_ieee_lsap {
-	/**
-	 * Destination Service Access Point identifier.
-	 * The possible values are assigned by an IEEE committee.
-	 */
-	uint8_t dsap;
-	
-	/**
-	 * Source Service Access Point identifier.
-	 * The possible values are assigned by an IEEE committee.
-	 */
-	uint8_t ssap;
-	
-	/**
-	 * Control parameter.
-	 * The possible values are assigned by an IEEE committee.
-	 */
-	uint8_t ctrl;
-} __attribute__ ((packed));
-
-/** Ethernet header SNAP extension. */
-struct eth_snap {
-	/** Protocol identifier or organization code. */
-	uint8_t protocol[3];
-	
-	/**
-	 * Ethernet protocol identifier in the network byte order (big endian).
-	 * @see ethernet_protocols.h
-	 */
-	uint16_t ethertype;
-} __attribute__ ((packed));
-
-/** Ethernet header preamble.
- *
- * Used for dummy devices.
- */
-struct eth_preamble {
-	/**
-	 * Controlling preamble used for the frame transmission synchronization.
-	 * All should be set to ETH_PREAMBLE.
-	 */
-	uint8_t preamble[7];
-	
-	/**
-	 * Start of Frame Delimiter used for the frame transmission
-	 * synchronization.
-	 * Should be set to ETH_SFD.
-	 */
-	uint8_t sfd;
-} __attribute__ ((packed));
-
-/** Ethernet header. */
-struct eth_header {
-	/** Destination host Ethernet address (MAC address). */
-	uint8_t destination_address[ETH_ADDR];
-	/** Source host Ethernet address (MAC address). */
-	uint8_t source_address[ETH_ADDR];
-	
-	/**
-	 * Ethernet protocol identifier in the network byte order (big endian).
-	 * @see ethernet_protocols.h
-	 */
-	uint16_t ethertype;
-} __attribute__ ((packed));
-
-/** Ethernet header IEEE 802.3 + 802.2 extension. */
-struct eth_header_lsap {
-	/** Ethernet header. */
-	eth_header_t header;
-	
-	/**
-	 * LSAP extension.
-	 * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being
-	 * used.
-	 * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet
-	 * without any extensions is being used and the frame content starts
-	 * rigth after the two fields.
-	 */
-	eth_ieee_lsap_t lsap;
-} __attribute__ ((packed));
-
-/** Ethernet header IEEE 802.3 + 802.2 + SNAP extensions. */
-struct eth_header_snap {
-	/** Ethernet header. */
-	eth_header_t header;
-	
-	/**
-	 * LSAP extension.
-	 * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being
-	 * used.
-	 * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet
-	 * without any extensions is being used and the frame content starts
-	 * rigth after the two fields.
-	 */
-	eth_ieee_lsap_t lsap;
-	
-	/** SNAP extension. */
-	eth_snap_t snap;
-} __attribute__ ((packed));
-
-/** Ethernet Frame Check Sequence. */
-typedef uint32_t eth_fcs_t;
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/nil/eth/eth_module.c
===================================================================
--- uspace/srv/net/nil/eth/eth_module.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,86 +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 eth
- * @{
- */
-
-/** @file
- *  Ethernet module stub.
- *  @see module.c
- */
-
-#include "eth.h"
-
-#include <async.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-
-#include <net/modules.h>
-#include <net_interface.h>
-#include <net/packet.h>
-#include <nil_local.h>
-
-int nil_module_start_standalone(async_client_conn_t client_connection)
-{
-	sysarg_t phonehash;
-	int rc;
-	
-	async_set_client_connection(client_connection);
-	int net_phone = net_connect_module();
-
-	rc = pm_init();
-	if (rc != EOK)
-		return rc;
-	
-	rc = nil_initialize(net_phone);
-	if (rc != EOK)
-		goto out;
-
-	rc = ipc_connect_to_me(PHONE_NS, SERVICE_ETHERNET, 0, 0, &phonehash);
-	if (rc != EOK)
-		goto out;
-	
-	async_manager();
-
-out:
-	pm_destroy();
-	return rc;
-}
-
-int nil_module_message_standalone(const char *name, ipc_callid_t callid,
-    ipc_call_t *call, ipc_call_t *answer, int *answer_count)
-{
-	return nil_message_standalone(name, callid, call, answer, answer_count);
-}
-
-/** @}
- */
Index: uspace/srv/net/nil/nildummy/Makefile
===================================================================
--- uspace/srv/net/nil/nildummy/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/nil/nildummy/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -42,6 +42,5 @@
 
 SOURCES = \
-	nildummy.c \
-	nildummy_module.c
+	nildummy.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -41,5 +41,5 @@
 #include <stdio.h>
 #include <str.h>
-#include <ipc/ipc.h>
+#include <ipc/nil.h>
 #include <ipc/net.h>
 #include <ipc/services.h>
@@ -47,11 +47,10 @@
 #include <net/modules.h>
 #include <net/device.h>
-#include <netif_interface.h>
-#include <nil_interface.h>
-#include <il_interface.h>
+#include <il_remote.h>
 #include <adt/measured_strings.h>
 #include <net/packet.h>
 #include <packet_remote.h>
-#include <nil_local.h>
+#include <netif_remote.h>
+#include <nil_skel.h>
 
 #include "nildummy.h"
@@ -81,6 +80,4 @@
 int nil_initialize(int net_phone)
 {
-	int rc;
-	
 	fibril_rwlock_initialize(&nildummy_globals.devices_lock);
 	fibril_rwlock_initialize(&nildummy_globals.protos_lock);
@@ -90,5 +87,5 @@
 	nildummy_globals.net_phone = net_phone;
 	nildummy_globals.proto.phone = 0;
-	rc = nildummy_devices_initialize(&nildummy_globals.devices);
+	int rc = nildummy_devices_initialize(&nildummy_globals.devices);
 	
 	fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
@@ -98,9 +95,9 @@
 }
 
-/** Process IPC messages from the registered device driver modules in an
- * infinite loop.
- *
- * @param[in] iid	The message identifier.
- * @param[in,out]	icall The message parameters.
+/** Process IPC messages from the registered device driver modules
+ *
+ * @param[in]     iid   Message identifier.
+ * @param[in,out] icall Message parameters.
+ *
  */
 static void nildummy_receiver(ipc_callid_t iid, ipc_call_t *icall)
@@ -108,25 +105,25 @@
 	packet_t *packet;
 	int rc;
-
+	
 	while (true) {
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_NIL_DEVICE_STATE:
 			rc = nil_device_state_msg_local(0,
-			    IPC_GET_DEVICE(icall), IPC_GET_STATE(icall));
-			ipc_answer_0(iid, (sysarg_t) rc);
+			    IPC_GET_DEVICE(*icall), IPC_GET_STATE(*icall));
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
 		case NET_NIL_RECEIVED:
 			rc = packet_translate_remote(nildummy_globals.net_phone,
-			    &packet, IPC_GET_PACKET(icall));
-			if (rc == EOK) {
+			    &packet, IPC_GET_PACKET(*icall));
+			if (rc == EOK)
 				rc = nil_received_msg_local(0,
-				    IPC_GET_DEVICE(icall), packet, 0);
-			}
-			ipc_answer_0(iid, (sysarg_t) rc);
+				    IPC_GET_DEVICE(*icall), packet, 0);
+			
+			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
 		default:
-			ipc_answer_0(iid, (sysarg_t) ENOTSUP);
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
 		}
 		
@@ -139,26 +136,25 @@
  * Determine the device local hardware address.
  *
- * @param[in] device_id	The new device identifier.
- * @param[in] service	The device driver service.
- * @param[in] mtu	The device maximum transmission unit.
- * @return		EOK on success.
- * @return		EEXIST if the device with the different service exists.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			netif_bind_service() function.
- * @return		Other error codes as defined for the
- *			netif_get_addr_req() function.
+ * @param[in] device_id New device identifier.
+ * @param[in] service   Device driver service.
+ * @param[in] mtu       Device maximum transmission unit.
+ *
+ * @return EOK on success.
+ * @return EEXIST if the device with the different service exists.
+ * @return ENOMEM if there is not enough memory left.
+ * @return Other error codes as defined for the
+ *         netif_bind_service() function.
+ * @return Other error codes as defined for the
+ *         netif_get_addr_req() function.
+ *
  */
 static int nildummy_device_message(device_id_t device_id, services_t service,
     size_t mtu)
 {
-	nildummy_device_t *device;
-	int index;
-	int rc;
-
 	fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
-
+	
 	/* An existing device? */
-	device = nildummy_devices_find(&nildummy_globals.devices, device_id);
+	nildummy_device_t *device =
+	    nildummy_devices_find(&nildummy_globals.devices, device_id);
 	if (device) {
 		if (device->service != service) {
@@ -213,6 +209,6 @@
 	
 	/* Get hardware address */
-	rc = netif_get_addr_req(device->phone, device->device_id, &device->addr,
-	    &device->addr_data);
+	int rc = netif_get_addr_req(device->phone, device->device_id,
+	    &device->addr, &device->addr_data);
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
@@ -222,5 +218,5 @@
 	
 	/* Add to the cache */
-	index = nildummy_devices_add(&nildummy_globals.devices,
+	int index = nildummy_devices_add(&nildummy_globals.devices,
 	    device->device_id, device);
 	if (index < 0) {
@@ -240,9 +236,10 @@
 /** Return the device hardware address.
  *
- * @param[in] device_id	The device identifier.
- * @param[out] address	The device hardware address.
- * @return		 EOK on success.
- * @return		EBADMEM if the address parameter is NULL.
- * @return		ENOENT if there no such device.
+ * @param[in]  device_id Device identifier.
+ * @param[out] address   Device hardware address.
+ *
+ * @return EOK on success.
+ * @return EBADMEM if the address parameter is NULL.
+ * @return ENOENT if there no such device.
  *
  */
@@ -250,16 +247,18 @@
     measured_string_t **address)
 {
-	nildummy_device_t *device;
-
 	if (!address)
 		return EBADMEM;
 	
 	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
-	device = nildummy_devices_find(&nildummy_globals.devices, device_id);
+	
+	nildummy_device_t *device =
+	    nildummy_devices_find(&nildummy_globals.devices, device_id);
 	if (!device) {
 		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
 		return ENOENT;
 	}
+	
 	*address = device->addr;
+	
 	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
 	
@@ -269,12 +268,13 @@
 /** Return the device packet dimensions for sending.
  *
- * @param[in] device_id	The device identifier.
- * @param[out] addr_len	The minimum reserved address length.
- * @param[out] prefix	The minimum reserved prefix size.
- * @param[out] content	The maximum content size.
- * @param[out] suffix	The minimum reserved suffix size.
- * @return		EOK on success.
- * @return		EBADMEM if either one of the parameters is NULL.
- * @return		ENOENT if there is no such device.
+ * @param[in]  device_id Device identifier.
+ * @param[out] addr_len  Minimum reserved address length.
+ * @param[out] prefix    Minimum reserved prefix size.
+ * @param[out] content   Maximum content size.
+ * @param[out] suffix    Minimum reserved suffix size.
+ *
+ * @return EOK on success.
+ * @return EBADMEM if either one of the parameters is NULL.
+ * @return ENOENT if there is no such device.
  *
  */
@@ -282,17 +282,18 @@
     size_t *prefix, size_t *content, size_t *suffix)
 {
-	nildummy_device_t *device;
-
-	if (!addr_len || !prefix || !content || !suffix)
+	if ((!addr_len) || (!prefix) || (!content) || (!suffix))
 		return EBADMEM;
 	
 	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
-	device = nildummy_devices_find(&nildummy_globals.devices, device_id);
+	
+	nildummy_device_t *device =
+	    nildummy_devices_find(&nildummy_globals.devices, device_id);
 	if (!device) {
 		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
 		return ENOENT;
 	}
-
+	
 	*content = device->mtu;
+	
 	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
 	
@@ -306,15 +307,15 @@
     packet_t *packet, services_t target)
 {
-	packet_t *next;
-
 	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
+	
 	if (nildummy_globals.proto.phone) {
 		do {
-			next = pq_detach(packet);
+			packet_t *next = pq_detach(packet);
 			il_received_msg(nildummy_globals.proto.phone, device_id,
 			    packet, nildummy_globals.proto.service);
 			packet = next;
-		} while(packet);
-	}
+		} while (packet);
+	}
+	
 	fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
 	
@@ -326,9 +327,11 @@
  * Pass received packets for this service.
  *
- * @param[in] service	The module service.
- * @param[in] phone	The service phone.
- * @return		EOK on success.
- * @return		ENOENT if the service is not known.
- * @return		ENOMEM if there is not enough memory left.
+ * @param[in] service Module service.
+ * @param[in] phone   Service phone.
+ *
+ * @return EOK on success.
+ * @return ENOENT if the service is not known.
+ * @return ENOMEM if there is not enough memory left.
+ *
  */
 static int nildummy_register_message(services_t service, int phone)
@@ -347,33 +350,37 @@
 /** Send the packet queue.
  *
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The packet queue.
- * @param[in] sender	The sending module service.
- * @return		EOK on success.
- * @return		ENOENT if there no such device.
- * @return		EINVAL if the service parameter is not known.
+ * @param[in] device_id Device identifier.
+ * @param[in] packet    Packet queue.
+ * @param[in] sender    Sending module service.
+ *
+ * @return EOK on success.
+ * @return ENOENT if there no such device.
+ * @return EINVAL if the service parameter is not known.
+ *
  */
 static int nildummy_send_message(device_id_t device_id, packet_t *packet,
     services_t sender)
 {
-	nildummy_device_t *device;
-
 	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
-	device = nildummy_devices_find(&nildummy_globals.devices, device_id);
+	
+	nildummy_device_t *device =
+	    nildummy_devices_find(&nildummy_globals.devices, device_id);
 	if (!device) {
 		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
 		return ENOENT;
 	}
-
+	
 	/* Send packet queue */
 	if (packet)
 		netif_send_msg(device->phone, device_id, packet,
 		    SERVICE_NILDUMMY);
+	
 	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-	return EOK;
-}
-
-int nil_message_standalone(const char *name, ipc_callid_t callid,
-    ipc_call_t *call, ipc_call_t *answer, int *answer_count)
+	
+	return EOK;
+}
+
+int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, size_t *answer_count)
 {
 	measured_string_t *address;
@@ -391,29 +398,29 @@
 	
 	case NET_NIL_DEVICE:
-		return nildummy_device_message(IPC_GET_DEVICE(call),
-		    IPC_GET_SERVICE(call), IPC_GET_MTU(call));
+		return nildummy_device_message(IPC_GET_DEVICE(*call),
+		    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
 	
 	case NET_NIL_SEND:
 		rc = packet_translate_remote(nildummy_globals.net_phone,
-		    &packet, IPC_GET_PACKET(call));
+		    &packet, IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
-		return nildummy_send_message(IPC_GET_DEVICE(call), packet,
-		    IPC_GET_SERVICE(call));
+		return nildummy_send_message(IPC_GET_DEVICE(*call), packet,
+		    IPC_GET_SERVICE(*call));
 	
 	case NET_NIL_PACKET_SPACE:
-		rc = nildummy_packet_space_message(IPC_GET_DEVICE(call),
+		rc = nildummy_packet_space_message(IPC_GET_DEVICE(*call),
 		    &addrlen, &prefix, &content, &suffix);
 		if (rc != EOK)
 			return rc;
-		IPC_SET_ADDR(answer, addrlen);
-		IPC_SET_PREFIX(answer, prefix);
-		IPC_SET_CONTENT(answer, content);
-		IPC_SET_SUFFIX(answer, suffix);
+		IPC_SET_ADDR(*answer, addrlen);
+		IPC_SET_PREFIX(*answer, prefix);
+		IPC_SET_CONTENT(*answer, content);
+		IPC_SET_SUFFIX(*answer, suffix);
 		*answer_count = 4;
 		return EOK;
 	
 	case NET_NIL_ADDR:
-		rc = nildummy_addr_message(IPC_GET_DEVICE(call), &address);
+		rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &address);
 		if (rc != EOK)
 			return rc;
@@ -421,5 +428,5 @@
 	
 	case NET_NIL_BROADCAST_ADDR:
-		rc = nildummy_addr_message(IPC_GET_DEVICE(call), &address);
+		rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &address);
 		if (rc != EOK)
 			return rc;
@@ -427,6 +434,6 @@
 	
 	case IPC_M_CONNECT_TO_ME:
-		return nildummy_register_message(NIL_GET_PROTO(call),
-		    IPC_GET_PHONE(call));
+		return nildummy_register_message(NIL_GET_PROTO(*call),
+		    IPC_GET_PHONE(*call));
 	}
 	
@@ -434,52 +441,8 @@
 }
 
-/** Default thread for new connections.
- *
- * @param[in] iid	The initial message identifier.
- * @param[in] icall	The initial message call structure.
- */
-static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	ipc_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		int answer_count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &answer_count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = nil_module_message_standalone(NAME, callid, &call,
-		    &answer, &answer_count);
-		
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, answer_count);
-	}
-}
-
 int main(int argc, char *argv[])
 {
-	int rc;
-	
 	/* Start the module */
-	rc = nil_module_start_standalone(nil_client_connection);
-	return rc;
+	return nil_module_start(SERVICE_NILDUMMY);
 }
 
Index: uspace/srv/net/nil/nildummy/nildummy.h
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/nil/nildummy/nildummy.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -45,21 +45,29 @@
 
 /** Type definition of the dummy nil global data.
+ *
  * @see nildummy_globals
+ *
  */
 typedef struct nildummy_globals nildummy_globals_t;
 
 /** Type definition of the dummy nil device specific data.
+ *
  * @see nildummy_device
+ *
  */
 typedef struct nildummy_device nildummy_device_t;
 
 /** Type definition of the dummy nil protocol specific data.
+ *
  * @see nildummy_proto
+ *
  */
 typedef struct nildummy_proto nildummy_proto_t;
 
 /** Dummy nil device map.
- * Maps devices to the dummy nil device specific data.
+ *
+ * Map devices to the dummy nil device specific data.
  * @see device.h
+ *
  */
 DEVICE_MAP_DECLARE(nildummy_devices, nildummy_device_t);
@@ -69,12 +77,17 @@
 	/** Device identifier. */
 	device_id_t device_id;
+	
 	/** Device driver service. */
 	services_t service;
+	
 	/** Driver phone. */
 	int phone;
+	
 	/** Maximal transmission unit. */
 	size_t mtu;
+	
 	/** Actual device hardware address. */
 	measured_string_t *addr;
+	
 	/** Actual device hardware address data. */
 	uint8_t *addr_data;
@@ -85,4 +98,5 @@
 	/** Protocol service. */
 	services_t service;
+	
 	/** Protocol module phone. */
 	int phone;
@@ -93,10 +107,14 @@
 	/** Networking module phone. */
 	int net_phone;
-	/** Safety lock for devices. */
+	
+	/** Lock for devices. */
 	fibril_rwlock_t devices_lock;
+	
 	/** All known Ethernet devices. */
 	nildummy_devices_t devices;
+	
 	/** Safety lock for protocols. */
 	fibril_rwlock_t protos_lock;
+	
 	/** Default protocol. */
 	nildummy_proto_t proto;
Index: pace/srv/net/nil/nildummy/nildummy_module.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy_module.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,87 +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 nildummy
- * @{
- */
-
-/** @file
- *  Dummy network interface layer module stub.
- *  @see module.c
- */
-
-#include <async.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-
-#include <net/modules.h>
-#include <net_interface.h>
-#include <net/packet.h>
-#include <nil_local.h>
-
-#include "nildummy.h"
-
-int nil_module_start_standalone(async_client_conn_t client_connection)
-{
-	sysarg_t phonehash;
-	int rc;
-	
-	async_set_client_connection(client_connection);
-	int net_phone = net_connect_module();
-	
-	rc = pm_init();
-	if (rc != EOK)
-		return rc;
-	
-	
-	rc = nil_initialize(net_phone);
-	if (rc != EOK)
-		goto out;
-	
-	rc = ipc_connect_to_me(PHONE_NS, SERVICE_NILDUMMY, 0, 0, &phonehash);
-	if (rc != EOK)
-		goto out;
-	
-	async_manager();
-
-out:
-	pm_destroy();
-	return rc;
-}
-
-int nil_module_message_standalone(const char *name, ipc_callid_t callid,
-    ipc_call_t *call, ipc_call_t *answer, int *answer_count)
-{
-	return nil_message_standalone(name, callid, call, answer, answer_count);
-}
-
-/** @}
- */
Index: uspace/srv/net/tl/icmp/Makefile
===================================================================
--- uspace/srv/net/tl/icmp/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/tl/icmp/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -34,6 +34,5 @@
 
 SOURCES = \
-	icmp.c \
-	icmp_module.c
+	icmp.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/tl/icmp/icmp.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -33,9 +33,5 @@
 /** @file
  * ICMP module implementation.
- * @see icmp.h
- */
-
-#include "icmp.h"
-#include "icmp_module.h"
+ */
 
 #include <async.h>
@@ -45,5 +41,4 @@
 #include <stdint.h>
 #include <str.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -54,4 +49,5 @@
 #include <byteorder.h>
 #include <errno.h>
+#include <adt/hash_table.h>
 
 #include <net/socket_codes.h>
@@ -67,38 +63,35 @@
 #include <net_checksum.h>
 #include <icmp_client.h>
-#include <icmp_interface.h>
-#include <il_interface.h>
+#include <icmp_remote.h>
+#include <il_remote.h>
 #include <ip_client.h>
 #include <ip_interface.h>
 #include <net_interface.h>
-#include <tl_interface.h>
-#include <tl_local.h>
+#include <tl_remote.h>
+#include <tl_skel.h>
 #include <icmp_header.h>
 
-/** ICMP module name. */
-#define NAME	"ICMP protocol"
-
-/** 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.
+/** ICMP module name */
+#define NAME  "icmp"
+
+/** 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) \
@@ -106,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;
@@ -290,116 +324,329 @@
 	}
 	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);
-}
-
-/** Initializes the ICMP module.
- *
- * @param[in] client_connection The client connection processing function. The
- *			module skeleton propagates its own one.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- */
-int icmp_initialize(async_client_conn_t client_connection)
+	    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. 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)
+{
+	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_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_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)
+{
+	icmp_type_t type;
+	icmp_code_t code;
+	int rc;
+	
+	switch (error) {
+	case SERVICE_NONE:
+		break;
+	case SERVICE_ICMP:
+		/* Process error */
+		rc = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
+		if (rc < 0)
+			return rc;
+		
+		/* Remove the error header */
+		rc = packet_trim(packet, (size_t) rc, 0);
+		if (rc != EOK)
+			return rc;
+		
+		break;
+	default:
+		return ENOTSUP;
+	}
+	
+	/* Get rid of the IP header */
+	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;
+	
+	void *data = packet_get_data(packet);
+	if (!data)
+		return EINVAL;
+	
+	/* Get ICMP header */
+	icmp_header_t *header = (icmp_header_t *) data;
+	
+	if (header->checksum) {
+		while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
+			/*
+			 * Set the original message type on error notification.
+			 * Type swap observed in Qemu.
+			 */
+			if (error) {
+				switch (header->type) {
+				case ICMP_ECHOREPLY:
+					header->type = ICMP_ECHO;
+					continue;
+				}
+			}
+			
+			return EINVAL;
+		}
+	}
+	
+	switch (header->type) {
+	case ICMP_ECHOREPLY:
+		if (error)
+			icmp_process_echo_reply(packet, header, type, code);
+		else
+			icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
+		
+		return EOK;
+	
+	case ICMP_ECHO:
+		if (error) {
+			icmp_process_echo_reply(packet, header, type, code);
+			return EOK;
+		}
+		
+		/* Do not send a reply if disabled */
+		if (echo_replying) {
+			uint8_t *src;
+			int addrlen = packet_get_addr(packet, &src, NULL);
+			
+			/*
+			 * Set both addresses to the source one (avoid the
+			 * source address deletion before setting the
+			 * destination one).
+			 */
+			if ((addrlen > 0) && (packet_set_addr(packet, src, src,
+			    (size_t) addrlen) == EOK)) {
+				/* Send the reply */
+				icmp_send_packet(ICMP_ECHOREPLY, 0, packet,
+				    header, 0, 0, 0, 0);
+				return EOK;
+			}
+			
+			return EINVAL;
+		}
+		
+		return EPERM;
+	
+	case ICMP_DEST_UNREACH:
+	case ICMP_SOURCE_QUENCH:
+	case ICMP_REDIRECT:
+	case ICMP_ALTERNATE_ADDR:
+	case ICMP_ROUTER_ADV:
+	case ICMP_ROUTER_SOL:
+	case ICMP_TIME_EXCEEDED:
+	case ICMP_PARAMETERPROB:
+	case ICMP_CONVERSION_ERROR:
+	case ICMP_REDIRECT_MOBILE:
+	case ICMP_SKIP:
+	case ICMP_PHOTURIS:
+		ip_received_error_msg(phone_ip, -1, packet,
+		    SERVICE_IP, SERVICE_ICMP);
+		return EOK;
+	
+	default:
+		return ENOTSUP;
+	}
+}
+
+/** Process IPC messages from the IP module
+ *
+ * @param[in]     iid   Message identifier.
+ * @param[in,out] icall Message parameters.
+ *
+ */
+static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall)
+{
+	bool loop = true;
+	packet_t *packet;
+	int rc;
+	
+	while (loop) {
+		switch (IPC_GET_IMETHOD(*icall)) {
+		case NET_TL_RECEIVED:
+			rc = packet_translate_remote(phone_net, &packet,
+			    IPC_GET_PACKET(*icall));
+			if (rc == EOK) {
+				rc = icmp_process_packet(packet, IPC_GET_ERROR(*icall));
+				if (rc != EOK)
+					icmp_release(packet);
+			}
+			
+			async_answer_0(iid, (sysarg_t) rc);
+			break;
+		case IPC_M_PHONE_HUNGUP:
+			loop = false;
+			continue;
+		default:
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
+		}
+		
+		iid = async_get_call(icall);
+	}
+}
+
+/** Initialize the ICMP module.
+ *
+ * @param[in] net_phone Network module phone.
+ *
+ * @return EOK on success.
+ * @return ENOMEM if there is not enough memory left.
+ *
+ */
+int tl_initialize(int net_phone)
 {
 	measured_string_t names[] = {
@@ -416,566 +663,147 @@
 	size_t count = sizeof(names) / sizeof(measured_string_t);
 	uint8_t *data;
-	int rc;
-
-	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.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP,
-	    SERVICE_ICMP, client_connection);
-	if (icmp_globals.ip_phone < 0) {
-		fibril_rwlock_write_unlock(&icmp_globals.lock);
-		return icmp_globals.ip_phone;
-	}
-	
-	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;
 }
 
-/** Tries 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,
-    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));
-
-	/* Find the pending reply */
-	fibril_rwlock_write_lock(&icmp_globals.lock);
-	reply = icmp_replies_find(&icmp_globals.replies, reply_key);
-	if (reply) {
-		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.
- */
-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;
+/** 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;
 	
-	switch (error) {
-	case SERVICE_NONE:
-		break;
-	case SERVICE_ICMP:
-		/* Process error */
-		result = icmp_client_process_packet(packet, &type, &code, NULL,
-		    NULL);
-		if (result < 0)
-			return result;
-		length = (size_t) result;
-		/* Remove the error header */
-		rc = packet_trim(packet, length, 0);
+	*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;
-		break;
-	default:
-		return ENOTSUP;
-	}
-
-	/* Get rid of the IP header */
-	length = ip_client_header_length(packet);
-	rc = packet_trim(packet, length, 0);
-	if (rc != EOK)
+		
+		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;
-
-	length = packet_get_data_length(packet);
-	if (length <= 0)
-		return EINVAL;
-
-	if (length < ICMP_HEADER_SIZE)
-		return EINVAL;
-
-	data = packet_get_data(packet);
-	if (!data)
-		return EINVAL;
-
-	/* Get ICMP header */
-	header = (icmp_header_t *) data;
-
-	if (header->checksum) {
-		while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
-			/*
-			 * Set the original message type on error notification.
-			 * Type swap observed in Qemu.
-			 */
-			if (error) {
-				switch (header->type) {
-				case ICMP_ECHOREPLY:
-					header->type = ICMP_ECHO;
-					continue;
-				}
-			}
-			return EINVAL;
-		}
-	}
-
-	switch (header->type) {
-	case ICMP_ECHOREPLY:
-		if (error)
-			icmp_process_echo_reply(packet, header, type, code);
-		else
-			icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
-
-		return EOK;
-
-	case ICMP_ECHO:
-		if (error) {
-			icmp_process_echo_reply(packet, header, type, code);
-			return EOK;
-		}
-		
-		/* Do not send a reply if disabled */
-		if (icmp_globals.echo_replying) {
-			addrlen = packet_get_addr(packet, &src, NULL);
-
-			/*
-			 * Set both addresses to the source one (avoids the
-			 * source address deletion before setting the
-			 * destination one).
-			 */
-			if ((addrlen > 0) && (packet_set_addr(packet, src, src,
-			    (size_t) addrlen) == EOK)) {
-				/* Send the reply */
-				icmp_send_packet(ICMP_ECHOREPLY, 0, packet,
-				    header, 0, 0, 0, 0);
-				return EOK;
-			}
-
-			return EINVAL;
-		}
-
-		return EPERM;
-
-	case ICMP_DEST_UNREACH:
-	case ICMP_SOURCE_QUENCH:
-	case ICMP_REDIRECT:
-	case ICMP_ALTERNATE_ADDR:
-	case ICMP_ROUTER_ADV:
-	case ICMP_ROUTER_SOL:
-	case ICMP_TIME_EXCEEDED:
-	case ICMP_PARAMETERPROB:
-	case ICMP_CONVERSION_ERROR:
-	case ICMP_REDIRECT_MOBILE:
-	case ICMP_SKIP:
-	case ICMP_PHOTURIS:
-		ip_received_error_msg(icmp_globals.ip_phone, -1, packet,
-		    SERVICE_IP, SERVICE_ICMP);
-		return EOK;
-
-	default:
-		return ENOTSUP;
-	}
-}
-
-/** 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;
-}
-
-/** 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)
-{
-	packet_t *packet;
-	int rc;
-
-	switch (IPC_GET_IMETHOD(*call)) {
+	
 	case NET_ICMP_DEST_UNREACH:
-		rc = packet_translate_remote(icmp_globals.net_phone, &packet,
-		    IPC_GET_PACKET(call));
+		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,
-		    IPC_GET_PACKET(call));
+		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,
-		    IPC_GET_PACKET(call));
+		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,
-		    IPC_GET_PACKET(call));
+		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),
-		    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;
-	int 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 icmp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
-{
-	packet_t *packet;
-	int rc;
-
-	*answer_count = 0;
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_TL_RECEIVED:
-		rc = packet_translate_remote(icmp_globals.net_phone, &packet,
-		    IPC_GET_PACKET(call));
-		if (rc != EOK)
-			return rc;
-		return icmp_received_msg_local(IPC_GET_DEVICE(call), packet,
-		    SERVICE_ICMP, IPC_GET_ERROR(call));
-	
-	case NET_ICMP_INIT:
-		return icmp_process_client_messages(callid, * call);
-	
-	default:
-		return icmp_process_message(call);
-	}
-
+		
+		return icmp_parameter_problem(ICMP_GET_CODE(*call),
+		    ICMP_GET_POINTER(*call), packet);
+	}
+	
 	return ENOTSUP;
 }
 
-
-/** Default thread for new connections.
- *
- * @param[in] iid The initial message identifier.
- * @param[in] icall The initial message call structure.
- *
- */
-static void tl_client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	ipc_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		int answer_count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &answer_count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = tl_module_message_standalone(callid, &call, &answer,
-		    &answer_count);
-		
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, answer_count);
-	}
-}
-
-/** Starts the module.
- *
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- *			start function.
- */
 int main(int argc, char *argv[])
 {
-	int rc;
-	
 	/* Start the module */
-	rc = tl_module_start_standalone(tl_client_connection);
-	return rc;
+	return tl_module_start(SERVICE_ICMP);
 }
 
 /** @}
  */
-
Index: pace/srv/net/tl/icmp/icmp.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(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: pace/srv/net/tl/icmp/icmp_module.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp_module.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,94 +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 standalone module implementation.
- * Contains skeleton module functions mapping.
- * The functions are used by the module skeleton as module specific entry points.
- * @see module.c
- */
-
-#include "icmp.h"
-#include "icmp_module.h"
-
-#include <async.h>
-#include <stdio.h>
-#include <errno.h>
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-
-#include <net/modules.h>
-#include <net/packet.h>
-#include <net_interface.h>
-
-#include <tl_local.h>
-
-/** ICMP module global data. */
-extern icmp_globals_t icmp_globals;
-
-int tl_module_start_standalone(async_client_conn_t client_connection)
-{
-	sysarg_t phonehash;
-	int rc;
-
-	async_set_client_connection(client_connection);
-	icmp_globals.net_phone = net_connect_module();
-	if (icmp_globals.net_phone < 0)
-		return icmp_globals.net_phone;
-
-	rc = pm_init();
-	if (rc != EOK)
-		return rc;
-	
-	rc = icmp_initialize(client_connection);
-	if (rc != EOK)
-		goto out;
-
-	rc = ipc_connect_to_me(PHONE_NS, SERVICE_ICMP, 0, 0, &phonehash);
-	if (rc != EOK)
-		goto out;
-
-	async_manager();
-
-out:
-	pm_destroy();
-	return rc;
-}
-
-int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
-{
-	return icmp_message_standalone(callid, call, answer, answer_count);
-}
-
-/** @}
- */
Index: pace/srv/net/tl/icmp/icmp_module.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp_module.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,51 +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 functions.
- * The functions are used as ICMP module entry points.
- */
-
-#ifndef NET_ICMP_MODULE_H_
-#define NET_ICMP_MODULE_H_
-
-#include <async.h>
-#include <ipc/ipc.h>
-
-extern int icmp_initialize(async_client_conn_t);
-extern int icmp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
-    int *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/tl/tcp/Makefile
===================================================================
--- uspace/srv/net/tl/tcp/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/tl/tcp/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -34,6 +34,5 @@
 
 SOURCES = \
-	tcp.c \
-	tcp_module.c
+	tcp.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -36,8 +36,4 @@
  */
 
-#include "tcp.h"
-#include "tcp_header.h"
-#include "tcp_module.h"
-
 #include <assert.h>
 #include <async.h>
@@ -48,5 +44,4 @@
 #include <errno.h>
 
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -68,13 +63,16 @@
 #include <ip_interface.h>
 #include <icmp_client.h>
-#include <icmp_interface.h>
+#include <icmp_remote.h>
 #include <net_interface.h>
 #include <socket_core.h>
 #include <tl_common.h>
-#include <tl_local.h>
-#include <tl_interface.h>
+#include <tl_remote.h>
+#include <tl_skel.h>
+
+#include "tcp.h"
+#include "tcp_header.h"
 
 /** TCP module name. */
-#define NAME	"TCP protocol"
+#define NAME  "tcp"
 
 /** The TCP window default value. */
@@ -220,46 +218,4 @@
 /** TCP global data. */
 tcp_globals_t tcp_globals;
-
-/** Initializes the TCP module.
- *
- * @param[in] client_connection The client connection processing function. The
- *			module skeleton propagates its own one.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- */
-int tcp_initialize(async_client_conn_t client_connection)
-{
-	int rc;
-
-	assert(client_connection);
-
-	fibril_rwlock_initialize(&tcp_globals.lock);
-	fibril_rwlock_write_lock(&tcp_globals.lock);
-
-	tcp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
-	    ICMP_CONNECT_TIMEOUT);
-	tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
-	    SERVICE_TCP, client_connection);
-	if (tcp_globals.ip_phone < 0) {
-		fibril_rwlock_write_unlock(&tcp_globals.lock);
-		return tcp_globals.ip_phone;
-	}
-	
-	rc = socket_ports_initialize(&tcp_globals.sockets);
-	if (rc != EOK)
-		goto out;
-
-	rc = packet_dimensions_initialize(&tcp_globals.dimensions);
-	if (rc != EOK) {
-		socket_ports_destroy(&tcp_globals.sockets);
-		goto out;
-	}
-
-	tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
-
-out:
-	fibril_rwlock_write_unlock(&tcp_globals.lock);
-	return rc;
-}
 
 int tcp_received_msg(device_id_t device_id, packet_t *packet,
@@ -1247,4 +1203,11 @@
 }
 
+/** Per-connection initialization
+ *
+ */
+void tl_connection(void)
+{
+}
+
 /** Processes the TCP message.
  *
@@ -1260,11 +1223,7 @@
  * @see IS_NET_TCP_MESSAGE()
  */
-int
-tcp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
-{
-	packet_t *packet;
-	int rc;
-
+int tl_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, size_t *answer_count)
+{
 	assert(call);
 	assert(answer);
@@ -1273,16 +1232,4 @@
 	*answer_count = 0;
 	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_TL_RECEIVED:
-//		fibril_rwlock_read_lock(&tcp_globals.lock);
-		rc = packet_translate_remote(tcp_globals.net_phone, &packet,
-		    IPC_GET_PACKET(call));
-		if (rc != EOK) {
-//			fibril_rwlock_read_unlock(&tcp_globals.lock);
-			return rc;
-		}
-		rc = tcp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_TCP,
-		    IPC_GET_ERROR(call));
-//		fibril_rwlock_read_unlock(&tcp_globals.lock);
-		return rc;
 	case IPC_M_CONNECT_TO_ME:
 		return tcp_process_client_messages(callid, *call);
@@ -1323,5 +1270,5 @@
 	bool keep_on_going = true;
 	socket_cores_t local_sockets;
-	int app_phone = IPC_GET_PHONE(&call);
+	int app_phone = IPC_GET_PHONE(call);
 	struct sockaddr *addr;
 	int socket_id;
@@ -1330,5 +1277,5 @@
 	fibril_rwlock_t lock;
 	ipc_call_t answer;
-	int answer_count;
+	size_t answer_count;
 	tcp_socket_data_t *socket_data;
 	socket_core_t *socket;
@@ -1558,5 +1505,5 @@
 
 	/* Release the application phone */
-	ipc_hangup(app_phone);
+	async_hangup(app_phone);
 
 	printf("release\n");
@@ -2486,61 +2433,77 @@
 }
 
-/** Default thread for new connections.
+/** Process IPC messages from the IP module
  *
- * @param[in] iid	The initial message identifier.
- * @param[in] icall	The initial message call structure.
+ * @param[in]     iid   Message identifier.
+ * @param[in,out] icall Message parameters.
  *
  */
-static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	ipc_answer_0(iid, EOK);
-
+static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall)
+{
+	packet_t *packet;
+	int rc;
+	
 	while (true) {
-		ipc_call_t answer;
-		int answer_count;
-
-		/* Clear the answer structure */
-		refresh_answer(&answer, &answer_count);
-
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		/* Process the message */
-		int res = tl_module_message_standalone(callid, &call, &answer,
-		    &answer_count);
-
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
-			return;
-
-		/*
-		 * Answer the message 
-		 */
-		answer_call(callid, res, &answer, answer_count);
-	}
-}
-
-/** Starts the module.
+		switch (IPC_GET_IMETHOD(*icall)) {
+		case NET_TL_RECEIVED:
+			rc = packet_translate_remote(tcp_globals.net_phone, &packet,
+			    IPC_GET_PACKET(*icall));
+			if (rc == EOK)
+				rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
+				    SERVICE_TCP, IPC_GET_ERROR(*icall));
+			
+			async_answer_0(iid, (sysarg_t) rc);
+			break;
+		default:
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
+		}
+		
+		iid = async_get_call(icall);
+	}
+}
+
+/** Initialize the TCP module.
  *
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- *			start function.
+ * @param[in] net_phone Network module phone.
+ *
+ * @return EOK on success.
+ * @return ENOMEM if there is not enough memory left.
+ *
  */
-int
-main(int argc, char *argv[])
-{
-	int rc;
-
-	rc = tl_module_start_standalone(tl_client_connection);
+int tl_initialize(int net_phone)
+{
+	fibril_rwlock_initialize(&tcp_globals.lock);
+	fibril_rwlock_write_lock(&tcp_globals.lock);
+	
+	tcp_globals.net_phone = net_phone;
+	
+	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);
+	if (tcp_globals.ip_phone < 0) {
+		fibril_rwlock_write_unlock(&tcp_globals.lock);
+		return tcp_globals.ip_phone;
+	}
+	
+	int rc = socket_ports_initialize(&tcp_globals.sockets);
+	if (rc != EOK)
+		goto out;
+
+	rc = packet_dimensions_initialize(&tcp_globals.dimensions);
+	if (rc != EOK) {
+		socket_ports_destroy(&tcp_globals.sockets);
+		goto out;
+	}
+
+	tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
+
+out:
+	fibril_rwlock_write_unlock(&tcp_globals.lock);
 	return rc;
+}
+
+int main(int argc, char *argv[])
+{
+	return tl_module_start(SERVICE_TCP);
 }
 
Index: pace/srv/net/tl/tcp/tcp_module.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp_module.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,95 +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 tcp
- * @{
- */
-
-/** @file
- * TCP standalone module implementation.
- * Contains skeleton module functions mapping.
- * The functions are used by the module skeleton as module specific entry
- * points.
- * @see module.c
- */
-
-#include "tcp.h"
-#include "tcp_module.h"
-
-#include <async.h>
-#include <stdio.h>
-#include <errno.h>
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-
-#include <net/ip_protocols.h>
-#include <net/modules.h>
-#include <net/packet.h>
-#include <net_interface.h>
-
-#include <ip_interface.h>
-#include <tl_local.h>
-
-/** TCP module global data. */
-extern tcp_globals_t tcp_globals;
-
-int tl_module_start_standalone(async_client_conn_t client_connection)
-{
-	sysarg_t phonehash;
-	int rc;
-
-	async_set_client_connection(client_connection);
-	tcp_globals.net_phone = net_connect_module();
-
-	rc = pm_init();
-	if (rc != EOK)
-		return rc;
-
-	rc = tcp_initialize(client_connection);
-	if (rc != EOK)
-		goto out;
-
-	rc = ipc_connect_to_me(PHONE_NS, SERVICE_TCP, 0, 0, &phonehash);
-	if (rc != EOK)
-		goto out;
-	
-	async_manager();
-	
-out:
-	pm_destroy();
-	return rc;
-}
-
-int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
-{
-	return tcp_message_standalone(callid, call, answer, answer_count);
-}
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/tcp_module.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_module.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,51 +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 tcp
- * @{
- */
-
-/** @file
- * TCP module functions.
- * The functions are used as TCP module entry points.
- */
-
-#ifndef NET_TCP_MODULE_H_
-#define NET_TCP_MODULE_H_
-
-#include <async.h>
-#include <ipc/ipc.h>
-
-extern int tcp_initialize(async_client_conn_t);
-extern int tcp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
-    int *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/tl/udp/Makefile
===================================================================
--- uspace/srv/net/tl/udp/Makefile	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/tl/udp/Makefile	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -34,6 +34,5 @@
 
 SOURCES = \
-	udp.c \
-	udp_module.c
+	udp.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/net/tl/udp/udp.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -36,13 +36,8 @@
  */
 
-#include "udp.h"
-#include "udp_header.h"
-#include "udp_module.h"
-
 #include <async.h>
 #include <fibril_synch.h>
 #include <malloc.h>
 #include <stdio.h>
-#include <ipc/ipc.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -65,13 +60,16 @@
 #include <ip_interface.h>
 #include <icmp_client.h>
-#include <icmp_interface.h>
+#include <icmp_remote.h>
 #include <net_interface.h>
 #include <socket_core.h>
 #include <tl_common.h>
-#include <tl_local.h>
-#include <tl_interface.h>
+#include <tl_remote.h>
+#include <tl_skel.h>
+
+#include "udp.h"
+#include "udp_header.h"
 
 /** UDP module name. */
-#define NAME	"UDP protocol"
+#define NAME  "udp"
 
 /** Default UDP checksum computing. */
@@ -92,95 +90,4 @@
 /** UDP global data.  */
 udp_globals_t udp_globals;
-
-/** Initializes the UDP module.
- *
- * @param[in] client_connection The client connection processing function. The
- *			module skeleton propagates its own one.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- */
-int udp_initialize(async_client_conn_t client_connection)
-{
-	measured_string_t names[] = {
-		{
-			(uint8_t *) "UDP_CHECKSUM_COMPUTING",
-			22
-		},
-		{
-			(uint8_t *) "UDP_AUTOBINDING",
-			15
-		}
-	};
-	measured_string_t *configuration;
-	size_t count = sizeof(names) / sizeof(measured_string_t);
-	uint8_t *data;
-	int rc;
-
-	fibril_rwlock_initialize(&udp_globals.lock);
-	fibril_rwlock_write_lock(&udp_globals.lock);
-
-	udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
-	    ICMP_CONNECT_TIMEOUT);
-	
-	udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
-	    SERVICE_UDP, client_connection);
-	if (udp_globals.ip_phone < 0) {
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return udp_globals.ip_phone;
-	}
-
-	/* Read default packet dimensions */
-	rc = ip_packet_size_req(udp_globals.ip_phone, -1,
-	    &udp_globals.packet_dimension);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	rc = socket_ports_initialize(&udp_globals.sockets);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	rc = packet_dimensions_initialize(&udp_globals.dimensions);
-	if (rc != EOK) {
-		socket_ports_destroy(&udp_globals.sockets);
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
-	udp_globals.packet_dimension.content -= sizeof(udp_header_t);
-	udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
-
-	udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
-	udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
-
-	/* Get configuration */
-	configuration = &names[0];
-	rc = net_get_conf_req(udp_globals.net_phone, &configuration, count,
-	    &data);
-	if (rc != EOK) {
-		socket_ports_destroy(&udp_globals.sockets);
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	if (configuration) {
-		if (configuration[0].value)
-			udp_globals.checksum_computing =
-			    (configuration[0].value[0] == 'y');
-		
-		if (configuration[1].value)
-			udp_globals.autobinding =
-			    (configuration[1].value[0] == 'y');
-
-		net_free_settings(configuration, data);
-	}
-
-	fibril_rwlock_write_unlock(&udp_globals.lock);
-	return EOK;
-}
 
 /** Releases the packet and returns the result.
@@ -426,4 +333,126 @@
 }
 
+/** Process IPC messages from the IP module
+ *
+ * @param[in]     iid   Message identifier.
+ * @param[in,out] icall Message parameters.
+ *
+ */
+static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall)
+{
+	packet_t *packet;
+	int rc;
+	
+	while (true) {
+		switch (IPC_GET_IMETHOD(*icall)) {
+		case NET_TL_RECEIVED:
+			rc = packet_translate_remote(udp_globals.net_phone, &packet,
+			    IPC_GET_PACKET(*icall));
+			if (rc == EOK)
+				rc = udp_received_msg(IPC_GET_DEVICE(*icall), packet,
+				    SERVICE_UDP, IPC_GET_ERROR(*icall));
+			
+			async_answer_0(iid, (sysarg_t) rc);
+			break;
+		default:
+			async_answer_0(iid, (sysarg_t) ENOTSUP);
+		}
+		
+		iid = async_get_call(icall);
+	}
+}
+
+/** Initialize the UDP module.
+ *
+ * @param[in] net_phone Network module phone.
+ *
+ * @return EOK on success.
+ * @return ENOMEM if there is not enough memory left.
+ *
+ */
+int tl_initialize(int net_phone)
+{
+	measured_string_t names[] = {
+		{
+			(uint8_t *) "UDP_CHECKSUM_COMPUTING",
+			22
+		},
+		{
+			(uint8_t *) "UDP_AUTOBINDING",
+			15
+		}
+	};
+	measured_string_t *configuration;
+	size_t count = sizeof(names) / sizeof(measured_string_t);
+	uint8_t *data;
+	
+	fibril_rwlock_initialize(&udp_globals.lock);
+	fibril_rwlock_write_lock(&udp_globals.lock);
+	
+	udp_globals.net_phone = net_phone;
+	
+	udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
+	
+	udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
+	    SERVICE_UDP, udp_receiver);
+	if (udp_globals.ip_phone < 0) {
+		fibril_rwlock_write_unlock(&udp_globals.lock);
+		return udp_globals.ip_phone;
+	}
+	
+	/* Read default packet dimensions */
+	int rc = ip_packet_size_req(udp_globals.ip_phone, -1,
+	    &udp_globals.packet_dimension);
+	if (rc != EOK) {
+		fibril_rwlock_write_unlock(&udp_globals.lock);
+		return rc;
+	}
+	
+	rc = socket_ports_initialize(&udp_globals.sockets);
+	if (rc != EOK) {
+		fibril_rwlock_write_unlock(&udp_globals.lock);
+		return rc;
+	}
+	
+	rc = packet_dimensions_initialize(&udp_globals.dimensions);
+	if (rc != EOK) {
+		socket_ports_destroy(&udp_globals.sockets);
+		fibril_rwlock_write_unlock(&udp_globals.lock);
+		return rc;
+	}
+	
+	udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
+	udp_globals.packet_dimension.content -= sizeof(udp_header_t);
+	udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
+
+	udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
+	udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
+
+	/* Get configuration */
+	configuration = &names[0];
+	rc = net_get_conf_req(udp_globals.net_phone, &configuration, count,
+	    &data);
+	if (rc != EOK) {
+		socket_ports_destroy(&udp_globals.sockets);
+		fibril_rwlock_write_unlock(&udp_globals.lock);
+		return rc;
+	}
+	
+	if (configuration) {
+		if (configuration[0].value)
+			udp_globals.checksum_computing =
+			    (configuration[0].value[0] == 'y');
+		
+		if (configuration[1].value)
+			udp_globals.autobinding =
+			    (configuration[1].value[0] == 'y');
+
+		net_free_settings(configuration, data);
+	}
+
+	fibril_rwlock_write_unlock(&udp_globals.lock);
+	return EOK;
+}
+
 /** Sends data from the socket to the remote address.
  *
@@ -707,5 +736,5 @@
 	bool keep_on_going = true;
 	socket_cores_t local_sockets;
-	int app_phone = IPC_GET_PHONE(&call);
+	int app_phone = IPC_GET_PHONE(call);
 	struct sockaddr *addr;
 	int socket_id;
@@ -713,5 +742,5 @@
 	size_t size;
 	ipc_call_t answer;
-	int answer_count;
+	size_t answer_count;
 	packet_dimension_t *packet_dimension;
 
@@ -838,5 +867,5 @@
 
 	/* Release the application phone */
-	ipc_hangup(app_phone);
+	async_hangup(app_phone);
 
 	/* Release all local sockets */
@@ -845,4 +874,11 @@
 
 	return res;
+}
+
+/** Per-connection initialization
+ *
+ */
+void tl_connection(void)
+{
 }
 
@@ -860,22 +896,12 @@
  * @see IS_NET_UDP_MESSAGE()
  */
-int udp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
-{
-	packet_t *packet;
-	int rc;
-
+int tl_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_TL_RECEIVED:
-		rc = packet_translate_remote(udp_globals.net_phone, &packet,
-		    IPC_GET_PACKET(call));
-		if (rc != EOK)
-			return rc;
-		return udp_received_msg(IPC_GET_DEVICE(call), packet,
-		    SERVICE_UDP, IPC_GET_ERROR(call));
 	case IPC_M_CONNECT_TO_ME:
-		return udp_process_client_messages(callid, * call);
+		return udp_process_client_messages(callid, *call);
 	}
 
@@ -883,58 +909,8 @@
 }
 
-/** Default thread for new connections.
- *
- * @param[in] iid	The initial message identifier.
- * @param[in] icall	The initial message call structure.
- */
-static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	ipc_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		int answer_count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &answer_count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = tl_module_message_standalone(callid, &call, &answer,
-		    &answer_count);
-		
-		/*
-		 * End if told to either by the message or the processing
-		 * result.
-		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, answer_count);
-	}
-}
-
-/** Starts the module.
- *
- * @return		EOK on success.
- * @return		Other error codes as defined for each specific module
- *			start function.
- */
 int main(int argc, char *argv[])
 {
-	int rc;
-	
 	/* Start the module */
-	rc = tl_module_start_standalone(tl_client_connection);
-	return rc;
+	return tl_module_start(SERVICE_UDP);
 }
 
Index: pace/srv/net/tl/udp/udp_module.c
===================================================================
--- uspace/srv/net/tl/udp/udp_module.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,95 +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 udp
- * @{
- */
-
-/** @file
- * UDP standalone module implementation.
- * Contains skeleton module functions mapping.
- * The functions are used by the module skeleton as module specific entry
- * points.
- * @see module.c
- */
-
-#include "udp.h"
-#include "udp_module.h"
-
-#include <async.h>
-#include <stdio.h>
-#include <errno.h>
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-
-#include <net/modules.h>
-#include <net/packet.h>
-
-#include <net_interface.h>
-#include <tl_local.h>
-
-/** UDP module global data. */
-extern udp_globals_t udp_globals;
-
-int tl_module_start_standalone(async_client_conn_t client_connection)
-{
-	sysarg_t phonehash;
-	int rc;
-
-	async_set_client_connection(client_connection);
-	udp_globals.net_phone = net_connect_module();
-	if (udp_globals.net_phone < 0)
-		return udp_globals.net_phone;
-	
-	rc = pm_init();
-	if (rc != EOK)
-		return EOK;
-		
-	rc = udp_initialize(client_connection);
-	if (rc != EOK)
-		goto out;
-	
-	rc = ipc_connect_to_me(PHONE_NS, SERVICE_UDP, 0, 0, &phonehash);
-	if (rc != EOK)
-		goto out;
-
-	async_manager();
-
-out:
-	pm_destroy();
-	return rc;
-}
-
-int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
-{
-	return udp_message_standalone(callid, call, answer, answer_count);
-}
-
-/** @}
- */
Index: pace/srv/net/tl/udp/udp_module.h
===================================================================
--- uspace/srv/net/tl/udp/udp_module.h	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ 	(revision )
@@ -1,51 +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 udp
- * @{
- */
-
-/** @file
- * UDP module functions.
- * The functions are used as UDP module entry points.
- */
-
-#ifndef NET_UDP_MODULE_H_
-#define NET_UDP_MODULE_H_
-
-#include <async.h>
-#include <ipc/ipc.h>
-
-extern int udp_initialize(async_client_conn_t);
-extern int udp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
-    int *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/ns/clonable.c
===================================================================
--- uspace/srv/ns/clonable.c	(revision 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/ns/clonable.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/ns/clonable.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/ns/ns.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/ns/service.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/ns/service.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/ns/task.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/ns/task.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/taskmon/taskmon.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/vfs/vfs.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/vfs/vfs.h	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/vfs/vfs_file.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/vfs/vfs_lookup.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/vfs/vfs_ops.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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 22027b6e7981eafebc4220c771cc114cfcc00c1f)
+++ uspace/srv/vfs/vfs_register.c	(revision 8b5690f2670aee6dddfa3127ce14232d1d21555d)
@@ -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);
