Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ boot/Makefile.common	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -98,6 +98,5 @@
 	$(USPACE_PATH)/srv/fs/fat/fat \
 	$(USPACE_PATH)/srv/taskmon/taskmon \
-	$(USPACE_PATH)/srv/hw/netif/dp8390/dp8390 \
-	$(USPACE_PATH)/srv/hw/bus/usb/hcd/virtual/vhcd \
+	$(USPACE_PATH)/srv/hw/netif/ne2000/ne2000 \
 	$(USPACE_PATH)/srv/net/netif/lo/lo \
 	$(USPACE_PATH)/srv/net/nil/eth/eth \
@@ -133,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 \
Index: kernel/arch/amd64/include/interrupt.h
===================================================================
--- kernel/arch/amd64/include/interrupt.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/arch/amd64/include/interrupt.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/arch/amd64/src/amd64.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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/ia32/include/interrupt.h
===================================================================
--- kernel/arch/ia32/include/interrupt.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/arch/ia32/include/interrupt.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/arch/ia32/src/ia32.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/arch/ia64/include/interrupt.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/arch/ia64/src/ia64.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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/generic/include/ddi/ddi.h
===================================================================
--- kernel/generic/include/ddi/ddi.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/generic/include/ddi/ddi.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -54,5 +54,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);
 
 /*
Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/generic/include/syscall/syscall.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -82,5 +82,4 @@
 	SYS_PHYSMEM_MAP,
 	SYS_IOSPACE_ENABLE,
-	SYS_INTERRUPT_ENABLE,
 	
 	SYS_SYSINFO_GET_TAG,
Index: kernel/generic/src/ddi/ddi.c
===================================================================
--- kernel/generic/src/ddi/ddi.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/generic/src/ddi/ddi.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -258,34 +258,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/mm/slab.c
===================================================================
--- kernel/generic/src/mm/slab.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/generic/src/mm/slab.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ kernel/generic/src/syscall/syscall.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -171,5 +171,4 @@
 	(syshandler_t) sys_physmem_map,
 	(syshandler_t) sys_iospace_enable,
-	(syshandler_t) sys_interrupt_enable,
 	
 	/* Sysinfo syscalls */
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -82,5 +82,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/app/trace/syscalls.c
===================================================================
--- uspace/app/trace/syscalls.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/app/trace/syscalls.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -73,5 +73,4 @@
     [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_SYSINFO_GET_TAG] = { "sysinfo_get_tag",		2,	V_INTEGER },
Index: uspace/app/usbinfo/dump.c
===================================================================
--- uspace/app/usbinfo/dump.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/app/usbinfo/dump.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -45,4 +45,5 @@
 
 #include "usbinfo.h"
+#include <usb/dp.h>
 
 #define INDENT "  "
@@ -125,4 +126,83 @@
 }
 
+static void dump_tree_descriptor(uint8_t *descriptor, size_t depth)
+{
+	if (descriptor == NULL) {
+		return;
+	}
+	while (depth > 0) {
+		printf("  ");
+		depth--;
+	}
+	int type = (int) *(descriptor + 1);
+	const char *name = "unknown";
+	switch (type) {
+#define _TYPE(descriptor_type) \
+		case USB_DESCTYPE_##descriptor_type: name = #descriptor_type; break
+		_TYPE(DEVICE);
+		_TYPE(CONFIGURATION);
+		_TYPE(STRING);
+		_TYPE(INTERFACE);
+		_TYPE(ENDPOINT);
+		_TYPE(HID);
+		_TYPE(HID_REPORT);
+		_TYPE(HID_PHYSICAL);
+		_TYPE(HUB);
+#undef _TYPE
+	}
+	printf("0x%02x (%s)\n", type, name);
+}
+
+static void dump_tree_internal(usb_dp_parser_t *parser, usb_dp_parser_data_t *data,
+    uint8_t *root, size_t depth)
+{
+	if (root == NULL) {
+		return;
+	}
+	dump_tree_descriptor(root, depth);
+	uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
+	do {
+		dump_tree_internal(parser, data, child, depth + 1);
+		child = usb_dp_get_sibling_descriptor(parser, data, root, child);
+	} while (child != NULL);
+}
+
+static void dump_tree(usb_dp_parser_t *parser, usb_dp_parser_data_t *data)
+{
+	uint8_t *ptr = data->data;
+	printf("Descriptor tree:\n");
+	dump_tree_internal(parser, data, ptr, 1);
+}
+
+#define NESTING(parentname, childname) \
+	{ \
+		.child = USB_DESCTYPE_##childname, \
+		.parent = USB_DESCTYPE_##parentname, \
+	}
+#define LAST_NESTING { -1, -1 }
+
+static usb_dp_descriptor_nesting_t descriptor_nesting[] = {
+	NESTING(CONFIGURATION, INTERFACE),
+	NESTING(INTERFACE, ENDPOINT),
+	NESTING(INTERFACE, HUB),
+	NESTING(INTERFACE, HID),
+	NESTING(HID, HID_REPORT),
+	LAST_NESTING
+};
+
+static usb_dp_parser_t parser = {
+	.nesting = descriptor_nesting
+};
+
+void dump_descriptor_tree(uint8_t *descriptors, size_t length)
+{
+	usb_dp_parser_data_t data = {
+		.data = descriptors,
+		.size = length,
+		.arg = NULL
+	};
+
+	dump_tree(&parser, &data);
+}
 
 /** @}
Index: uspace/app/usbinfo/info.c
===================================================================
--- uspace/app/usbinfo/info.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/app/usbinfo/info.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -112,4 +112,7 @@
 	    full_config_descriptor, config_descriptor.total_length);
 
+	dump_descriptor_tree(full_config_descriptor,
+	    config_descriptor.total_length);
+
 	return EOK;
 }
Index: uspace/app/usbinfo/usbinfo.h
===================================================================
--- uspace/app/usbinfo/usbinfo.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/app/usbinfo/usbinfo.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -50,4 +50,5 @@
     usb_standard_configuration_descriptor_t *);
 int dump_device(int, usb_address_t);
+void dump_descriptor_tree(uint8_t *, size_t);
 
 static inline void internal_error(int err)
Index: uspace/doc/doxygroups.h
===================================================================
--- uspace/doc/doxygroups.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/doc/doxygroups.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/drv/ns8250/ns8250.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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. */
Index: uspace/lib/c/generic/ddi.c
===================================================================
--- uspace/lib/c/generic/ddi.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/c/generic/ddi.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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.
  *
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/c/generic/devman.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -79,10 +79,11 @@
 		}
 		
-		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);
Index: uspace/lib/c/include/ddi.h
===================================================================
--- uspace/lib/c/include/ddi.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/c/include/ddi.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -42,6 +42,4 @@
 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);
 
 #endif
Index: uspace/lib/c/include/ipc/il.h
===================================================================
--- uspace/lib/c/include/ipc/il.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/c/include/ipc/il.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -33,5 +33,5 @@
 /** @file
  * Internetwork layer modules messages.
- * @see il_interface.h
+ * @see il_remote.h
  * @see ip_interface.h
  */
@@ -45,28 +45,18 @@
 /** 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;
 
Index: uspace/lib/c/include/ipc/ip.h
===================================================================
--- uspace/lib/c/include/ipc/ip.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/c/include/ipc/ip.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -47,8 +47,13 @@
 /** 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.
@@ -65,5 +70,15 @@
 	 * @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;
 
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/c/include/ipc/services.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -54,5 +54,5 @@
 	SERVICE_NETWORKING,
 	SERVICE_LO,
-	SERVICE_DP8390,
+	SERVICE_NE2000,
 	SERVICE_ETHERNET,
 	SERVICE_NILDUMMY,
Index: uspace/lib/net/Makefile
===================================================================
--- uspace/lib/net/Makefile	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/net/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -43,5 +43,7 @@
 	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/protocol_map.c
===================================================================
--- uspace/lib/net/generic/protocol_map.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/net/generic/protocol_map.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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: pace/lib/net/il/il_interface.c
===================================================================
--- uspace/lib/net/il/il_interface.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/net/il/il_remote.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/net/il/il_skel.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -0,0 +1,130 @@
+/*
+ * 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.
+	 */
+	ipc_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;
+	
+	sysarg_t phonehash;
+	rc = ipc_connect_to_me(PHONE_NS, service, 0, 0, &phonehash);
+	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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/net/il/ip_remote.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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);
 }
@@ -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: pace/lib/net/include/il_interface.h
===================================================================
--- uspace/lib/net/include/il_interface.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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, size_t *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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/net/include/il_remote.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/net/include/il_skel.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -0,0 +1,84 @@
+/*
+ * 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/ipc.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/nil_interface.h
===================================================================
--- uspace/lib/net/include/nil_interface.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 *, size_t *);
-
-/** 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 *, size_t *);
-
-/** 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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/net/include/nil_remote.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/net/include/nil_skel.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -0,0 +1,123 @@
+/*
+ * 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/ipc.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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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_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 *, size_t *);
-
-/** 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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/net/include/tl_remote.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/net/include/tl_skel.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -0,0 +1,84 @@
+/*
+ * 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/ipc.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);
+
+/** 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_module_message(ipc_callid_t, ipc_call_t *,
+    ipc_call_t *, size_t *);
+
+extern int tl_module_start(int);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/net/netif/netif_skel.c
===================================================================
--- uspace/lib/net/netif/netif_skel.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/net/netif/netif_skel.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -33,5 +33,5 @@
 /** @file
  * Network interface module skeleton implementation.
- * @see netif.h
+ * @see netif_skel.h
  */
 
@@ -52,6 +52,6 @@
 #include <adt/measured_strings.h>
 #include <net/device.h>
-#include <nil_interface.h>
 #include <netif_skel.h>
+#include <nil_remote.h>
 
 DEVICE_MAP_IMPLEMENT(netif_device_map, netif_device_t);
@@ -130,6 +130,6 @@
 	if (result > NETIF_NULL) {
 		int phone = device->nil_phone;
+		nil_device_state_msg(phone, device_id, result);
 		fibril_rwlock_write_unlock(&netif_globals.lock);
-		nil_device_state_msg(phone, device_id, result);
 		return EOK;
 	}
@@ -166,6 +166,6 @@
 	if (result > NETIF_NULL) {
 		int phone = device->nil_phone;
+		nil_device_state_msg(phone, device_id, result);
 		fibril_rwlock_write_unlock(&netif_globals.lock);
-		nil_device_state_msg(phone, device_id, result);
 		return EOK;
 	}
Index: uspace/lib/net/nil/nil_remote.c
===================================================================
--- uspace/lib/net/nil/nil_remote.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/net/nil/nil_remote.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/net/nil/nil_skel.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -0,0 +1,130 @@
+/*
+ * 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.
+	 */
+	ipc_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;
+	
+	sysarg_t phonehash;
+	rc = ipc_connect_to_me(PHONE_NS, service, 0, 0, &phonehash);
+	if (rc != EOK)
+		goto out;
+	
+	async_manager();
+	
+out:
+	pm_destroy();
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/net/tl/tl_common.c
===================================================================
--- uspace/lib/net/tl/tl_common.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/net/tl/tl_common.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -42,5 +42,5 @@
 #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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/net/tl/tl_remote.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/net/tl/tl_skel.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -0,0 +1,130 @@
+/*
+ * 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.
+	 */
+	ipc_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 = tl_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 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;
+	
+	sysarg_t phonehash;
+	rc = ipc_connect_to_me(PHONE_NS, service, 0, 0, &phonehash);
+	if (rc != EOK)
+		goto out;
+	
+	async_manager();
+	
+out:
+	pm_destroy();
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/usb/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -36,4 +36,5 @@
 	src/class.c \
 	src/debug.c \
+	src/dp.c \
 	src/drvpsync.c \
 	src/hcdhubd.c \
Index: uspace/lib/usb/include/usb/classes/hidparser.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidparser.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/usb/include/usb/classes/hidparser.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -38,7 +38,24 @@
 #include <stdint.h>
 
+/**
+ * Description of report items
+ */
+typedef struct {
+
+	uint8_t usage_min;
+	uint8_t usage_max;
+	uint8_t logical_min;
+	uint8_t logical_max;
+	uint8_t size;
+	uint8_t count;
+	uint8_t offset;
+
+} usb_hid_report_item_t;
+
+
 /** HID report parser structure. */
 typedef struct {
 } usb_hid_report_parser_t;
+
 
 /** HID parser callbacks for IN items. */
@@ -50,6 +67,21 @@
 	 * @param arg Custom argument.
 	 */
-	void (*keyboard)(const uint16_t *key_codes, size_t count, void *arg);
+	void (*keyboard)(const uint8_t *key_codes, size_t count, const uint8_t modifiers, void *arg);
 } usb_hid_report_in_callbacks_t;
+
+#define USB_HID_BOOT_KEYBOARD_NUM_LOCK		0x01
+#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK		0x02
+#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK	0x04
+#define USB_HID_BOOT_KEYBOARD_COMPOSE		0x08
+#define USB_HID_BOOT_KEYBOARD_KANA			0x10
+
+/*
+ * modifiers definitions
+ */
+
+int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
+	const usb_hid_report_in_callbacks_t *callbacks, void *arg);
+
+int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
 
 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser, 
@@ -60,4 +92,7 @@
     const usb_hid_report_in_callbacks_t *callbacks, void *arg);
 
+
+int usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
+
 #endif
 /**
Index: uspace/lib/usb/include/usb/dp.h
===================================================================
--- uspace/lib/usb/include/usb/dp.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/usb/include/usb/dp.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libusb
+ * @{
+ */
+/** @file
+ * @brief USB descriptor parser.
+ */
+#ifndef LIBUSB_DP_H_
+#define LIBUSB_DP_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+
+typedef struct {
+	int child;
+	int parent;
+} usb_dp_descriptor_nesting_t;
+
+typedef struct {
+	usb_dp_descriptor_nesting_t *nesting;
+} usb_dp_parser_t;
+
+typedef struct {
+	uint8_t *data;
+	size_t size;
+	void *arg;
+} usb_dp_parser_data_t;
+
+uint8_t *usb_dp_get_nested_descriptor(usb_dp_parser_t *,
+    usb_dp_parser_data_t *, uint8_t *);
+uint8_t *usb_dp_get_sibling_descriptor(usb_dp_parser_t *,
+    usb_dp_parser_data_t *, uint8_t *, uint8_t *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/dp.c
===================================================================
--- uspace/lib/usb/src/dp.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/lib/usb/src/dp.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libusb
+ * @{
+ */
+/**
+ * @file
+ * @brief USB descriptor parser (implementation).
+ */
+#include <stdio.h>
+#include <str_error.h>
+#include <errno.h>
+#include <usb/usbdrv.h>
+#include <bool.h>
+#include <usb/dp.h>
+
+/** Tells whether pointer points inside descriptor data.
+ *
+ * @param data Parser data.
+ * @param ptr Pointer to be verified.
+ * @return Whether @ptr points inside <code>data->data</code> field.
+ */
+static bool is_valid_descriptor_pointer(usb_dp_parser_data_t *data,
+    uint8_t *ptr)
+{
+	if (ptr == NULL) {
+		return false;
+	}
+
+	if (ptr < data->data) {
+		return false;
+	}
+
+	if ((size_t)(ptr - data->data) >= data->size) {
+		return false;
+	}
+
+	return true;
+}
+
+/** Get next descriptor regardless of the nesting.
+ *
+ * @param data Parser data.
+ * @param current Pointer to current descriptor.
+ * @return Pointer to start of next descriptor.
+ * @retval NULL Invalid input or no next descriptor.
+ */
+static uint8_t *get_next_descriptor(usb_dp_parser_data_t *data,
+    uint8_t *current)
+{
+	assert(is_valid_descriptor_pointer(data, current));
+
+	uint8_t current_length = *current;
+	uint8_t *next = current + current_length;
+
+	if (!is_valid_descriptor_pointer(data, next)) {
+		return NULL;
+	}
+
+	return next;
+}
+
+/** Get descriptor type.
+ *
+ * @see usb_descriptor_type_t
+ *
+ * @param data Parser data.
+ * @param start Pointer to start of the descriptor.
+ * @return Descriptor type.
+ * @retval -1 Invalid input.
+ */
+static int get_descriptor_type(usb_dp_parser_data_t *data, uint8_t *start)
+{
+	if (start == NULL) {
+		return -1;
+	}
+
+	start++;
+	if (!is_valid_descriptor_pointer(data, start)) {
+		return -1;
+	} else {
+		return (int) (*start);
+	}
+}
+
+/** Tells whether descriptors could be nested.
+ *
+ * @param parser Parser.
+ * @param child Child descriptor type.
+ * @param parent Parent descriptor type.
+ * @return Whether @p child could be child of @p parent.
+ */
+static bool is_nested_descriptor_type(usb_dp_parser_t *parser,
+    int child, int parent)
+{
+	usb_dp_descriptor_nesting_t *nesting = parser->nesting;
+	while ((nesting->child > 0) && (nesting->parent > 0)) {
+		if ((nesting->child == child) && (nesting->parent == parent)) {
+			return true;
+		}
+		nesting++;
+	}
+	return false;
+}
+
+/** Tells whether descriptors could be nested.
+ *
+ * @param parser Parser.
+ * @param data Parser data.
+ * @param child Pointer to child descriptor.
+ * @param parent Pointer to parent descriptor.
+ * @return Whether @p child could be child of @p parent.
+ */
+static bool is_nested_descriptor(usb_dp_parser_t *parser,
+    usb_dp_parser_data_t *data, uint8_t *child, uint8_t *parent)
+{
+	return is_nested_descriptor_type(parser,
+	    get_descriptor_type(data, child),
+	    get_descriptor_type(data, parent));
+}
+
+/** Find first nested descriptor of given parent.
+ *
+ * @param parser Parser.
+ * @param data Parser data.
+ * @param parent Pointer to the beginning of parent descriptor.
+ * @return Pointer to the beginning of the first nested (child) descriptor.
+ * @retval NULL No child descriptor found.
+ * @retval NULL Invalid input.
+ */
+uint8_t *usb_dp_get_nested_descriptor(usb_dp_parser_t *parser,
+    usb_dp_parser_data_t *data, uint8_t *parent)
+{
+	if (!is_valid_descriptor_pointer(data, parent)) {
+		return NULL;
+	}
+
+	uint8_t *next = get_next_descriptor(data, parent);
+	if (next == NULL) {
+		return NULL;
+	}
+
+	if (is_nested_descriptor(parser, data, next, parent)) {
+		return next;
+	} else {
+		return NULL;
+	}
+}
+
+/** Skip all nested descriptors.
+ *
+ * @param parser Parser.
+ * @param data Parser data.
+ * @param parent Pointer to the beginning of parent descriptor.
+ * @return Pointer to first non-child descriptor.
+ * @retval NULL No next descriptor.
+ * @retval NULL Invalid input.
+ */
+static uint8_t *skip_nested_descriptors(usb_dp_parser_t *parser,
+    usb_dp_parser_data_t *data, uint8_t *parent)
+{
+	uint8_t *child = usb_dp_get_nested_descriptor(parser, data, parent);
+	if (child == NULL) {
+		return get_next_descriptor(data, parent);
+	}
+	uint8_t *next_child = skip_nested_descriptors(parser, data, child);
+	while (is_nested_descriptor(parser, data, next_child, parent)) {
+		next_child = skip_nested_descriptors(parser, data, next_child);
+	}
+
+	return next_child;
+}
+
+/** Get sibling descriptor.
+ *
+ * @param parser Parser.
+ * @param data Parser data.
+ * @param parent Pointer to common parent descriptor.
+ * @param sibling Left sibling.
+ * @return Pointer to first right sibling of @p sibling.
+ * @retval NULL No sibling exist.
+ * @retval NULL Invalid input.
+ */
+uint8_t *usb_dp_get_sibling_descriptor(usb_dp_parser_t *parser,
+    usb_dp_parser_data_t *data, uint8_t *parent, uint8_t *sibling)
+{
+	if (!is_valid_descriptor_pointer(data, parent)
+	    || !is_valid_descriptor_pointer(data, sibling)) {
+		return NULL;
+	}
+
+	uint8_t *possible_sibling = skip_nested_descriptors(parser, data, sibling);
+	if (possible_sibling == NULL) {
+		return NULL;
+	}
+
+	int parent_type = get_descriptor_type(data, parent);
+	int possible_sibling_type = get_descriptor_type(data, possible_sibling);
+	if (is_nested_descriptor_type(parser, possible_sibling_type, parent_type)) {
+		return possible_sibling;
+	} else {
+		return NULL;
+	}
+}
+
+
+/** @}
+ */
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/usb/src/hidparser.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -40,5 +40,4 @@
  * @param parser Opaque HID report parser structure.
  * @param data Data describing the report.
- * @param size Size of the descriptor in bytes.
  * @return Error code.
  */
@@ -55,5 +54,4 @@
  * @param parser Opaque HID report parser structure.
  * @param data Data for the report.
- * @param size Size of the data in bytes.
  * @param callbacks Callbacks for report actions.
  * @param arg Custom argument (passed through to the callbacks).
@@ -66,7 +64,10 @@
 	int i;
 	
-	// TODO: parse report
+	/* main parsing loop */
+	while(0){
+	}
 	
-	uint16_t keys[6];
+	
+	uint8_t keys[6];
 	
 	for (i = 0; i < 6; ++i) {
@@ -74,6 +75,17 @@
 	}
 	
-	callbacks->keyboard(keys, 6, arg);
-	
+	callbacks->keyboard(keys, 6, 0, arg);
+
+	return EOK;
+}
+
+/** Free the HID report parser structure 
+ *
+ * @param parser Opaque HID report parser structure
+ * @return Error code
+ */
+int usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
+{
+
 	return EOK;
 }
@@ -81,4 +93,64 @@
 
 /**
+ * Parse input report.
+ *
+ * @param data Data for report
+ * @param size Size of report
+ * @param callbacks Callbacks for report actions
+ * @param arg Custom arguments
+ *
+ * @return Error code
+ */
+int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
+	const usb_hid_report_in_callbacks_t *callbacks, void *arg)
+{
+	int i;
+	usb_hid_report_item_t item;
+
+	/* fill item due to the boot protocol report descriptor */
+	// modifier keys are in the first byte
+	uint8_t modifiers = data[0];
+
+	item.offset = 2; /* second byte is reserved */
+	item.size = 8;
+	item.count = 6;
+	item.usage_min = 0;
+	item.usage_max = 255;
+	item.logical_min = 0;
+	item.logical_max = 255;
+
+	if(size != 8){
+		return -1;
+	}
+
+	uint8_t keys[6];
+	for(i=item.offset; i<item.count; i++) {
+		keys[i-2] = data[i];
+	}
+
+	callbacks->keyboard(keys, 6, modifiers, arg);
+	return EOK;
+}
+
+/**
+ * Makes output report for keyboard boot protocol
+ *
+ * @param leds
+ * @param output Output report data buffer
+ * @param size Size of the output buffer
+ * @return Error code
+ */
+int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
+{
+	if(size != 1){
+		return -1;
+	}
+
+	/* used only first five bits, others are only padding*/
+	*data = leds;
+	return EOK;
+}
+
+/**
  * @}
  */
Index: uspace/lib/usb/src/recognise.c
===================================================================
--- uspace/lib/usb/src/recognise.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/usb/src/recognise.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -346,4 +346,6 @@
     usb_address_t address, devman_handle_t *child_handle)
 {
+	static size_t device_name_index = 0;
+
 	device_t *child = NULL;
 	char *child_name = NULL;
@@ -357,7 +359,8 @@
 
 	/*
-	 * TODO: some better child naming
-	 */
-	rc = asprintf(&child_name, "usb%p", child);
+	 * TODO: Once the device driver framework support persistent
+	 * naming etc., something more descriptive could be created.
+	 */
+	rc = asprintf(&child_name, "usbdev%02zu", device_name_index);
 	if (rc < 0) {
 		goto failure;
@@ -381,4 +384,6 @@
 	}
 	
+	device_name_index++;
+
 	return EOK;
 
Index: uspace/lib/usb/src/usbdrvreq.c
===================================================================
--- uspace/lib/usb/src/usbdrvreq.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/lib/usb/src/usbdrvreq.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -60,5 +60,5 @@
 #define PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
     p_request, p_value, p_index, p_length) \
-	usb_device_request_setup_packet_t setup_packet = { \
+	usb_device_request_setup_packet_t name = { \
 		.request_type = \
 			((p_direction) == USB_DIRECTION_IN ? 128 : 0) \
Index: pace/srv/hw/netif/dp8390/Makefile
===================================================================
--- uspace/srv/hw/netif/dp8390/Makefile	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(revision )
@@ -1,47 +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 \
-	ne2000.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/hw/netif/dp8390/dp8390.c
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(revision )
@@ -1,650 +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 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 <netif_skel.h>
-#include <net/packet.h>
-#include <nil_interface.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  100
-
-/** 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);
-	}
-}
-
-/** 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;
-	
-	/* 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 < 0x1000; i++) {
-		if (pio_read_8(ne2k->port + DP_ISR) != 0)
-			break;
-	}
-	
-	/* Check if the DP8390 is really there */
-	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);
-	
-	/*
-	 * 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_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->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;
-	
-	pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA);
-	pio_write_8(ne2k->port + DP_RCR, RCR_AB);
-	
-	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);
-		
-		/* Reset the ethernet card */
-		uint8_t val = pio_read_8(ne2k->port + NE2K_RESET);
-		usleep(2000);
-		pio_write_8(ne2k->port + NE2K_RESET, val);
-		
-		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 < 0x1000; 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 < 0x1000; 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 uint8_t ne2k_isr_ack(ne2k_t *ne2k)
-{
-	uint8_t isr = pio_read_8(ne2k->port + DP_ISR);
-	if (isr != 0)
-		pio_write_8(ne2k->port + DP_ISR, isr);
-	
-	return isr;
-}
-
-static void ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length,
-    int nil_phone, device_id_t device_id)
-{
-	packet_t *packet = netif_packet_get_1(length);
-	if (!packet)
-		return;
-	
-	void *buf = packet_suffix(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++;
-	nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE);
-}
-
-static void ne2k_receive(ne2k_t *ne2k, int nil_phone, device_id_t device_id)
-{
-	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))
-			ne2k_receive_frame(ne2k, boundary, length, nil_phone, device_id);
-		
-		/*
-		 * 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);
-	}
-}
-
-void ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, int nil_phone, device_id_t device_id)
-{
-	bool signal = false;
-	bool stopped = false;
-	
-	for (; (isr & 0x7f) != 0; isr = ne2k_isr_ack(ne2k)) {
-		if (isr & (ISR_PTX | ISR_TXE)) {
-			if (isr & ISR_TXE)
-				ne2k->stats.send_errors++;
-			else {
-				uint8_t tsr = pio_read_8(ne2k->port + DP_TSR);
-				
-				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 = true;
-			} 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_PRX)
-			ne2k_receive(ne2k, nil_phone, device_id);
-		
-		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_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.
-			 */
-			stopped = true;
-		}
-	}
-	
-	if (stopped) {
-		/*
-		 * The chip is stopped, and all arrived
-		 * frames are delivered.
-		 */
-		ne2k_reset(ne2k);
-	}
-	
-	/* Signal a next frame to be sent */
-	if (signal)
-		fibril_condvar_broadcast(&ne2k->sq_cv);
-}
-
-/** @}
- */
Index: pace/srv/hw/netif/dp8390/dp8390.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(revision )
@@ -1,241 +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 ne2000
- *  @{
- */
-
-/** @file
- *  DP8390 network interface definitions.
- */
-
-#ifndef __NET_NETIF_DP8390_H__
-#define __NET_NETIF_DP8390_H__
-
-#include <fibril_synch.h>
-#include <net/packet.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;
-
-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 void ne2k_interrupt(ne2k_t *, uint8_t isr, int, device_id_t);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hw/netif/dp8390/ne2000.c
===================================================================
--- uspace/srv/hw/netif/dp8390/ne2000.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(revision )
@@ -1,361 +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.
- */
-
-/** @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/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 <netif_skel.h>
-#include <nil_interface.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))
-
-static int irc_service = 0;
-static int irc_phone = -1;
-
-/** DP8390 kernel interrupt command sequence.
- *
- */
-static irq_cmd_t ne2k_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 ne2k_code = {
-	sizeof(ne2k_cmds) / sizeof(irq_cmd_t),
-	ne2k_cmds
-};
-
-/** Handle the interrupt notification.
- *
- * This is the interrupt notification function.
- *
- * @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)
-		ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), nil_phone, device_id);
-}
-
-/** 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_cmds[0].addr;
-		
-		int rc = ipc_register_irq(ne2k->irq, device->device_id,
-		    device->device_id, &ne2k_code);
-		if (rc != EOK)
-			return rc;
-		
-		rc = ne2k_up(ne2k);
-		if (rc != EOK) {
-			ipc_unregister_irq(ne2k->irq, device->device_id);
-			return rc;
-		}
-		
-		if (irc_service)
-			async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq);
-		
-		change_state(device, NETIF_ACTIVE);
-	}
-	
-	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);
-		ipc_unregister_irq(ne2k->irq, device->device_id);
-		change_state(device, NETIF_STOPPED);
-	}
-	
-	return EOK;
-}
-
-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 = 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);
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return netif_module_start();
-}
-
-/** @}
- */
Index: uspace/srv/hw/netif/ne2000/Makefile
===================================================================
--- uspace/srv/hw/netif/ne2000/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/srv/hw/netif/ne2000/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/srv/hw/netif/ne2000/dp8390.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/srv/hw/netif/ne2000/dp8390.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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/ne2000.c
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
+++ uspace/srv/hw/netif/ne2000/ne2000.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -0,0 +1,410 @@
+/*
+ * 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/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 <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 = ipc_register_irq(ne2k->irq, device->device_id,
+		    device->device_id, &ne2k_code);
+		if (rc != EOK)
+			return rc;
+		
+		rc = ne2k_up(ne2k);
+		if (rc != EOK) {
+			ipc_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);
+		ipc_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 = 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_NE2000, 0, 0, &phonehash);
+}
+
+int main(int argc, char *argv[])
+{
+	/* Start the module */
+	return netif_module_start();
+}
+
+/** @}
+ */
Index: uspace/srv/net/cfg/ne2k
===================================================================
--- uspace/srv/net/cfg/ne2k	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/cfg/ne2k	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -3,5 +3,5 @@
 NAME=ne2k
 
-NETIF=dp8390
+NETIF=ne2000
 NIL=eth
 IL=ip
@@ -17,5 +17,5 @@
 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
Index: uspace/srv/net/il/arp/Makefile
===================================================================
--- uspace/srv/net/il/arp/Makefile	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/il/arp/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/il/arp/arp.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -36,13 +36,9 @@
  */
 
-#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>
@@ -54,18 +50,17 @@
 #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 +68,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 +121,5 @@
 		trans->hw_addr = NULL;
 	}
+	
 	fibril_condvar_broadcast(&trans->cv);
 }
@@ -94,8 +128,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 +137,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 +168,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 +194,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 +258,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 +267,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 +308,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 +335,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 +350,5 @@
 			}
 		}
+		
 		if (!trans->hw_addr) {
 			trans->hw_addr = measured_string_create_bulk(src_hw,
@@ -518,4 +360,5 @@
 			fibril_condvar_broadcast(&trans->cv);
 		}
+		
 		if (ntohs(header->operation) == ARPOP_REQUEST) {
 			header->operation = htons(ARPOP_REPLY);
@@ -538,82 +381,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 */
+			ipc_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);
+			}
+			ipc_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));
+			ipc_answer_0(iid, (sysarg_t) rc);
+			break;
+		
+		default:
+			ipc_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 +665,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 +677,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 +684,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 +801,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, size_t *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:
@@ -702,4 +861,5 @@
 			free(data);
 		}
+		
 		return rc;
 	
@@ -714,19 +874,22 @@
 		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));
-
+	
 	case NET_ARP_CLEAR_ADDRESS:
 		rc = measured_strings_receive(&address, &data, 1);
@@ -742,33 +905,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 +910,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;
-		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_standalone(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);
-	}
-}
-
-/** 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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/il/arp/arp.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -125,10 +125,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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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, size_t *count)
-{
-	return arp_message_standalone(callid, call, 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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 *,
-    size_t *);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/il/arp/arp_oc.h
===================================================================
--- uspace/srv/net/il/arp/arp_oc.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/il/ip/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/il/ip/ip.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -35,7 +35,4 @@
  * @see arp.h
  */
-
-#include "ip.h"
-#include "ip_module.h"
 
 #include <async.h>
@@ -52,4 +49,5 @@
 #include <sys/types.h>
 #include <byteorder.h>
+#include "ip.h"
 
 #include <adt/measured_strings.h>
@@ -70,13 +68,13 @@
 #include <icmp_client.h>
 #include <icmp_interface.h>
-#include <il_interface.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 +120,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 +244,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 +257,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 +423,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",
@@ -487,75 +479,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;
 }
 
@@ -626,7 +683,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;
@@ -757,6 +813,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)
@@ -792,4 +847,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;
 }
 
@@ -996,7 +1072,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;
@@ -1061,195 +1136,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;
@@ -1355,4 +1241,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.
  *
@@ -1366,7 +1504,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;
@@ -1418,231 +1555,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));
+			ipc_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);
+			}
+			
+			ipc_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));
+			ipc_answer_0(iid, (sysarg_t) rc);
+			break;
+		
+		default:
+			ipc_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
@@ -1845,33 +1877,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.
  *
@@ -1885,19 +1888,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 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;
@@ -1912,26 +1914,7 @@
 		    IPC_GET_PHONE(*call), NULL);
 	
-	case NET_IL_DEVICE:
+	case NET_IP_DEVICE:
 		return ip_device_req_local(0, IPC_GET_DEVICE(*call),
 		    IPC_GET_SERVICE(*call));
-	
-	case NET_IL_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));
-	
-	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:
@@ -1975,5 +1958,5 @@
 		return rc;
 	
-	case NET_IL_PACKET_SPACE:
+	case NET_IP_PACKET_SPACE:
 		rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen,
 		    &prefix, &content, &suffix);
@@ -1988,7 +1971,12 @@
 		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));
 	}
 	
@@ -1996,58 +1984,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;
-		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_standalone(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);
-	}
-}
-
-/** 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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/il/ip/ip.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -138,6 +138,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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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, size_t *count)
-{
-	return ip_message_standalone(callid, call, 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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 *,
-    size_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/net/net.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -45,4 +45,5 @@
 #include <stdio.h>
 #include <str.h>
+#include <str_error.h>
 
 #include <ipc/ipc.h>
@@ -51,4 +52,5 @@
 #include <ipc/net_net.h>
 #include <ipc/il.h>
+#include <ipc/nil.h>
 
 #include <net/modules.h>
@@ -62,5 +64,5 @@
 
 #include <netif_remote.h>
-#include <nil_interface.h>
+#include <nil_remote.h>
 #include <net_interface.h>
 #include <ip_interface.h>
@@ -288,6 +290,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;
@@ -331,5 +333,4 @@
 	if (rc != EOK)
 		return rc;
-	
 	
 	rc = net_initialize(client_connection);
@@ -591,6 +592,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;
 		}
@@ -709,13 +713,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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/net/net.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -52,6 +52,6 @@
  */
 
-#define DP8390_FILENAME  "/srv/dp8390"
-#define DP8390_NAME      "dp8390"
+#define NE2000_FILENAME  "/srv/ne2000"
+#define NE2000_NAME      "ne2000"
 
 #define ETHERNET_FILENAME  "/srv/eth"
Index: uspace/srv/net/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/netif/lo/lo.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -48,9 +48,6 @@
 #include <packet_client.h>
 #include <net/device.h>
-#include <nil_interface.h>
 #include <netif_skel.h>
-
-/** Default hardware address. */
-#define DEFAULT_ADDR  0
+#include <nil_remote.h>
 
 /** Default address length. */
@@ -60,6 +57,6 @@
 #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,
@@ -74,8 +71,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;
 	
@@ -85,60 +79,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) {
@@ -146,12 +147,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,5 +168,4 @@
 {
 	sysarg_t phonehash;
-
 	return ipc_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, &phonehash);
 }
@@ -173,15 +173,11 @@
 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;
 }
@@ -190,33 +186,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;
 }
@@ -224,10 +216,12 @@
 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);
+	change_state_message(device, NETIF_STOPPED);
+	return device->state;
 }
 
Index: uspace/srv/net/nil/eth/Makefile
===================================================================
--- uspace/srv/net/nil/eth/Makefile	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/nil/eth/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/nil/eth/eth.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -45,4 +45,5 @@
 
 #include <ipc/ipc.h>
+#include <ipc/nil.h>
 #include <ipc/net.h>
 #include <ipc/services.h>
@@ -56,13 +57,11 @@
 #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 +71,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 +117,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.
@@ -246,8 +247,8 @@
 			rc = packet_translate_remote(eth_globals.net_phone,
 			    &packet, IPC_GET_PACKET(*icall));
-			if (rc == EOK) {
+			if (rc == EOK)
 				rc = nil_received_msg_local(0,
 				    IPC_GET_DEVICE(*icall), packet, 0);
-			}
+			
 			ipc_answer_0(iid, (sysarg_t) rc);
 			break;
@@ -836,6 +837,6 @@
 }
 
-int nil_message_standalone(const char *name, ipc_callid_t callid,
-    ipc_call_t *call, ipc_call_t *answer, size_t *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;
@@ -893,52 +894,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;
-		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_standalone(NAME, 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);
-	}
-}
-
 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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/nil/eth/eth.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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, size_t *count)
-{
-	return nil_message_standalone(name, callid, call, answer, count);
-}
-
-/** @}
- */
Index: uspace/srv/net/nil/nildummy/Makefile
===================================================================
--- uspace/srv/net/nil/nildummy/Makefile	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/nil/nildummy/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -42,4 +42,5 @@
 #include <str.h>
 #include <ipc/ipc.h>
+#include <ipc/nil.h>
 #include <ipc/net.h>
 #include <ipc/services.h>
@@ -47,11 +48,10 @@
 #include <net/modules.h>
 #include <net/device.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 <netif_remote.h>
-#include <nil_local.h>
+#include <nil_skel.h>
 
 #include "nildummy.h"
@@ -81,6 +81,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 +88,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 +96,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,5 +106,5 @@
 	packet_t *packet;
 	int rc;
-
+	
 	while (true) {
 		switch (IPC_GET_IMETHOD(*icall)) {
@@ -120,8 +118,8 @@
 			rc = packet_translate_remote(nildummy_globals.net_phone,
 			    &packet, IPC_GET_PACKET(*icall));
-			if (rc == EOK) {
+			if (rc == EOK)
 				rc = nil_received_msg_local(0,
 				    IPC_GET_DEVICE(*icall), packet, 0);
-			}
+			
 			ipc_answer_0(iid, (sysarg_t) rc);
 			break;
@@ -139,26 +137,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 +210,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 +219,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 +237,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 +248,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 +269,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 +283,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 +308,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 +328,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 +351,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, size_t *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;
@@ -434,52 +442,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;
-		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_standalone(NAME, 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);
-	}
-}
-
 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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/nil/nildummy/nildummy.h	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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, size_t *count)
-{
-	return nil_message_standalone(name, callid, call, answer, count);
-}
-
-/** @}
- */
Index: uspace/srv/net/tl/icmp/Makefile
===================================================================
--- uspace/srv/net/tl/icmp/Makefile	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/tl/icmp/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/tl/icmp/icmp.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -35,7 +35,4 @@
  * @see icmp.h
  */
-
-#include "icmp.h"
-#include "icmp_module.h"
 
 #include <async.h>
@@ -68,14 +65,16 @@
 #include <icmp_client.h>
 #include <icmp_interface.h>
-#include <il_interface.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>
 
+#include "icmp.h"
+
 /** ICMP module name. */
-#define NAME	"ICMP protocol"
+#define NAME  "icmp"
 
 /** Default ICMP error reporting. */
@@ -394,78 +393,4 @@
 }
 
-/** 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)
-{
-	measured_string_t names[] = {
-		{
-			(uint8_t *) "ICMP_ERROR_REPORTING",
-			20
-		},
-		{
-			(uint8_t *) "ICMP_ECHO_REPLYING",
-			18
-		}
-	};
-	measured_string_t *configuration;
-	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);
-		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;
-
-	/* 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);
-		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');
-		}
-		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.
  *
@@ -667,4 +592,110 @@
 		return icmp_release_and_return(packet, rc);
 
+	return EOK;
+}
+
+/** 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)
+{
+	packet_t *packet;
+	int rc;
+	
+	while (true) {
+		switch (IPC_GET_IMETHOD(*icall)) {
+		case NET_TL_RECEIVED:
+			rc = packet_translate_remote(icmp_globals.net_phone, &packet,
+			    IPC_GET_PACKET(*icall));
+			if (rc == EOK)
+				rc = icmp_received_msg_local(IPC_GET_DEVICE(*icall), packet,
+				    SERVICE_ICMP, IPC_GET_ERROR(*icall));
+			
+			ipc_answer_0(iid, (sysarg_t) rc);
+			break;
+		default:
+			ipc_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[] = {
+		{
+			(uint8_t *) "ICMP_ERROR_REPORTING",
+			20
+		},
+		{
+			(uint8_t *) "ICMP_ECHO_REPLYING",
+			18
+		}
+	};
+	measured_string_t *configuration;
+	size_t count = sizeof(names) / sizeof(measured_string_t);
+	uint8_t *data;
+	
+	fibril_rwlock_initialize(&icmp_globals.lock);
+	fibril_rwlock_write_lock(&icmp_globals.lock);
+	icmp_replies_initialize(&icmp_globals.replies);
+	icmp_echo_data_initialize(&icmp_globals.echo_data);
+	
+	icmp_globals.net_phone = net_phone;
+	
+	icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP,
+	    SERVICE_ICMP, icmp_receiver);
+	if (icmp_globals.ip_phone < 0) {
+		fibril_rwlock_write_unlock(&icmp_globals.lock);
+		return icmp_globals.ip_phone;
+	}
+	
+	int rc = ip_packet_size_req(icmp_globals.ip_phone, -1,
+	    &icmp_globals.packet_dimension);
+	if (rc != EOK) {
+		fibril_rwlock_write_unlock(&icmp_globals.lock);
+		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;
+	
+	/* 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);
+		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');
+		}
+		net_free_settings(configuration, data);
+	}
+	
+	fibril_rwlock_write_unlock(&icmp_globals.lock);
 	return EOK;
 }
@@ -893,89 +924,24 @@
  * @see IS_NET_ICMP_MESSAGE()
  */
-int icmp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
+int tl_module_message	(ipc_callid_t callid, ipc_call_t *call,
     ipc_call_t *answer, size_t *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 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;
-		size_t 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_module.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp_module.c	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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, size_t *count)
-{
-	return icmp_message_standalone(callid, call, answer, count);
-}
-
-/** @}
- */
Index: pace/srv/net/tl/icmp/icmp_module.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp_module.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 *,
-    size_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/tl/tcp/Makefile
===================================================================
--- uspace/srv/net/tl/tcp/Makefile	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/tl/tcp/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -36,8 +36,4 @@
  */
 
-#include "tcp.h"
-#include "tcp_header.h"
-#include "tcp_module.h"
-
 #include <assert.h>
 #include <async.h>
@@ -72,9 +68,12 @@
 #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 +219,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,
@@ -1260,11 +1217,7 @@
  * @see IS_NET_TCP_MESSAGE()
  */
-int
-tcp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
+int tl_module_message(ipc_callid_t callid, ipc_call_t *call,
     ipc_call_t *answer, size_t *answer_count)
 {
-	packet_t *packet;
-	int rc;
-
 	assert(call);
 	assert(answer);
@@ -1273,16 +1226,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);
@@ -2486,61 +2427,78 @@
 }
 
-/** 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;
-		size_t 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));
+			
+			ipc_answer_0(iid, (sysarg_t) rc);
+			break;
+		default:
+			ipc_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(SERVICE_ICMP,
+	    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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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, size_t *count)
-{
-	return tcp_message_standalone(callid, call, answer, count);
-}
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/tcp_module.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_module.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 *,
-    size_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/tl/udp/Makefile
===================================================================
--- uspace/srv/net/tl/udp/Makefile	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/tl/udp/Makefile	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ uspace/srv/net/tl/udp/udp.c	(revision 7a725b138c9bf9e650764a1067e2922361155650)
@@ -35,8 +35,4 @@
  * @see udp.h
  */
-
-#include "udp.h"
-#include "udp_header.h"
-#include "udp_module.h"
 
 #include <async.h>
@@ -69,9 +65,12 @@
 #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 +91,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 +334,127 @@
 }
 
+/** 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));
+			
+			ipc_answer_0(iid, (sysarg_t) rc);
+			break;
+		default:
+			ipc_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(SERVICE_ICMP,
+	    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.
  *
@@ -860,20 +891,10 @@
  * @see IS_NET_UDP_MESSAGE()
  */
-int udp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
+int tl_module_message(ipc_callid_t callid, ipc_call_t *call,
     ipc_call_t *answer, size_t *answer_count)
 {
-	packet_t *packet;
-	int rc;
-
 	*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);
@@ -883,58 +904,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;
-		size_t 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 f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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, size_t *count)
-{
-	return udp_message_standalone(callid, call, answer, count);
-}
-
-/** @}
- */
Index: pace/srv/net/tl/udp/udp_module.h
===================================================================
--- uspace/srv/net/tl/udp/udp_module.h	(revision f40a1e24252e9904e01ba889c8b1edbbe5cc9d63)
+++ 	(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 *,
-    size_t *);
-
-#endif
-
-/** @}
- */
