Index: uspace/srv/Makefile.common
===================================================================
--- uspace/srv/Makefile.common	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ 	(revision )
@@ -1,98 +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.
-#
-
-## Common rules for building servers.
-#
-
-# Individual makefiles set:
-#
-#	USPACE_PREFIX	relative path to uspace/ directory
-#	LIBS		libraries to link with (with relative path)
-#	EXTRA_CFLAGS	additional flags to pass to C compiler
-#	JOB		job file name (like appname.job)
-#	OUTPUT		output binary name (like appname)
-#	SOURCES		list of source files
-#
-
-DEPEND = Makefile.depend
-DEPEND_PREV = $(DEPEND).prev
-
-LIBC_PREFIX = $(USPACE_PREFIX)/lib/libc
-LIBBLOCK_PREFIX = $(USPACE_PREFIX)/lib/libblock
-LIBFS_PREFIX = $(USPACE_PREFIX)/lib/libfs
-LIBPCI_PREFIX = $(USPACE_PREFIX)/lib/libpci
-SOFTINT_PREFIX = $(USPACE_PREFIX)/lib/softint
-LIBDRV_PREFIX = $(USPACE_PREFIX)/lib/libdrv
-
-LINK_SCRIPT ?= $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld
-
-JOB = $(OUTPUT).job
-
-OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
-
-include $(LIBC_PREFIX)/Makefile.toolchain
-
-CFLAGS += $(EXTRA_CFLAGS)
-
-.PHONY: all build clean
-
-all: \
-    $(LIBC_PREFIX)/../../../version \
-    $(LIBC_PREFIX)/../../../Makefile.config \
-    $(LIBC_PREFIX)/../../../config.h \
-    $(LIBC_PREFIX)/../../../config.defs \
-    $(LIBS) \
-    \
-    $(OUTPUT) $(OUTPUT).disasm \
-    $(EXTRA_OUTPUT)
-	-[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
-
-clean:
-	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm $(EXTRA_OUTPUT)
-	find . -name '*.o' -follow -exec rm \{\} \;
-
-build: 
-
--include $(DEPEND)
-
-$(OUTPUT).disasm: $(OUTPUT)
-	$(OBJDUMP) -d $< > $@
-
-$(OUTPUT): $(LINK_SCRIPT) $(OBJECTS) $(LIBS)
-	$(LD) -T $(LINK_SCRIPT) $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
-
-%.o: %.c $(DEPEND)
-	$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
-ifeq ($(PRECHECK),y)
-	$(JOBFILE) $(JOB) $< $@ cc core $(DEFS) $(CFLAGS)
-endif
-
-$(DEPEND):
-	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > $@ 2> /dev/null
-	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
Index: uspace/srv/bd/ata_bd/Makefile
===================================================================
--- uspace/srv/bd/ata_bd/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/ata_bd/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,10 +29,8 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = ata_bd
+BINARY = ata_bd
 
 SOURCES = \
 	ata_bd.c
 
-include ../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -56,5 +56,5 @@
 #include <as.h>
 #include <fibril_synch.h>
-#include <string.h>
+#include <str.h>
 #include <devmap.h>
 #include <sys/types.h>
@@ -500,5 +500,7 @@
 
 	d = &disk[disk_id];
-	bc.h = 0;	/* Silence warning. */
+	
+	/* Silence warning. */
+	memset(&bc, 0, sizeof(bc));
 
 	/* Compute block coordinates. */
@@ -574,5 +576,7 @@
 
 	d = &disk[disk_id];
-	bc.h = 0;	/* Silence warning. */
+	
+	/* Silence warning. */
+	memset(&bc, 0, sizeof(bc));
 
 	/* Compute block coordinates. */
Index: uspace/srv/bd/ata_bd/ata_bd.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/ata_bd/ata_bd.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -38,5 +38,5 @@
 #include <sys/types.h>
 #include <fibril_synch.h>
-#include <string.h>
+#include <str.h>
 
 enum {
Index: uspace/srv/bd/file_bd/Makefile
===================================================================
--- uspace/srv/bd/file_bd/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/file_bd/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,10 +29,8 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = file_bd
+BINARY = file_bd
 
 SOURCES = \
 	file_bd.c
 
-include ../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/bd/file_bd/file_bd.c
===================================================================
--- uspace/srv/bd/file_bd/file_bd.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/file_bd/file_bd.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -48,4 +48,5 @@
 #include <devmap.h>
 #include <sys/types.h>
+#include <sys/typefmt.h>
 #include <errno.h>
 #include <bool.h>
@@ -56,5 +57,5 @@
 
 static const size_t block_size = 512;
-static bn_t num_blocks;
+static aoff64_t num_blocks;
 static FILE *img;
 
@@ -207,4 +208,12 @@
 	int rc;
 
+	/* Check whether access is within device address bounds. */
+	if (ba + cnt > num_blocks) {
+		printf(NAME ": Accessed blocks %" PRIuOFF64 "-%" PRIuOFF64 ", while "
+		    "max block number is %" PRIuOFF64 ".\n", ba, ba + cnt - 1,
+		    num_blocks - 1);
+		return ELIMIT;
+	}
+
 	fibril_mutex_lock(&dev_lock);
 
@@ -237,4 +246,12 @@
 	int rc;
 
+	/* Check whether access is within device address bounds. */
+	if (ba + cnt > num_blocks) {
+		printf(NAME ": Accessed blocks %" PRIuOFF64 "-%" PRIuOFF64 ", while "
+		    "max block number is %" PRIuOFF64 ".\n", ba, ba + cnt - 1,
+		    num_blocks - 1);
+		return ELIMIT;
+	}
+
 	fibril_mutex_lock(&dev_lock);
 
Index: uspace/srv/bd/gxe_bd/Makefile
===================================================================
--- uspace/srv/bd/gxe_bd/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/gxe_bd/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,10 +29,8 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = gxe_bd
+BINARY = gxe_bd
 
 SOURCES = \
 	gxe_bd.c
 
-include ../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/bd/part/guid_part/Makefile
===================================================================
--- uspace/srv/bd/part/guid_part/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/part/guid_part/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -28,12 +28,12 @@
 
 USPACE_PREFIX = ../../../..
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBC_PREFIX)/libc.a
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a
 EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX)
 
 # Correct name is 'guid_part' but must use this because of FAT 8.3 names.
-OUTPUT = g_part
+BINARY = g_part
 
 SOURCES = \
 	guid_part.c
 
-include ../../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/bd/part/guid_part/guid_part.c
===================================================================
--- uspace/srv/bd/part/guid_part/guid_part.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/part/guid_part/guid_part.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -79,7 +79,7 @@
 	bool present;
 	/** Address of first block */
-	bn_t start_addr;
+	aoff64_t start_addr;
 	/** Number of blocks */
-	bn_t length;
+	aoff64_t length;
 	/** Device representing the partition (outbound device) */
 	dev_handle_t dev;
@@ -101,7 +101,7 @@
 static void gpt_pte_to_part(const gpt_entry_t *pte, part_t *part);
 static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall);
-static int gpt_bd_read(part_t *p, bn_t ba, size_t cnt, void *buf);
-static int gpt_bd_write(part_t *p, bn_t ba, size_t cnt, const void *buf);
-static int gpt_bsa_translate(part_t *p, bn_t ba, size_t cnt, bn_t *gba);
+static int gpt_bd_read(part_t *p, aoff64_t ba, size_t cnt, void *buf);
+static int gpt_bd_write(part_t *p, aoff64_t ba, size_t cnt, const void *buf);
+static int gpt_bsa_translate(part_t *p, aoff64_t ba, size_t cnt, aoff64_t *gba);
 
 int main(int argc, char **argv)
@@ -199,5 +199,5 @@
 		    / (1024 * 1024);
 		printf(NAME ": Registered device %s: %" PRIu64 " blocks "
-		    "%" PRIuBN " MB.\n", name, part->length, size_mb);
+		    "%" PRIuOFF64 " MB.\n", name, part->length, size_mb);
 
 		part->dev = dev;
@@ -319,5 +319,5 @@
 	int flags;
 	int retval;
-	bn_t ba;
+	aoff64_t ba;
 	size_t cnt;
 	part_t *part;
@@ -402,7 +402,7 @@
 
 /** Read blocks from partition. */
-static int gpt_bd_read(part_t *p, bn_t ba, size_t cnt, void *buf)
-{
-	bn_t gba;
+static int gpt_bd_read(part_t *p, aoff64_t ba, size_t cnt, void *buf)
+{
+	aoff64_t gba;
 
 	if (gpt_bsa_translate(p, ba, cnt, &gba) != EOK)
@@ -413,7 +413,7 @@
 
 /** Write blocks to partition. */
-static int gpt_bd_write(part_t *p, bn_t ba, size_t cnt, const void *buf)
-{
-	bn_t gba;
+static int gpt_bd_write(part_t *p, aoff64_t ba, size_t cnt, const void *buf)
+{
+	aoff64_t gba;
 
 	if (gpt_bsa_translate(p, ba, cnt, &gba) != EOK)
@@ -424,5 +424,5 @@
 
 /** Translate block segment address with range checking. */
-static int gpt_bsa_translate(part_t *p, bn_t ba, size_t cnt, bn_t *gba)
+static int gpt_bsa_translate(part_t *p, aoff64_t ba, size_t cnt, aoff64_t *gba)
 {
 	if (ba + cnt > p->length)
Index: uspace/srv/bd/part/mbr_part/Makefile
===================================================================
--- uspace/srv/bd/part/mbr_part/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/part/mbr_part/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,11 +29,10 @@
 
 USPACE_PREFIX = ../../../..
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBC_PREFIX)/libc.a
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a
 EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX)
-
-OUTPUT = mbr_part
+BINARY = mbr_part
 
 SOURCES = \
 	mbr_part.c
 
-include ../../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/bd/part/mbr_part/mbr_part.c
===================================================================
--- uspace/srv/bd/part/mbr_part/mbr_part.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/part/mbr_part/mbr_part.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -97,7 +97,7 @@
 	bool present;
 	/** Address of first block */
-	bn_t start_addr;
+	aoff64_t start_addr;
 	/** Number of blocks */
-	bn_t length;
+	aoff64_t length;
 	/** Device representing the partition (outbound device) */
 	dev_handle_t dev;
@@ -249,5 +249,5 @@
 		size_mb = (part->length * block_size + 1024 * 1024 - 1)
 		    / (1024 * 1024);
-		printf(NAME ": Registered device %s: %" PRIuBN " blocks "
+		printf(NAME ": Registered device %s: %" PRIuOFF64 " blocks "
 		    "%" PRIu64 " MB.\n", name, part->length, size_mb);
 
Index: uspace/srv/bd/rd/Makefile
===================================================================
--- uspace/srv/bd/rd/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/rd/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,10 +29,8 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = rd
+BINARY = rd
 
 SOURCES = \
 	rd.c
 
-include ../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/bd/rd/rd.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -32,9 +32,9 @@
 /** @addtogroup rd
  * @{
- */ 
+ */
 
 /**
- * @file	rd.c
- * @brief	Initial RAM disk for HelenOS.
+ * @file rd.c
+ * @brief Initial RAM disk for HelenOS.
  */
 
@@ -61,4 +61,5 @@
 /** Pointer to the ramdisk's image */
 static void *rd_addr;
+
 /** Size of the ramdisk */
 static size_t rd_size;
@@ -70,16 +71,17 @@
 static int rd_write_blocks(uint64_t ba, size_t cnt, const void *buf);
 
-/**
- * This rwlock protects the ramdisk's data.
+/** This rwlock protects the ramdisk's data.
+ *
  * If we were to serve multiple requests (read + write or several writes)
- * concurrently (i.e. from two or more threads), each read and write needs to be
- * protected by this rwlock.
- */ 
+ * concurrently (i.e. from two or more threads), each read and write needs to
+ * be protected by this rwlock.
+ *
+ */
 fibril_rwlock_t rd_lock;
 
 /** Handle one connection to ramdisk.
  *
- * @param iid		Hash of the request that opened the connection.
- * @param icall		Call data of the request that opened the connection.
+ * @param iid   Hash of the request that opened the connection.
+ * @param icall Call data of the request that opened the connection.
  */
 static void rd_connection(ipc_callid_t iid, ipc_call_t *icall)
@@ -92,10 +94,10 @@
 	size_t cnt;
 	size_t comm_size;
-
+	
 	/*
 	 * Answer the first IPC_M_CONNECT_ME_TO call.
 	 */
 	ipc_answer_0(iid, EOK);
-
+	
 	/*
 	 * Now we wait for the client to send us its communication as_area.
@@ -108,5 +110,5 @@
 		} else {
 			ipc_answer_0(callid, EHANGUP);
-			return;		
+			return;
 		}
 	} else {
@@ -178,9 +180,9 @@
 		return ELIMIT;
 	}
-
+	
 	fibril_rwlock_read_lock(&rd_lock);
 	memcpy(buf, rd_addr + ba * block_size, block_size * cnt);
 	fibril_rwlock_read_unlock(&rd_lock);
-
+	
 	return EOK;
 }
@@ -193,9 +195,9 @@
 		return ELIMIT;
 	}
-
+	
 	fibril_rwlock_write_lock(&rd_lock);
 	memcpy(rd_addr + ba * block_size, buf, block_size * cnt);
 	fibril_rwlock_write_unlock(&rd_lock);
-
+	
 	return EOK;
 }
@@ -204,9 +206,14 @@
 static bool rd_init(void)
 {
-	rd_size = sysinfo_value("rd.size");
-	void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
-	
-	if (rd_size == 0) {
-		printf(NAME ": No RAM disk found\n");
+	int ret = sysinfo_get_value("rd.size", &rd_size);
+	if ((ret != EOK) || (rd_size == 0)) {
+		printf("%s: No RAM disk found\n", NAME);
+		return false;
+	}
+	
+	sysarg_t rd_ph_addr;
+	ret = sysinfo_get_value("rd.address.physical", &rd_ph_addr);
+	if ((ret != EOK) || (rd_ph_addr == 0)) {
+		printf("%s: Invalid RAM disk physical address\n", NAME);
 		return false;
 	}
@@ -215,17 +222,17 @@
 	
 	int flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
-	int retval = physmem_map(rd_ph_addr, rd_addr,
+	int retval = physmem_map((void *) rd_ph_addr, rd_addr,
 	    ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
 	
 	if (retval < 0) {
-		printf(NAME ": Error mapping RAM disk\n");
-		return false;
-	}
-	
-	printf(NAME ": Found RAM disk at %p, %d bytes\n", rd_ph_addr, rd_size);
+		printf("%s: Error mapping RAM disk\n", NAME);
+		return false;
+	}
+	
+	printf("%s: Found RAM disk at %p, %d bytes\n", NAME, rd_ph_addr, rd_size);
 	
 	int rc = devmap_driver_register(NAME, rd_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
+		printf("%s: Unable to register driver (%d)\n", NAME, rc);
 		return false;
 	}
@@ -234,5 +241,5 @@
 	if (devmap_device_register("bd/initrd", &dev_handle) != EOK) {
 		devmap_hangup_phone(DEVMAP_DRIVER);
-		printf(NAME ": Unable to register device\n");
+		printf("%s: Unable to register device\n", NAME);
 		return false;
 	}
@@ -245,10 +252,10 @@
 int main(int argc, char **argv)
 {
-	printf(NAME ": HelenOS RAM disk server\n");
+	printf("%s: HelenOS RAM disk server\n", NAME);
 	
 	if (!rd_init())
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
 	async_manager();
 
Index: uspace/srv/clip/Makefile
===================================================================
--- uspace/srv/clip/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/clip/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,10 +29,8 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = clip
+BINARY = clip
 
 SOURCES = \
 	clip.c
 
-include ../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/clip/clip.c
===================================================================
--- uspace/srv/clip/clip.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/clip/clip.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -65,5 +65,5 @@
 		break;
 	case CLIPBOARD_TAG_DATA:
-		rc = async_data_receive(&data, 0, 0, 0, &size);
+		rc = async_data_write_accept((void **) &data, false, 0, 0, 0, &size);
 		if (rc != EOK) {
 			ipc_answer_0(rid, rc);
@@ -145,5 +145,5 @@
 	
 	fibril_mutex_unlock(&clip_mtx);
-	ipc_answer_2(rid, EOK, (ipcarg_t) size, (ipcarg_t) clip_tag);
+	ipc_answer_2(rid, EOK, (ipcarg_t) size, (ipcarg_t) tag);
 }
 
Index: uspace/srv/dd/Makefile
===================================================================
--- uspace/srv/dd/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/dd/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,7 +29,5 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = dd
+BINARY = dd
 
 SOURCES = \
@@ -39,15 +37,6 @@
 	intel_piix3.c \
 	isa.c \
-	serial.c
+	serial.c \
+	intel_method1.c
 
-#ifeq ($(PROCESSOR), us)
-#        SOURCES += psycho.c
-#endif
-
-#ifeq ($(UARCH), ia32)
-        SOURCES += intel_method1.c
-#endif
-
-
-
-include ../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/devman/Makefile
===================================================================
--- uspace/srv/devman/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/devman/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,7 +29,5 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = devman
+BINARY = devman
 
 SOURCES = \
@@ -39,3 +37,3 @@
 	util.c
 
-include ../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/devman/devman.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -38,5 +38,4 @@
 
 #include "devman.h"
-#include "util.h"
 
 /** Allocate and initialize a new driver structure.
@@ -74,5 +73,5 @@
  * @return the match id. 
  */
-char * read_match_id(const char **buf) 
+char * read_match_id(char **buf) 
 {
 	char *res = NULL;
@@ -100,5 +99,5 @@
  * @return true if at least one match id and associated match score was successfully read, false otherwise.
  */
-bool parse_match_ids(const char *buf, match_id_list_t *ids)
+bool parse_match_ids(char *buf, match_id_list_t *ids)
 {
 	int score = 0;
@@ -158,5 +157,5 @@
 	bool opened = false;
 	int fd;		
-	off_t len = 0;
+	size_t len = 0;
 	
 	fd = open(conf_path, O_RDONLY);
@@ -315,8 +314,8 @@
 	printf(NAME ": create_root_node\n");
 	node_t *node = create_dev_node();
-	if (node) {
-		insert_dev_node(tree, node, "", NULL);
+	if (node) {		
+		insert_dev_node(tree, node, clone_string(""), NULL);
 		match_id_t *id = create_match_id();
-		id->id = "root";
+		id->id = clone_string("root");
 		id->score = 100;
 		add_match_id(&node->match_ids, id);
@@ -392,11 +391,12 @@
 	printf(NAME ": start_driver '%s'\n", drv->name);
 	
-	char *argv[2];
+	const char *argv[2];
 	
 	argv[0] = drv->name;
 	argv[1] = NULL;
 	
-	if (!task_spawn(drv->binary_path, argv)) {
-		printf(NAME ": error spawning %s\n", drv->name);
+	int err;
+	if (!task_spawn(drv->binary_path, argv, &err)) {
+		printf(NAME ": error spawning %s, errno = %d\n", drv->name, err);
 		return false;
 	}
@@ -682,5 +682,4 @@
 	char *rel_path = path;
 	char *next_path_elem = NULL;
-	size_t elem_size = 0;
 	bool cont = '/' == rel_path[0];
 	
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/devman/devman.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -37,5 +37,5 @@
 #include <bool.h>
 #include <dirent.h>
-#include <string.h>
+#include <str.h>
 #include <adt/list.h>
 #include <ipc/ipc.h>
@@ -145,7 +145,8 @@
 int get_match_score(driver_t *drv, node_t *dev);
 
-bool parse_match_ids(const char *buf, match_id_list_t *ids);
+bool parse_match_ids(char *buf, match_id_list_t *ids);
 bool read_match_ids(const char *conf_path, match_id_list_t *ids);
-char * read_id(const char **buf) ;
+char * read_match_id(char **buf);
+char * read_id(const char **buf);
 
 // Drivers
@@ -165,5 +166,5 @@
 }
 
-driver_t * create_driver();
+driver_t * create_driver(void);
 bool get_driver_info(const char *base_path, const char *name, driver_t *drv);
 int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path);
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/devman/main.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -45,5 +45,5 @@
 #include <fibril_synch.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <dirent.h>
 #include <fcntl.h>
@@ -60,4 +60,53 @@
 static driver_list_t drivers_list;
 static dev_tree_t device_tree;
+
+/** Wrapper for receiving strings
+ *
+ * This wrapper only makes it more comfortable to use async_data_write_*
+ * functions to receive strings.
+ *
+ * @param str      Pointer to string pointer (which should be later disposed
+ *                 by free()). If the operation fails, the pointer is not
+ *                 touched.
+ * @param max_size Maximum size (in bytes) of the string to receive. 0 means
+ *                 no limit.
+ * @param received If not NULL, the size of the received data is stored here.
+ *
+ * @return Zero on success or a value from @ref errno.h on failure.
+ *
+ */
+static int async_string_receive(char **str, const size_t max_size, size_t *received)
+{
+        ipc_callid_t callid;
+        size_t size;
+        if (!async_data_write_receive(&callid, &size)) {
+                ipc_answer_0(callid, EINVAL);
+                return EINVAL;
+        }
+        
+        if ((max_size > 0) && (size > max_size)) {
+                ipc_answer_0(callid, EINVAL);
+                return EINVAL;
+        }
+        
+        char *data = (char *) malloc(size + 1);
+        if (data == NULL) {
+                ipc_answer_0(callid, ENOMEM);
+                return ENOMEM;
+        }
+        
+        int rc = async_data_write_finalize(callid, data, size);
+        if (rc != EOK) {
+                free(data);
+                return rc;
+        }
+        
+        data[size] = 0;
+        *str = data;
+        if (received != NULL)
+                *received = size;
+        
+        return EOK;
+}
 
 /**
@@ -155,5 +204,7 @@
 	match_id->score = IPC_GET_ARG1(call);
 	
-	rc = async_string_receive(&match_id->id, DEVMAN_NAME_MAXLEN, NULL);	
+	char *match_id_str;
+	rc = async_string_receive(&match_id_str, DEVMAN_NAME_MAXLEN, NULL);	
+	match_id->id = match_id_str;
 	if (EOK != rc) {
 		delete_match_id(match_id);
Index: uspace/srv/devman/match.c
===================================================================
--- uspace/srv/devman/match.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/devman/match.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -32,5 +32,5 @@
  
  
-#include <string.h>
+#include <str.h>
 
 #include "devman.h"
Index: uspace/srv/devman/util.c
===================================================================
--- uspace/srv/devman/util.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/devman/util.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -32,5 +32,5 @@
 
 #include <stdlib.h>
-#include <string.h> 
+#include <str.h> 
  
 #include "util.h"
@@ -62,5 +62,5 @@
 }
 
-const char * get_path_elem_end(const char *path)
+char * get_path_elem_end(char *path)
 {
 	while (0 != *path && '/' != *path) {
Index: uspace/srv/devman/util.h
===================================================================
--- uspace/srv/devman/util.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/devman/util.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -35,10 +35,12 @@
 
 #include <ctype.h>
+#include <str.h>
+#include <malloc.h>
 
 
 char * get_abs_path(const char *base_path, const char *name, const char *ext);
-const char * get_path_elem_end(const char *path);
+char * get_path_elem_end(char *path);
 
-static inline bool skip_spaces(const char **buf) 
+static inline bool skip_spaces(char **buf) 
 {
 	while (isspace(**buf)) {
@@ -65,3 +67,13 @@
 }
 
+static inline char * clone_string(const char *s) 
+{
+	size_t size = str_size(s) + 1;
+	char *str = (char *)malloc(size);
+	if (NULL != str) {
+		str_cpy(str, size, s);
+	}
+	return str;
+}
+
 #endif
Index: uspace/srv/devmap/Makefile
===================================================================
--- uspace/srv/devmap/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/devmap/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,10 +29,8 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = devmap
+BINARY = devmap
 
 SOURCES = \
 	devmap.c
 
-include ../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/devmap/devmap.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -44,5 +44,5 @@
 #include <fibril_synch.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <ipc/devmap.h>
 
@@ -172,5 +172,11 @@
 		
 		*name = str_dup(fqdn);
-		if ((*name == NULL) || (str_cmp(*name, "") == 0)) {
+		if (*name == NULL) {
+			free(*ns_name);
+			return false;
+		}
+		
+		if (str_cmp(*name, "") == 0) {
+			free(*name);
 			free(*ns_name);
 			return false;
@@ -186,9 +192,15 @@
 	
 	*name = str_dup(fqdn + slash_after);
-	if ((*name == NULL) || (str_cmp(*name, "") == 0)) {
+	if (*name == NULL) {
 		free(*ns_name);
 		return false;
 	}
 	
+	if (str_cmp(*name, "") == 0) {
+		free(*name);
+		free(*ns_name);
+		return false;
+	}
+	
 	return true;
 }
@@ -202,11 +214,10 @@
 static devmap_namespace_t *devmap_namespace_find_name(const char *name)
 {
-	link_t *item = namespaces_list.next;
-	
-	while (item != &namespaces_list) {
-		devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
+	link_t *item;
+	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
+		devmap_namespace_t *namespace =
+		    list_get_instance(item, devmap_namespace_t, namespaces);
 		if (str_cmp(namespace->name, name) == 0)
 			return namespace;
-		item = item->next;
 	}
 	
@@ -224,12 +235,10 @@
 static devmap_namespace_t *devmap_namespace_find_handle(dev_handle_t handle)
 {
-	link_t *item = namespaces_list.next;
-	
-	while (item != &namespaces_list) {
-		devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
+	link_t *item;
+	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
+		devmap_namespace_t *namespace =
+		    list_get_instance(item, devmap_namespace_t, namespaces);
 		if (namespace->handle == handle)
 			return namespace;
-		
-		item = item->next;
 	}
 	
@@ -246,11 +255,11 @@
     const char *name)
 {
-	link_t *item = devices_list.next;
-	
-	while (item != &devices_list) {
-		devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
-		if ((str_cmp(device->namespace->name, ns_name) == 0) && (str_cmp(device->name, name) == 0))
+	link_t *item;
+	for (item = devices_list.next; item != &devices_list; item = item->next) {
+		devmap_device_t *device =
+		    list_get_instance(item, devmap_device_t, devices);
+		if ((str_cmp(device->namespace->name, ns_name) == 0)
+		    && (str_cmp(device->name, name) == 0))
 			return device;
-		item = item->next;
 	}
 	
@@ -268,12 +277,10 @@
 static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
 {
-	link_t *item = devices_list.next;
-	
-	while (item != &devices_list) {
-		devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
+	link_t *item;
+	for (item = devices_list.next; item != &devices_list; item = item->next) {
+		devmap_device_t *device =
+		    list_get_instance(item, devmap_device_t, devices);
 		if (device->handle == handle)
 			return device;
-		
-		item = item->next;
 	}
 	
@@ -367,5 +374,4 @@
 	list_remove(&(device->driver_devices));
 	
-	free(device->namespace);
 	free(device->name);
 	free(device);
@@ -386,6 +392,6 @@
 	}
 	
-	devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
-	
+	devmap_driver_t *driver =
+	    (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
 	if (driver == NULL) {
 		ipc_answer_0(iid, ENOMEM);
@@ -396,5 +402,6 @@
 	 * Get driver name
 	 */
-	int rc = async_string_receive(&driver->name, DEVMAP_NAME_MAXLEN, NULL);
+	int rc = async_data_write_accept((void **) &driver->name, true, 0,
+	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
 		free(driver);
@@ -403,5 +410,25 @@
 	}
 	
-	/* Initialize mutex for list of devices owned by this driver */
+	/*
+	 * Create connection to the driver
+	 */
+	ipc_call_t call;
+	ipc_callid_t callid = async_get_call(&call);
+	
+	if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
+		free(driver->name);
+		free(driver);
+		ipc_answer_0(callid, ENOTSUP);
+		ipc_answer_0(iid, ENOTSUP);
+		return NULL;
+	}
+	
+	driver->phone = IPC_GET_ARG5(call);
+	ipc_answer_0(callid, EOK);
+	
+	/*
+	 * Initialize mutex for list of devices
+	 * owned by this driver
+	 */
 	fibril_mutex_initialize(&driver->devices_mutex);
 	
@@ -410,24 +437,4 @@
 	 */
 	list_initialize(&driver->devices);
-	
-	/*
-	 * Create connection to the driver
-	 */
-	ipc_call_t call;
-	ipc_callid_t callid = async_get_call(&call);
-	
-	if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
-		ipc_answer_0(callid, ENOTSUP);
-		
-		free(driver->name);
-		free(driver);
-		ipc_answer_0(iid, ENOTSUP);
-		return NULL;
-	}
-	
-	driver->phone = IPC_GET_ARG5(call);
-	
-	ipc_answer_0(callid, EOK);
-	
 	list_initialize(&(driver->drivers));
 	
@@ -435,5 +442,6 @@
 	
 	/* TODO:
-	 * check that no driver with name equal to driver->name is registered
+	 * Check that no driver with name equal to
+	 * driver->name is registered
 	 */
 	
@@ -481,5 +489,5 @@
 	fibril_mutex_unlock(&drivers_list_mutex);
 	
-	/* free name and driver */
+	/* Free name and driver */
 	if (driver->name != NULL)
 		free(driver->name);
@@ -502,5 +510,6 @@
 	
 	/* Create new device entry */
-	devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
+	devmap_device_t *device =
+	    (devmap_device_t *) malloc(sizeof(devmap_device_t));
 	if (device == NULL) {
 		ipc_answer_0(iid, ENOMEM);
@@ -510,5 +519,6 @@
 	/* Get fqdn */
 	char *fqdn;
-	int rc = async_string_receive(&fqdn, DEVMAP_NAME_MAXLEN, NULL);
+	int rc = async_data_write_accept((void **) &fqdn, true, 0,
+	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
 		free(device);
@@ -531,6 +541,7 @@
 	devmap_namespace_t *namespace = devmap_namespace_create(ns_name);
 	free(ns_name);
-	if (!namespace) {
+	if (namespace == NULL) {
 		fibril_mutex_unlock(&devices_list_mutex);
+		free(device->name);
 		free(device);
 		ipc_answer_0(iid, ENOMEM);
@@ -543,8 +554,8 @@
 	/* Check that device is not already registered */
 	if (devmap_device_find_name(namespace->name, device->name) != NULL) {
-		printf(NAME ": Device '%s/%s' already registered\n", device->namespace, device->name);
+		printf("%s: Device '%s/%s' already registered\n", NAME,
+		    device->namespace, device->name);
 		devmap_namespace_destroy(namespace);
 		fibril_mutex_unlock(&devices_list_mutex);
-		free(device->namespace);
 		free(device->name);
 		free(device);
@@ -601,4 +612,5 @@
 	
 	if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
+		fibril_mutex_unlock(&devices_list_mutex);
 		ipc_answer_0(callid, ENOENT);
 		return;
@@ -622,5 +634,6 @@
 	
 	/* Get fqdn */
-	int rc = async_string_receive(&fqdn, DEVMAP_NAME_MAXLEN, NULL);
+	int rc = async_data_write_accept((void **) &fqdn, true, 0,
+	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(iid, rc);
@@ -665,7 +678,8 @@
 		return;
 	}
+	
+	ipc_answer_1(iid, EOK, dev->handle);
+	
 	fibril_mutex_unlock(&devices_list_mutex);
-	
-	ipc_answer_1(iid, EOK, dev->handle);
 	free(ns_name);
 	free(name);
@@ -683,5 +697,6 @@
 	
 	/* Get device name */
-	int rc = async_string_receive(&name, DEVMAP_NAME_MAXLEN, NULL);
+	int rc = async_data_write_accept((void **) &name, true, 0,
+	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(iid, rc);
@@ -715,7 +730,8 @@
 		return;
 	}
+	
+	ipc_answer_1(iid, EOK, namespace->handle);
+	
 	fibril_mutex_unlock(&devices_list_mutex);
-	
-	ipc_answer_1(iid, EOK, namespace->handle);
 	free(name);
 }
@@ -725,7 +741,9 @@
 	fibril_mutex_lock(&devices_list_mutex);
 	
-	devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
+	devmap_namespace_t *namespace =
+	    devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
 	if (namespace == NULL) {
-		devmap_device_t *dev = devmap_device_find_handle(IPC_GET_ARG1(*icall));
+		devmap_device_t *dev =
+		    devmap_device_find_handle(IPC_GET_ARG1(*icall));
 		if (dev == NULL)
 			ipc_answer_1(iid, EOK, DEV_HANDLE_NONE);
@@ -749,5 +767,6 @@
 	fibril_mutex_lock(&devices_list_mutex);
 	
-	devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
+	devmap_namespace_t *namespace =
+	    devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
 	if (namespace == NULL)
 		ipc_answer_0(iid, EEXISTS);
@@ -778,4 +797,5 @@
 	size_t count = size / sizeof(dev_desc_t);
 	if (count != list_count(&namespaces_list)) {
+		fibril_mutex_unlock(&devices_list_mutex);
 		ipc_answer_0(callid, EOVERFLOW);
 		ipc_answer_0(iid, EOVERFLOW);
@@ -785,4 +805,5 @@
 	dev_desc_t *desc = (dev_desc_t *) malloc(size);
 	if (desc == NULL) {
+		fibril_mutex_unlock(&devices_list_mutex);
 		ipc_answer_0(callid, ENOMEM);
 		ipc_answer_0(iid, ENOMEM);
@@ -790,14 +811,14 @@
 	}
 	
-	link_t *item = namespaces_list.next;
+	link_t *item;
 	size_t pos = 0;
-	while (item != &namespaces_list) {
-		devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
+	for (item = namespaces_list.next; item != &namespaces_list;
+	    item = item->next) {
+		devmap_namespace_t *namespace =
+		    list_get_instance(item, devmap_namespace_t, namespaces);
 		
 		desc[pos].handle = namespace->handle;
 		str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);
 		pos++;
-		
-		item = item->next;
 	}
 	
@@ -831,5 +852,6 @@
 	fibril_mutex_lock(&devices_list_mutex);
 	
-	devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
+	devmap_namespace_t *namespace =
+	    devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
 	if (namespace == NULL) {
 		fibril_mutex_unlock(&devices_list_mutex);
@@ -841,4 +863,5 @@
 	size_t count = size / sizeof(dev_desc_t);
 	if (count != namespace->refcnt) {
+		fibril_mutex_unlock(&devices_list_mutex);
 		ipc_answer_0(callid, EOVERFLOW);
 		ipc_answer_0(iid, EOVERFLOW);
@@ -848,4 +871,5 @@
 	dev_desc_t *desc = (dev_desc_t *) malloc(size);
 	if (desc == NULL) {
+		fibril_mutex_unlock(&devices_list_mutex);
 		ipc_answer_0(callid, ENOMEM);
 		ipc_answer_0(iid, EREFUSED);
@@ -853,8 +877,9 @@
 	}
 	
-	link_t *item = devices_list.next;
+	link_t *item;
 	size_t pos = 0;
-	while (item != &devices_list) {
-		devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
+	for (item = devices_list.next; item != &devices_list; item = item->next) {
+		devmap_device_t *device =
+		    list_get_instance(item, devmap_device_t, devices);
 		
 		if (device->namespace == namespace) {
@@ -863,6 +888,4 @@
 			pos++;
 		}
-		
-		item = item->next;
 	}
 	
@@ -905,5 +928,6 @@
 	}
 	
-	devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
+	devmap_device_t *device =
+	    (devmap_device_t *) malloc(sizeof(devmap_device_t));
 	if (device == NULL) {
 		fibril_mutex_unlock(&null_devices_mutex);
@@ -915,5 +939,5 @@
 	
 	devmap_namespace_t *namespace = devmap_namespace_create("null");
-	if (!namespace) {
+	if (namespace == NULL) {
 		fibril_mutex_lock(&devices_list_mutex);
 		fibril_mutex_unlock(&null_devices_mutex);
@@ -945,9 +969,14 @@
 static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
 {
+	ipcarg_t i = IPC_GET_ARG1(*icall);
+	if (i >= NULL_DEVICES) {
+		ipc_answer_0(iid, ELIMIT);
+		return;
+	}
+	
 	fibril_mutex_lock(&null_devices_mutex);
 	
-	ipcarg_t i = IPC_GET_ARG1(*icall);
-	
 	if (null_devices[i] == NULL) {
+		fibril_mutex_unlock(&null_devices_mutex);
 		ipc_answer_0(iid, ENOENT);
 		return;
@@ -961,5 +990,4 @@
 	
 	fibril_mutex_unlock(&null_devices_mutex);
-	
 	ipc_answer_0(iid, EOK);
 }
@@ -1117,8 +1145,8 @@
 int main(int argc, char *argv[])
 {
-	printf(NAME ": HelenOS Device Mapper\n");
+	printf("%s: HelenOS Device Mapper\n", NAME);
 	
 	if (!devmap_init()) {
-		printf(NAME ": Error while initializing service\n");
+		printf("%s: Error while initializing service\n", NAME);
 		return -1;
 	}
@@ -1132,5 +1160,5 @@
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
 	async_manager();
 	
Index: uspace/srv/drivers/isa/Makefile
===================================================================
--- uspace/srv/drivers/isa/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/drivers/isa/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,12 +27,10 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBC_PREFIX)/libc.a
-
-OUTPUT = isa
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = isa
 
 SOURCES = \
 	isa.c
 
-include ../../Makefile.common
-
-EXTRA_CFLAGS = -I$(LIBDRV_PREFIX)/include
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/drivers/isa/isa.c
===================================================================
--- uspace/srv/drivers/isa/isa.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/drivers/isa/isa.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -42,5 +42,5 @@
 #include <fibril_synch.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <ctype.h>
 #include <macros.h>
@@ -136,5 +136,5 @@
 	bool opened = false;
 	int fd;		
-	off_t len = 0;
+	size_t len = 0;
 	
 	fd = open(conf_path, O_RDONLY);
@@ -458,5 +458,5 @@
 }
 
-static char * parse_dev_conf(char *conf, device_t *parent)
+static void parse_dev_conf(char *conf, device_t *parent)
 {
 	while (NULL != conf && 0 != *conf) {
Index: uspace/srv/drivers/ns8250/Makefile
===================================================================
--- uspace/srv/drivers/ns8250/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/drivers/ns8250/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,12 +27,10 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBC_PREFIX)/libc.a
-
-OUTPUT = ns8250
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = ns8250
 
 SOURCES = \
 	ns8250.c
 
-include ../../Makefile.common
-
-EXTRA_CFLAGS = -I$(LIBDRV_PREFIX)/include
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/drivers/ns8250/ns8250.c
===================================================================
--- uspace/srv/drivers/ns8250/ns8250.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/drivers/ns8250/ns8250.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -42,5 +42,5 @@
 #include <fibril_synch.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <ctype.h>
 #include <macros.h>
Index: uspace/srv/drivers/pciintel/Makefile
===================================================================
--- uspace/srv/drivers/pciintel/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/drivers/pciintel/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,12 +27,10 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBC_PREFIX)/libc.a
-
-OUTPUT = pciintel
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = pciintel
 
 SOURCES = \
 	pci.c
 
-include ../../Makefile.common
-
-EXTRA_CFLAGS = -I$(LIBDRV_PREFIX)/include
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/drivers/pciintel/pci.c
===================================================================
--- uspace/srv/drivers/pciintel/pci.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/drivers/pciintel/pci.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -41,5 +41,5 @@
 #include <bool.h>
 #include <fibril_synch.h>
-#include <string.h>
+#include <str.h>
 #include <ctype.h>
 #include <macros.h>
@@ -221,7 +221,9 @@
 	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
 	match_id_t *match_id = NULL;	
+	char *match_id_str;	
 	match_id = create_match_id();
 	if (NULL != match_id) {
-		asprintf(&match_id->id, "pci/ven=%04x&dev=%04x", dev_data->vendor_id, dev_data->device_id);
+		asprintf(&match_id_str, "pci/ven=%04x&dev=%04x", dev_data->vendor_id, dev_data->device_id);
+		match_id->id = match_id_str;
 		match_id->score = 90;
 		add_match_id(&dev->match_ids, match_id);
Index: uspace/srv/drivers/root/Makefile
===================================================================
--- uspace/srv/drivers/root/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/drivers/root/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,12 +27,10 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBC_PREFIX)/libc.a
-
-OUTPUT = root
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = root
 
 SOURCES = \
 	root.c
 
-include ../../Makefile.common
-
-EXTRA_CFLAGS = -I$(LIBDRV_PREFIX)/include
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/drivers/root/root.c
===================================================================
--- uspace/srv/drivers/root/root.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/drivers/root/root.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -42,5 +42,5 @@
 #include <fibril_synch.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <ctype.h>
 #include <macros.h>
Index: uspace/srv/drivers/rootia32/Makefile
===================================================================
--- uspace/srv/drivers/rootia32/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/drivers/rootia32/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,12 +27,10 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBC_PREFIX)/libc.a
-
-OUTPUT = rootia32
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = rootia32
 
 SOURCES = \
 	rootia32.c
 
-include ../../Makefile.common
-
-EXTRA_CFLAGS = -I$(LIBDRV_PREFIX)/include
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/drivers/rootia32/rootia32.c
===================================================================
--- uspace/srv/drivers/rootia32/rootia32.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/drivers/rootia32/rootia32.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -42,5 +42,5 @@
 #include <fibril_synch.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <ctype.h>
 #include <macros.h>
@@ -60,5 +60,5 @@
 
 static int rootia32_add_device(device_t *dev);
-static bool rootia32_init();
+static void root_ia32_init(void);
 
 /** The root device driver's standard operations.
Index: uspace/srv/fs/devfs/Makefile
===================================================================
--- uspace/srv/fs/devfs/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/devfs/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,8 +29,7 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBFS_PREFIX)/libfs.a $(LIBC_PREFIX)/libc.a
+LIBS = $(LIBFS_PREFIX)/libfs.a
 EXTRA_CFLAGS += -I$(LIBFS_PREFIX)
-
-OUTPUT = devfs
+BINARY = devfs
 
 SOURCES = \
@@ -38,3 +37,3 @@
 	devfs_ops.c
 
-include ../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -37,8 +37,9 @@
 
 #include <ipc/ipc.h>
+#include <macros.h>
 #include <bool.h>
 #include <errno.h>
 #include <malloc.h>
-#include <string.h>
+#include <str.h>
 #include <libfs.h>
 #include <fibril_synch.h>
@@ -337,5 +338,5 @@
 }
 
-static size_t devfs_size_get(fs_node_t *fn)
+static aoff64_t devfs_size_get(fs_node_t *fn)
 {
 	return 0;
@@ -419,5 +420,6 @@
 	
 	/* Accept the mount options */
-	ipcarg_t retval = async_string_receive(&opts, 0, NULL);
+	ipcarg_t retval = async_data_write_accept((void **) &opts, true, 0, 0,
+	    0, NULL);
 	if (retval != EOK) {
 		ipc_answer_0(rid, retval);
@@ -462,5 +464,6 @@
 {
 	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	off_t pos = (off_t) IPC_GET_ARG3(*request);
+	aoff64_t pos =
+	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
 	
 	if (index == 0) {
@@ -596,6 +599,4 @@
 {
 	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	off_t pos = (off_t) IPC_GET_ARG3(*request);
-	
 	if (index == 0) {
 		ipc_answer_0(rid, ENOTSUP);
Index: uspace/srv/fs/fat/Makefile
===================================================================
--- uspace/srv/fs/fat/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/fat/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,8 +29,7 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a $(LIBC_PREFIX)/libc.a
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a
 EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX)
-
-OUTPUT = fat
+BINARY = fat
 
 SOURCES = \
@@ -41,3 +40,3 @@
 	fat_fat.c
 
-include ../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/fat/fat.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -89,5 +89,5 @@
 			uint16_t	signature;
 		} __attribute__ ((packed));
-		struct fat32 {
+		struct {
 			/* FAT32 only */
 			/** Sectors per FAT. */
@@ -119,6 +119,6 @@
 			/** Signature. */
 			uint16_t	signature;
-		} __attribute__ ((packed));
-	}; 
+		} fat32 __attribute__ ((packed));
+	};
 } __attribute__ ((packed)) fat_bs_t;
 
@@ -194,5 +194,5 @@
 	/** FAT in-core node free list link. */
 	link_t			ffn_link;
-	size_t			size;
+	aoff64_t		size;
 	unsigned		lnkcnt;
 	unsigned		refcnt;
Index: uspace/srv/fs/fat/fat_dentry.c
===================================================================
--- uspace/srv/fs/fat/fat_dentry.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/fat/fat_dentry.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -38,5 +38,5 @@
 #include "fat_dentry.h"
 #include <ctype.h>
-#include <string.h>
+#include <str.h>
 
 static bool is_d_char(const char ch)
@@ -82,5 +82,6 @@
 bool fat_dentry_name_verify(const char *name)
 {
-	unsigned i, dot;
+	unsigned int i;
+	unsigned int dot = 0;
 	bool dot_found = false;
 	
Index: uspace/srv/fs/fat/fat_fat.c
===================================================================
--- uspace/srv/fs/fat/fat_fat.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/fat/fat_fat.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -93,5 +93,5 @@
 
 	while (clst < FAT_CLST_LAST1 && clusters < max_clusters) {
-		bn_t fsec;	/* sector offset relative to FAT1 */
+		aoff64_t fsec;	/* sector offset relative to FAT1 */
 		unsigned fidx;	/* FAT1 entry index */
 
@@ -135,5 +135,5 @@
 int
 _fat_block_get(block_t **block, fat_bs_t *bs, dev_handle_t dev_handle,
-    fat_cluster_t firstc, bn_t bn, int flags)
+    fat_cluster_t firstc, aoff64_t bn, int flags)
 {
 	unsigned bps;
@@ -148,4 +148,10 @@
 	int rc;
 
+	/*
+	 * This function can only operate on non-zero length files.
+	 */
+	if (firstc == FAT_CLST_RES0)
+		return ELIMIT;
+
 	bps = uint16_t_le2host(bs->bps);
 	rscnt = uint16_t_le2host(bs->rscnt);
@@ -190,10 +196,10 @@
  * @return		EOK on success or a negative error code.
  */
-int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
+int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
 {
 	uint16_t bps;
 	unsigned spc;
 	block_t *b;
-	off_t o, boundary;
+	aoff64_t o, boundary;
 	int rc;
 
@@ -361,5 +367,5 @@
 	uint16_t rscnt;
 	uint16_t sf;
-	uint16_t ts;
+	uint32_t ts;
 	unsigned rde;
 	unsigned rds;
@@ -379,5 +385,7 @@
 	sf = uint16_t_le2host(bs->sec_per_fat);
 	rde = uint16_t_le2host(bs->root_ent_max);
-	ts = uint16_t_le2host(bs->totsec16);
+	ts = (uint32_t) uint16_t_le2host(bs->totsec16);
+	if (ts == 0)
+		ts = uint32_t_le2host(bs->totsec32);
 
 	rds = (sizeof(fat_dentry_t) * rde) / bps;
Index: uspace/srv/fs/fat/fat_fat.h
===================================================================
--- uspace/srv/fs/fat/fat_fat.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/fat/fat_fat.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -69,6 +69,6 @@
 
 extern int _fat_block_get(block_t **, struct fat_bs *, dev_handle_t,
-    fat_cluster_t, bn_t, int);
-  
+    fat_cluster_t, aoff64_t, int);
+
 extern int fat_append_clusters(struct fat_bs *, struct fat_node *,
     fat_cluster_t);
@@ -85,5 +85,5 @@
     fat_cluster_t, fat_cluster_t);
 extern int fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t,
-    off_t);
+    aoff64_t);
 extern int fat_zero_cluster(struct fat_bs *, dev_handle_t, fat_cluster_t);
 extern int fat_sanity_check(struct fat_bs *, dev_handle_t);
Index: uspace/srv/fs/fat/fat_idx.c
===================================================================
--- uspace/srv/fs/fat/fat_idx.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/fat/fat_idx.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -39,5 +39,5 @@
 #include "../../vfs/vfs.h"
 #include <errno.h>
-#include <string.h>
+#include <str.h>
 #include <adt/hash_table.h>
 #include <adt/list.h>
@@ -164,4 +164,6 @@
 		assert((keys == 1) || (keys == 3));
 	}
+
+	return 0;
 }
 
@@ -219,4 +221,6 @@
 		assert((keys == 1) || (keys == 2));
 	}
+
+	return 0;
 }
 
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/fat/fat_ops.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -45,7 +45,8 @@
 #include <ipc/services.h>
 #include <ipc/devmap.h>
+#include <macros.h>
 #include <async.h>
 #include <errno.h>
-#include <string.h>
+#include <str.h>
 #include <byteorder.h>
 #include <adt/hash_table.h>
@@ -79,5 +80,5 @@
 static int fat_has_children(bool *, fs_node_t *);
 static fs_index_t fat_index_get(fs_node_t *);
-static size_t fat_size_get(fs_node_t *);
+static aoff64_t fat_size_get(fs_node_t *);
 static unsigned fat_lnkcnt_get(fs_node_t *);
 static char fat_plb_get_char(unsigned);
@@ -722,46 +723,49 @@
 	fibril_mutex_lock(&childp->idx->lock);
 	
-	/*
-	 * If possible, create the Sub-directory Identifier Entry and the
-	 * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries
-	 * are not mandatory according to Standard ECMA-107 and HelenOS VFS does
-	 * not use them anyway, so this is rather a sign of our good will.
-	 */
-	rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE);
-	if (rc != EOK) {
+	if (childp->type == FAT_DIRECTORY) {
 		/*
-		 * Rather than returning an error, simply skip the creation of
-		 * these two entries.
+		 * If possible, create the Sub-directory Identifier Entry and
+		 * the Sub-directory Parent Pointer Entry (i.e. "." and "..").
+		 * These entries are not mandatory according to Standard
+		 * ECMA-107 and HelenOS VFS does not use them anyway, so this is
+		 * rather a sign of our good will.
 		 */
-		goto skip_dots;
-	}
-	d = (fat_dentry_t *)b->data;
-	if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
-	    str_cmp(d->name, FAT_NAME_DOT) == 0) {
-	   	memset(d, 0, sizeof(fat_dentry_t));
-	   	str_cpy(d->name, 8, FAT_NAME_DOT);
-		str_cpy(d->ext, 3, FAT_EXT_PAD);
-		d->attr = FAT_ATTR_SUBDIR;
-		d->firstc = host2uint16_t_le(childp->firstc);
-		/* TODO: initialize also the date/time members. */
-	}
-	d++;
-	if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
-	    str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) {
-		memset(d, 0, sizeof(fat_dentry_t));
-		str_cpy(d->name, 8, FAT_NAME_DOT_DOT);
-		str_cpy(d->ext, 3, FAT_EXT_PAD);
-		d->attr = FAT_ATTR_SUBDIR;
-		d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
-		    host2uint16_t_le(FAT_CLST_RES0) :
-		    host2uint16_t_le(parentp->firstc);
-		/* TODO: initialize also the date/time members. */
-	}
-	b->dirty = true;		/* need to sync block */
-	/*
-	 * Ignore the return value as we would have fallen through on error
-	 * anyway.
-	 */
-	(void) block_put(b);
+		rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			/*
+			 * Rather than returning an error, simply skip the
+			 * creation of these two entries.
+			 */
+			goto skip_dots;
+		}
+		d = (fat_dentry_t *) b->data;
+		if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
+		    (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
+			memset(d, 0, sizeof(fat_dentry_t));
+			str_cpy((char *) d->name, 8, FAT_NAME_DOT);
+			str_cpy((char *) d->ext, 3, FAT_EXT_PAD);
+			d->attr = FAT_ATTR_SUBDIR;
+			d->firstc = host2uint16_t_le(childp->firstc);
+			/* TODO: initialize also the date/time members. */
+		}
+		d++;
+		if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
+		    (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
+			memset(d, 0, sizeof(fat_dentry_t));
+			str_cpy((char *) d->name, 8, FAT_NAME_DOT_DOT);
+			str_cpy((char *) d->ext, 3, FAT_EXT_PAD);
+			d->attr = FAT_ATTR_SUBDIR;
+			d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
+			    host2uint16_t_le(FAT_CLST_RES0) :
+			    host2uint16_t_le(parentp->firstc);
+			/* TODO: initialize also the date/time members. */
+		}
+		b->dirty = true;		/* need to sync block */
+		/*
+		 * Ignore the return value as we would have fallen through on error
+		 * anyway.
+		 */
+		(void) block_put(b);
+	}
 skip_dots:
 
@@ -912,5 +916,5 @@
 }
 
-size_t fat_size_get(fs_node_t *fn)
+aoff64_t fat_size_get(fs_node_t *fn)
 {
 	return FAT_NODE(fn)->size;
@@ -977,5 +981,5 @@
 	/* Accept the mount options */
 	char *opts;
-	int rc = async_string_receive(&opts, 0, NULL);
+	int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
 	
 	if (rc != EOK) {
@@ -1154,7 +1158,8 @@
 void fat_read(ipc_callid_t rid, ipc_call_t *request)
 {
-	dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	off_t pos = (off_t)IPC_GET_ARG3(*request);
+	dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
+	aoff64_t pos =
+	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1220,5 +1225,5 @@
 	} else {
 		unsigned bnum;
-		off_t spos = pos;
+		aoff64_t spos = pos;
 		char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
 		fat_dentry_t *d;
@@ -1236,5 +1241,5 @@
 		bnum = (pos * sizeof(fat_dentry_t)) / bps;
 		while (bnum < nodep->size / bps) {
-			off_t o;
+			aoff64_t o;
 
 			rc = fat_block_get(&b, bs, nodep, bnum,
@@ -1292,7 +1297,8 @@
 void fat_write(ipc_callid_t rid, ipc_call_t *request)
 {
-	dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	off_t pos = (off_t)IPC_GET_ARG3(*request);
+	dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
+	aoff64_t pos =
+	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1303,5 +1309,5 @@
 	unsigned spc;
 	unsigned bpc;		/* bytes per cluster */
-	off_t boundary;
+	aoff64_t boundary;
 	int flags = BLOCK_FLAGS_NONE;
 	int rc;
@@ -1449,7 +1455,8 @@
 void fat_truncate(ipc_callid_t rid, ipc_call_t *request)
 {
-	dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	size_t size = (off_t)IPC_GET_ARG3(*request);
+	dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
+	aoff64_t size =
+	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
 	fs_node_t *fn;
 	fat_node_t *nodep;
Index: uspace/srv/fs/tmpfs/Makefile
===================================================================
--- uspace/srv/fs/tmpfs/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/tmpfs/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,8 +29,7 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a $(LIBC_PREFIX)/libc.a
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a
 EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX)
-
-OUTPUT = tmpfs
+BINARY = tmpfs
 
 SOURCES = \
@@ -39,3 +38,3 @@
 	tmpfs_dump.c
 
-include ../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/tmpfs/tmpfs.h
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,5 +29,5 @@
 /** @addtogroup fs
  * @{
- */ 
+ */
 
 #ifndef TMPFS_TMPFS_H_
@@ -40,8 +40,4 @@
 #include <bool.h>
 #include <adt/hash_table.h>
-
-#ifndef dprintf
-#define dprintf(...)	printf(__VA_ARGS__)
-#endif
 
 #define TMPFS_NODE(node)	((node) ? (tmpfs_node_t *)(node)->data : NULL)
Index: uspace/srv/fs/tmpfs/tmpfs_dump.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_dump.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/tmpfs/tmpfs_dump.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -41,5 +41,5 @@
 #include <errno.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <sys/types.h>
 #include <as.h>
@@ -55,6 +55,6 @@
 
 static bool
-tmpfs_restore_recursion(dev_handle_t dev, off_t *bufpos, size_t *buflen,
-    off_t *pos, fs_node_t *pfn)
+tmpfs_restore_recursion(dev_handle_t dev, size_t *bufpos, size_t *buflen,
+    aoff64_t *pos, fs_node_t *pfn)
 {
 	struct rdentry entry;
@@ -171,7 +171,7 @@
 		return false; 
 	
-	off_t bufpos = 0;
+	size_t bufpos = 0;
 	size_t buflen = 0;
-	off_t pos = 0;
+	aoff64_t pos = 0;
 	
 	char tag[6];
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,5 +29,5 @@
 /** @addtogroup fs
  * @{
- */ 
+ */
 
 /**
@@ -40,9 +40,11 @@
 #include "../../vfs/vfs.h"
 #include <ipc/ipc.h>
+#include <macros.h>
+#include <limits.h>
 #include <async.h>
 #include <errno.h>
 #include <atomic.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <stdio.h>
 #include <assert.h>
@@ -93,5 +95,5 @@
 }
 
-static size_t tmpfs_size_get(fs_node_t *fn)
+static aoff64_t tmpfs_size_get(fs_node_t *fn)
 {
 	return TMPFS_NODE(fn)->size;
@@ -168,6 +170,8 @@
 		    (nodep->index == key[NODES_KEY_INDEX]));
 	default:
-		abort();
-	}
+		assert((keys == 1) || (keys == 2));
+	}
+
+	return 0;
 }
 
@@ -439,11 +443,21 @@
 {
 	dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
-	
-	/* Accept the mount options */
+	fs_node_t *rootfn;
+	int rc;
+	
+	/* Accept the mount options. */
 	char *opts;
-	int rc = async_string_receive(&opts, 0, NULL);
-	
+	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(rid, rc);
+		return;
+	}
+
+	/* Check if this device is not already mounted. */
+	rc = tmpfs_root_get(&rootfn, dev_handle);
+	if ((rc == EOK) && (rootfn)) {
+		(void) tmpfs_node_put(rootfn);
+		free(opts);
+		ipc_answer_0(rid, EEXIST);
 		return;
 	}
@@ -456,5 +470,4 @@
 	}
 
-	fs_node_t *rootfn;
 	rc = tmpfs_root_get(&rootfn, dev_handle);
 	assert(rc == EOK);
@@ -498,8 +511,9 @@
 void tmpfs_read(ipc_callid_t rid, ipc_call_t *request)
 {
-	dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	off_t pos = (off_t)IPC_GET_ARG3(*request);
-
+	dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
+	aoff64_t pos =
+	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	
 	/*
 	 * Lookup the respective TMPFS node.
@@ -517,5 +531,5 @@
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
-
+	
 	/*
 	 * Receive the read request.
@@ -524,5 +538,5 @@
 	size_t size;
 	if (!async_data_read_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);	
+		ipc_answer_0(callid, EINVAL);
 		ipc_answer_0(rid, EINVAL);
 		return;
@@ -531,5 +545,5 @@
 	size_t bytes;
 	if (nodep->type == TMPFS_FILE) {
-		bytes = max(0, min(nodep->size - pos, size));
+		bytes = min(nodep->size - pos, size);
 		(void) async_data_read_finalize(callid, nodep->data + pos,
 		    bytes);
@@ -537,5 +551,5 @@
 		tmpfs_dentry_t *dentryp;
 		link_t *lnk;
-		int i;
+		aoff64_t i;
 		
 		assert(nodep->type == TMPFS_DIRECTORY);
@@ -547,5 +561,5 @@
 		 */
 		for (i = 0, lnk = nodep->cs_head.next;
-		    i < pos && lnk != &nodep->cs_head;
+		    (i < pos) && (lnk != &nodep->cs_head);
 		    i++, lnk = lnk->next)
 			;
@@ -572,8 +586,9 @@
 void tmpfs_write(ipc_callid_t rid, ipc_call_t *request)
 {
-	dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	off_t pos = (off_t)IPC_GET_ARG3(*request);
-
+	dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
+	aoff64_t pos =
+	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	
 	/*
 	 * Lookup the respective TMPFS node.
@@ -636,11 +651,61 @@
 void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request)
 {
+	dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
+	aoff64_t size =
+	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	
+	/*
+	 * Lookup the respective TMPFS node.
+	 */
+	unsigned long key[] = {
+		[NODES_KEY_DEV] = dev_handle,
+		[NODES_KEY_INDEX] = index
+	};
+	link_t *hlp = hash_table_find(&nodes, key);
+	if (!hlp) {
+		ipc_answer_0(rid, ENOENT);
+		return;
+	}
+	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
+	    nh_link);
+	
+	if (size == nodep->size) {
+		ipc_answer_0(rid, EOK);
+		return;
+	}
+	
+	if (size > SIZE_MAX) {
+		ipc_answer_0(rid, ENOMEM);
+		return;
+	}
+	
+	void *newdata = realloc(nodep->data, size);
+	if (!newdata) {
+		ipc_answer_0(rid, ENOMEM);
+		return;
+	}
+	
+	if (size > nodep->size) {
+		size_t delta = size - nodep->size;
+		memset(newdata + nodep->size, 0, delta);
+	}
+	
+	nodep->size = size;
+	nodep->data = newdata;
+	ipc_answer_0(rid, EOK);
+}
+
+void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
+{
+	ipc_answer_0(rid, EOK);
+}
+
+void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
+{
 	dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
 	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	size_t size = (off_t)IPC_GET_ARG3(*request);
-
-	/*
-	 * Lookup the respective TMPFS node.
-	 */
+	int rc;
+
 	link_t *hlp;
 	unsigned long key[] = {
@@ -655,47 +720,4 @@
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
-
-	if (size == nodep->size) {
-		ipc_answer_0(rid, EOK);
-		return;
-	}
-
-	void *newdata = realloc(nodep->data, size);
-	if (!newdata) {
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	if (size > nodep->size) {
-		size_t delta = size - nodep->size;
-		memset(newdata + nodep->size, 0, delta);
-	}
-	nodep->size = size;
-	nodep->data = newdata;
-	ipc_answer_0(rid, EOK);
-}
-
-void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	ipc_answer_0(rid, EOK);
-}
-
-void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	int rc;
-
-	link_t *hlp;
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = dev_handle,
-		[NODES_KEY_INDEX] = index
-	};
-	hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		ipc_answer_0(rid, ENOENT);
-		return;
-	}
-	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
-	    nh_link);
 	rc = tmpfs_destroy_node(FS_NODE(nodep));
 	ipc_answer_0(rid, rc);
Index: uspace/srv/hid/adb_mouse/Makefile
===================================================================
--- uspace/srv/hid/adb_mouse/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/adb_mouse/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -28,8 +28,6 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBC_PREFIX)/libc.a
 EXTRA_CFLAGS = -Iinclude
-
-OUTPUT = adb_ms
+BINARY = adb_ms
 
 SOURCES = \
@@ -37,3 +35,3 @@
 	adb_dev.c
 
-include ../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/adb_mouse/adb_dev.c
===================================================================
--- uspace/srv/hid/adb_mouse/adb_dev.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/adb_mouse/adb_dev.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -50,5 +50,5 @@
 int adb_dev_init(void)
 {
-	char *input = "/dev/adb/mouse";
+	const char *input = "/dev/adb/mouse";
 	int input_fd;
 
Index: uspace/srv/hid/char_mouse/Makefile
===================================================================
--- uspace/srv/hid/char_mouse/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/char_mouse/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,8 +29,6 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBC_PREFIX)/libc.a
 EXTRA_CFLAGS = -Iinclude
-
-OUTPUT = char_ms
+BINARY = char_ms
 
 SOURCES = \
@@ -39,3 +37,3 @@
 	chardev.c
 
-include ../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/char_mouse/chardev.c
===================================================================
--- uspace/srv/hid/char_mouse/chardev.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/char_mouse/chardev.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -48,9 +48,9 @@
 static int dev_phone;
 
-#define NAME "kbd"
+#define NAME "char_mouse"
 
 int mouse_port_init(void)
 {
-	char *input = "/dev/char/ps2b";
+	const char *input = "/dev/char/ps2b";
 	int input_fd;
 
Index: uspace/srv/hid/char_mouse/proto/ps2.c
===================================================================
--- uspace/srv/hid/char_mouse/proto/ps2.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/char_mouse/proto/ps2.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -36,8 +36,12 @@
 
 #include <stdio.h>
+#include <mouse_port.h>
+#include <char_mouse.h>
 #include <mouse_proto.h>
-#include <char_mouse.h>
 
 #define BUFSIZE 3
+
+#define PS2_MOUSE_OUT_INIT  0xf4
+#define PS2_MOUSE_ACK       0xfa
 
 typedef struct {
@@ -67,4 +71,5 @@
 int mouse_proto_init(void)
 {
+	mouse_port_write(PS2_MOUSE_OUT_INIT);
 	return 0;
 }
Index: uspace/srv/hid/console/Makefile
===================================================================
--- uspace/srv/hid/console/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/console/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -28,13 +28,30 @@
 #
 
-include Makefile.common
+USPACE_PREFIX = ../../..
+BINARY = console
 
-.PHONY: all clean
+GENERIC_SOURCES = \
+	console.c \
+	keybuffer.c \
+	gcons.c
 
-all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
-	-[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
-	$(MAKE) -f Makefile.build PRECHECK=$(PRECHECK)
+IMAGES = \
+	gfx/helenos.ppm \
+	gfx/nameic.ppm \
+	gfx/cons_selected.ppm \
+	gfx/cons_idle.ppm \
+	gfx/cons_has_data.ppm \
+	gfx/cons_kernel.ppm \
+	gfx/anim_1.ppm \
+	gfx/anim_2.ppm \
+	gfx/anim_3.ppm \
+	gfx/anim_4.ppm
 
-clean:
-	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
-	find . -name '*.o' -follow -exec rm \{\} \;
+SOURCES = \
+	$(GENERIC_SOURCES) \
+	$(IMAGES)
+
+include $(USPACE_PREFIX)/Makefile.common
+
+%.o: %.ppm
+	$(OBJCOPY) -I binary -O $(BFD_NAME) -B $(BFD_ARCH) $< $@
Index: uspace/srv/hid/console/Makefile.build
===================================================================
--- uspace/srv/hid/console/Makefile.build	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ 	(revision )
@@ -1,82 +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.
-#
-
-## Setup toolchain
-#
-
-include Makefile.common
-include $(LIBC_PREFIX)/Makefile.toolchain
-
-## Sources
-#
-
-SOURCES = \
-	console.c \
-	screenbuffer.c \
-	keybuffer.c \
-	gcons.c
-
-IMAGES = \
-	gfx/helenos.ppm \
-	gfx/nameic.ppm \
-	gfx/cons_selected.ppm \
-	gfx/cons_idle.ppm \
-	gfx/cons_has_data.ppm \
-	gfx/cons_kernel.ppm \
-	gfx/anim_1.ppm \
-	gfx/anim_2.ppm \
-	gfx/anim_3.ppm \
-	gfx/anim_4.ppm
-
-OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) $(addsuffix .o,$(basename $(IMAGES)))
-
-.PHONY: all
-
-all: $(OUTPUT) $(OUTPUT).disasm
-
--include $(DEPEND)
-
-$(OUTPUT).disasm: $(OUTPUT)
-	$(OBJDUMP) -d $< > $@
-
-$(OUTPUT): $(OBJECTS) $(LIBS)
-	$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
-
-%.o: %.c $(DEPEND)
-	$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
-ifeq ($(PRECHECK),y)
-	$(JOBFILE) $(JOB) $< $@ cc core $(DEFS) $(CFLAGS)
-endif
-
-%.o: %.ppm
-	$(OBJCOPY) -I binary -O $(BFD_NAME) -B $(BFD_ARCH) $< $@
-
-$(DEPEND):
-	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > $@ 2> /dev/null
-	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
Index: uspace/srv/hid/console/Makefile.common
===================================================================
--- uspace/srv/hid/console/Makefile.common	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ 	(revision )
@@ -1,40 +1,0 @@
-#
-# Copyright (c) 2005 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.
-#
-
-
-## Common names
-#
-
-LIBC_PREFIX = ../../../lib/libc
-SOFTINT_PREFIX = ../../../lib/softint
-LIBS = $(LIBC_PREFIX)/libc.a
-
-DEPEND = Makefile.depend
-DEPEND_PREV = $(DEPEND).prev
-JOB = console.job
-OUTPUT = console
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/console/console.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -47,5 +47,5 @@
 #include <sys/mman.h>
 #include <stdio.h>
-#include <string.h>
+#include <str.h>
 #include <sysinfo.h>
 #include <event.h>
@@ -54,9 +54,11 @@
 #include <vfs/vfs.h>
 #include <fibril_synch.h>
+#include <io/style.h>
+#include <io/screenbuffer.h>
 
 #include "console.h"
 #include "gcons.h"
 #include "keybuffer.h"
-#include "screenbuffer.h"
+
 
 #define NAME       "console"
@@ -71,8 +73,8 @@
 /** Information about framebuffer */
 struct {
-	int phone;      /**< Framebuffer phone */
-	ipcarg_t cols;  /**< Framebuffer columns */
-	ipcarg_t rows;  /**< Framebuffer rows */
-	int color_cap;  /**< Color capabilities (FB_CCAP_xxx) */
+	int phone;           /**< Framebuffer phone */
+	ipcarg_t cols;       /**< Framebuffer columns */
+	ipcarg_t rows;       /**< Framebuffer rows */
+	ipcarg_t color_cap;  /**< Color capabilities (FB_CCAP_xxx) */
 } fb_info;
 
@@ -99,7 +101,7 @@
 /** Information on row-span yet unsent to FB driver. */
 struct {
-	size_t col;  /**< Leftmost column of the span. */
-	size_t row;  /**< Row where the span lies. */
-	size_t cnt;  /**< Width of the span. */
+	ipcarg_t col;  /**< Leftmost column of the span. */
+	ipcarg_t row;  /**< Row where the span lies. */
+	ipcarg_t cnt;  /**< Width of the span. */
 } fb_pending;
 
@@ -117,5 +119,5 @@
 }
 
-static void curs_goto(size_t x, size_t y)
+static void curs_goto(ipcarg_t x, ipcarg_t y)
 {
 	async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
@@ -147,15 +149,15 @@
 }
 
-static void set_style(int style)
+static void set_style(uint8_t style)
 {
 	async_msg_1(fb_info.phone, FB_SET_STYLE, style);
 }
 
-static void set_color(int fgcolor, int bgcolor, int flags)
+static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags)
 {
 	async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
 }
 
-static void set_rgb_color(int fgcolor, int bgcolor)
+static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
 {
 	async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 
@@ -178,14 +180,23 @@
 }
 
-static int ccap_fb_to_con(int ccap_fb, int *ccap_con)
+static int ccap_fb_to_con(ipcarg_t ccap_fb, ipcarg_t *ccap_con)
 {
 	switch (ccap_fb) {
-	case FB_CCAP_NONE: *ccap_con = CONSOLE_CCAP_NONE; break;
-	case FB_CCAP_STYLE: *ccap_con = CONSOLE_CCAP_STYLE; break;
-	case FB_CCAP_INDEXED: *ccap_con = CONSOLE_CCAP_INDEXED; break;
-	case FB_CCAP_RGB: *ccap_con = CONSOLE_CCAP_RGB; break;
-	default: return EINVAL;
-	}
-
+	case FB_CCAP_NONE:
+		*ccap_con = CONSOLE_CCAP_NONE;
+		break;
+	case FB_CCAP_STYLE:
+		*ccap_con = CONSOLE_CCAP_STYLE;
+		break;
+	case FB_CCAP_INDEXED:
+		*ccap_con = CONSOLE_CCAP_INDEXED;
+		break;
+	case FB_CCAP_RGB:
+		*ccap_con = CONSOLE_CCAP_RGB;
+		break;
+	default:
+		return EINVAL;
+	}
+	
 	return EOK;
 }
@@ -226,5 +237,5 @@
  *
  */
-static void cell_mark_changed(size_t col, size_t row)
+static void cell_mark_changed(ipcarg_t col, ipcarg_t row)
 {
 	if (fb_pending.cnt != 0) {
@@ -253,5 +264,5 @@
 {
 	bool flush_cursor = false;
-
+	
 	switch (ch) {
 	case '\n':
@@ -297,5 +308,5 @@
 			async_msg_1(fb_info.phone, FB_SCROLL, 1);
 	}
-
+	
 	if (cons == active_console && flush_cursor)
 		curs_goto(cons->scr.position_x, cons->scr.position_y);
@@ -327,8 +338,4 @@
 	
 	if (cons != kernel_console) {
-		size_t x;
-		size_t y;
-		int rc = 0;
-		
 		async_serialize_start();
 		
@@ -344,4 +351,9 @@
 		set_attrs(&cons->scr.attrs);
 		curs_visibility(false);
+		
+		ipcarg_t x;
+		ipcarg_t y;
+		int rc = 0;
+		
 		if (interbuffer) {
 			for (y = 0; y < cons->scr.size_y; y++) {
@@ -390,5 +402,4 @@
 	/* Ignore parameters, the connection is already opened */
 	while (true) {
-		
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
@@ -433,16 +444,11 @@
 static void mouse_events(ipc_callid_t iid, ipc_call_t *icall)
 {
-	int button, press;
-	int dx, dy;
-	int newcon;
-
 	/* Ignore parameters, the connection is already opened */
 	while (true) {
-
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
-
+		
 		int retval;
-
+		
 		switch (IPC_GET_METHOD(call)) {
 		case IPC_M_PHONE_HUNGUP:
@@ -450,8 +456,6 @@
 			return;
 		case MEVENT_BUTTON:
-			button = IPC_GET_ARG1(call);
-			press = IPC_GET_ARG2(call);
-			if (button == 1) {
-				newcon = gcons_mouse_btn(press);
+			if (IPC_GET_ARG1(call) == 1) {
+				int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
 				if (newcon != -1)
 					change_console(&consoles[newcon]);
@@ -460,7 +464,6 @@
 			break;
 		case MEVENT_MOVE:
-			dx = IPC_GET_ARG1(call);
-			dy = IPC_GET_ARG2(call);
-			gcons_mouse_move(dx, dy);
+			gcons_mouse_move((int) IPC_GET_ARG1(call),
+			    (int) IPC_GET_ARG2(call));
 			retval = 0;
 			break;
@@ -477,5 +480,5 @@
 	void *buf;
 	size_t size;
-	int rc = async_data_receive(&buf, 0, 0, 0, &size);
+	int rc = async_data_write_accept(&buf, false, 0, 0, 0, &size);
 	
 	if (rc != EOK) {
@@ -520,4 +523,5 @@
 	console_event_t ev;
 	fibril_mutex_lock(&input_mutex);
+	
 recheck:
 	while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) {
@@ -536,4 +540,5 @@
 		goto recheck;
 	}
+	
 	fibril_mutex_unlock(&input_mutex);
 }
@@ -542,6 +547,7 @@
 {
 	console_event_t ev;
-
+	
 	fibril_mutex_lock(&input_mutex);
+	
 recheck:
 	if (keybuffer_pop(&cons->keybuffer, &ev)) {
@@ -551,4 +557,5 @@
 		goto recheck;
 	}
+	
 	fibril_mutex_unlock(&input_mutex);
 }
@@ -580,6 +587,5 @@
 	ipcarg_t arg2;
 	ipcarg_t arg3;
-
-	int cons_ccap;
+	
 	int rc;
 	
@@ -622,5 +628,4 @@
 			if (cons == active_console) {
 				async_req_0_0(fb_info.phone, FB_FLUSH);
-				
 				curs_goto(cons->scr.position_x, cons->scr.position_y);
 			}
@@ -650,10 +655,9 @@
 			break;
 		case CONSOLE_GET_COLOR_CAP:
-			rc = ccap_fb_to_con(fb_info.color_cap, &cons_ccap);
+			rc = ccap_fb_to_con(fb_info.color_cap, &arg1);
 			if (rc != EOK) {
 				ipc_answer_0(callid, rc);
 				continue;
 			}
-			arg1 = cons_ccap;
 			break;
 		case CONSOLE_SET_STYLE:
@@ -714,5 +718,5 @@
 		return false;
 	}
-
+	
 	kbd_phone = fd_phone(input_fd);
 	if (kbd_phone < 0) {
@@ -720,5 +724,5 @@
 		return false;
 	}
-
+	
 	/* NB: The callback connection is slotted for removal */
 	ipcarg_t phonehash;
@@ -727,16 +731,16 @@
 		return false;
 	}
-
+	
 	async_new_connection(phonehash, 0, NULL, keyboard_events);
-
+	
 	/* Connect to mouse device */
 	mouse_phone = -1;
 	int mouse_fd = open("/dev/hid_in/mouse", O_RDONLY);
-
+	
 	if (mouse_fd < 0) {
 		printf(NAME ": Notice - failed opening %s\n", "/dev/hid_in/mouse");
 		goto skip_mouse;
 	}
-
+	
 	mouse_phone = fd_phone(mouse_fd);
 	if (mouse_phone < 0) {
@@ -744,5 +748,5 @@
 		goto skip_mouse;
 	}
-
+	
 	if (ipc_connect_to_me(mouse_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
 		printf(NAME ": Failed to create callback from mouse device\n");
@@ -750,8 +754,8 @@
 		goto skip_mouse;
 	}
-
+	
 	async_new_connection(phonehash, 0, NULL, mouse_events);
 skip_mouse:
-
+	
 	/* Connect to framebuffer driver */
 	fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
@@ -760,5 +764,5 @@
 		return -1;
 	}
-
+	
 	/* Register driver */
 	int rc = devmap_driver_register(NAME, client_connection);
@@ -772,9 +776,7 @@
 	
 	/* Synchronize, the gcons could put something in queue */
-	ipcarg_t color_cap;
 	async_req_0_0(fb_info.phone, FB_FLUSH);
 	async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
-	async_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &color_cap);
-	fb_info.color_cap = color_cap;
+	async_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap);
 	
 	/* Set up shared memory buffer. */
@@ -827,5 +829,5 @@
 	async_serialize_start();
 	gcons_redraw_console();
-	set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
+	set_style(STYLE_NORMAL);
 	screen_clear();
 	curs_goto(0, 0);
Index: uspace/srv/hid/console/gcons.c
===================================================================
--- uspace/srv/hid/console/gcons.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/console/gcons.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -38,5 +38,5 @@
 #include <stdio.h>
 #include <sys/mman.h>
-#include <string.h>
+#include <str.h>
 #include <align.h>
 #include <bool.h>
@@ -54,5 +54,30 @@
 #define STATUS_HEIGHT  48
 
-#define MAIN_COLOR  0xffffff
+#define COLOR_MAIN        0xffffff
+#define COLOR_FOREGROUND  0x202020
+#define COLOR_BACKGROUND  0xffffff
+
+extern char _binary_gfx_helenos_ppm_start[0];
+extern int _binary_gfx_helenos_ppm_size;
+extern char _binary_gfx_nameic_ppm_start[0];
+extern int _binary_gfx_nameic_ppm_size;
+
+extern char _binary_gfx_anim_1_ppm_start[0];
+extern int _binary_gfx_anim_1_ppm_size;
+extern char _binary_gfx_anim_2_ppm_start[0];
+extern int _binary_gfx_anim_2_ppm_size;
+extern char _binary_gfx_anim_3_ppm_start[0];
+extern int _binary_gfx_anim_3_ppm_size;
+extern char _binary_gfx_anim_4_ppm_start[0];
+extern int _binary_gfx_anim_4_ppm_size;
+
+extern char _binary_gfx_cons_selected_ppm_start[0];
+extern int _binary_gfx_cons_selected_ppm_size;
+extern char _binary_gfx_cons_idle_ppm_start[0];
+extern int _binary_gfx_cons_idle_ppm_size;
+extern char _binary_gfx_cons_has_data_ppm_start[0];
+extern int _binary_gfx_cons_has_data_ppm_size;
+extern char _binary_gfx_cons_kernel_ppm_start[0];
+extern int _binary_gfx_cons_kernel_ppm_size;
 
 static bool use_gcons = false;
@@ -82,10 +107,10 @@
 static size_t active_console = 0;
 
-size_t mouse_x;
-size_t mouse_y;
-
-bool btn_pressed;
-size_t btn_x;
-size_t btn_y;
+static ipcarg_t mouse_x = 0;
+static ipcarg_t mouse_y= 0;
+
+static bool btn_pressed = false;
+static ipcarg_t btn_x = 0;
+static ipcarg_t btn_y = 0;
 
 static void vp_switch(int vp)
@@ -95,5 +120,5 @@
 
 /** Create view port */
-static int vp_create(size_t x, size_t y, size_t width, size_t height)
+static int vp_create(ipcarg_t x, ipcarg_t y, ipcarg_t width, ipcarg_t height)
 {
 	return async_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
@@ -112,5 +137,5 @@
 
 /** Transparent putchar */
-static void tran_putch(wchar_t ch, size_t col, size_t row)
+static void tran_putch(wchar_t ch, ipcarg_t col, ipcarg_t row)
 {
 	async_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
@@ -259,14 +284,17 @@
 void gcons_mouse_move(ssize_t dx, ssize_t dy)
 {
-	mouse_x = limit(mouse_x + dx, 0, xres);
-	mouse_y = limit(mouse_y + dy, 0, yres);
-
+	ssize_t nx = (ssize_t) mouse_x + dx;
+	ssize_t ny = (ssize_t) mouse_y + dy;
+	
+	mouse_x = (size_t) limit(nx, 0, xres);
+	mouse_y = (size_t) limit(ny, 0, yres);
+	
 	if (active_console != KERNEL_CONSOLE)
 		async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
 }
 
-static int gcons_find_conbut(int x, int y)
-{
-	int status_start = STATUS_START + (xres - 800) / 2;
+static int gcons_find_conbut(ipcarg_t x, ipcarg_t y)
+{
+	ipcarg_t status_start = STATUS_START + (xres - 800) / 2;
 	
 	if ((y < STATUS_TOP) || (y >= STATUS_TOP + STATUS_HEIGHT))
@@ -278,8 +306,14 @@
 	if (x >= status_start + (STATUS_WIDTH + STATUS_SPACE) * CONSOLE_COUNT)
 		return -1;
+	
 	if (((x - status_start) % (STATUS_WIDTH + STATUS_SPACE)) < STATUS_SPACE)
 		return -1;
 	
-	return (x - status_start) / (STATUS_WIDTH + STATUS_SPACE);
+	ipcarg_t btn = (x - status_start) / (STATUS_WIDTH + STATUS_SPACE);
+	
+	if (btn < CONSOLE_COUNT)
+		return btn;
+	
+	return -1;
 }
 
@@ -287,11 +321,15 @@
  *
  * @param state New state (true - pressed, false - depressed)
+ *
  */
 int gcons_mouse_btn(bool state)
 {
-	int conbut;
+	/* Ignore mouse clicks if no buttons
+	   are drawn at all */
+	if (xres < 800)
+		return -1;
 	
 	if (state) {
-		conbut = gcons_find_conbut(mouse_x, mouse_y);
+		int conbut = gcons_find_conbut(mouse_x, mouse_y);
 		if (conbut != -1) {
 			btn_pressed = true;
@@ -307,5 +345,5 @@
 	btn_pressed = false;
 	
-	conbut = gcons_find_conbut(mouse_x, mouse_y);
+	int conbut = gcons_find_conbut(mouse_x, mouse_y);
 	if (conbut == gcons_find_conbut(btn_x, btn_y))
 		return conbut;
@@ -313,5 +351,4 @@
 	return -1;
 }
-
 
 /** Draw a PPM pixmap to framebuffer
@@ -321,12 +358,10 @@
  * @param x Coordinate of upper left corner
  * @param y Coordinate of upper left corner
- */
-static void draw_pixmap(char *logo, size_t size, int x, int y)
-{
-	char *shm;
-	int rc;
-	
+ *
+ */
+static void draw_pixmap(char *logo, size_t size, ipcarg_t x, ipcarg_t y)
+{
 	/* Create area */
-	shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
+	char *shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
 	    MAP_ANONYMOUS, 0, 0);
 	if (shm == MAP_FAILED)
@@ -336,5 +371,5 @@
 	
 	/* Send area */
-	rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm);
+	int rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm);
 	if (rc)
 		goto exit;
@@ -356,19 +391,12 @@
 }
 
-extern char _binary_gfx_helenos_ppm_start[0];
-extern int _binary_gfx_helenos_ppm_size;
-extern char _binary_gfx_nameic_ppm_start[0];
-extern int _binary_gfx_nameic_ppm_size;
-
 /** Redraws console graphics */
 void gcons_redraw_console(void)
 {
-	int i;
-	
 	if (!use_gcons)
 		return;
 	
 	vp_switch(0);
-	set_rgb_color(MAIN_COLOR, MAIN_COLOR);
+	set_rgb_color(COLOR_MAIN, COLOR_MAIN);
 	clear();
 	draw_pixmap(_binary_gfx_helenos_ppm_start,
@@ -377,4 +405,5 @@
 	    (size_t) &_binary_gfx_nameic_ppm_size, 5, 17);
 	
+	unsigned int i;
 	for (i = 0; i < CONSOLE_COUNT; i++)
 		redraw_state(i);
@@ -393,10 +422,6 @@
 static int make_pixmap(char *data, size_t size)
 {
-	char *shm;
-	int rc;
-	int pxid = -1;
-	
 	/* Create area */
-	shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
+	char *shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
 	    MAP_ANONYMOUS, 0, 0);
 	if (shm == MAP_FAILED)
@@ -405,6 +430,8 @@
 	memcpy(shm, data, size);
 	
+	int pxid = -1;
+	
 	/* Send area */
-	rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm);
+	int rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm);
 	if (rc)
 		goto exit;
@@ -432,33 +459,25 @@
 }
 
-extern char _binary_gfx_anim_1_ppm_start[0];
-extern int _binary_gfx_anim_1_ppm_size;
-extern char _binary_gfx_anim_2_ppm_start[0];
-extern int _binary_gfx_anim_2_ppm_size;
-extern char _binary_gfx_anim_3_ppm_start[0];
-extern int _binary_gfx_anim_3_ppm_size;
-extern char _binary_gfx_anim_4_ppm_start[0];
-extern int _binary_gfx_anim_4_ppm_size;
-
 static void make_anim(void)
 {
-	int an = async_req_1_0(fbphone, FB_ANIM_CREATE, cstatus_vp[KERNEL_CONSOLE]);
+	int an = async_req_1_0(fbphone, FB_ANIM_CREATE,
+	    cstatus_vp[KERNEL_CONSOLE]);
 	if (an < 0)
 		return;
 	
 	int pm = make_pixmap(_binary_gfx_anim_1_ppm_start,
-	    (int) &_binary_gfx_anim_1_ppm_size);
+	    (size_t) &_binary_gfx_anim_1_ppm_size);
 	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
 	
 	pm = make_pixmap(_binary_gfx_anim_2_ppm_start,
-	    (int) &_binary_gfx_anim_2_ppm_size);
+	    (size_t) &_binary_gfx_anim_2_ppm_size);
 	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
 	
 	pm = make_pixmap(_binary_gfx_anim_3_ppm_start,
-	    (int) &_binary_gfx_anim_3_ppm_size);
+	    (size_t) &_binary_gfx_anim_3_ppm_size);
 	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
 	
 	pm = make_pixmap(_binary_gfx_anim_4_ppm_start,
-	    (int) &_binary_gfx_anim_4_ppm_size);
+	    (size_t) &_binary_gfx_anim_4_ppm_size);
 	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
 	
@@ -467,13 +486,4 @@
 	animation = an;
 }
-
-extern char _binary_gfx_cons_selected_ppm_start[0];
-extern int _binary_gfx_cons_selected_ppm_size;
-extern char _binary_gfx_cons_idle_ppm_start[0];
-extern int _binary_gfx_cons_idle_ppm_size;
-extern char _binary_gfx_cons_has_data_ppm_start[0];
-extern int _binary_gfx_cons_has_data_ppm_size;
-extern char _binary_gfx_cons_kernel_ppm_start[0];
-extern int _binary_gfx_cons_kernel_ppm_size;
 
 /** Initialize nice graphical console environment */
@@ -500,5 +510,5 @@
 	
 	/* Create status buttons */
-	size_t status_start = STATUS_START + (xres - 800) / 2;
+	ipcarg_t status_start = STATUS_START + (xres - 800) / 2;
 	size_t i;
 	for (i = 0; i < CONSOLE_COUNT; i++) {
@@ -511,5 +521,5 @@
 		
 		vp_switch(cstatus_vp[i]);
-		set_rgb_color(0x202020, 0xffffff);
+		set_rgb_color(COLOR_FOREGROUND, COLOR_BACKGROUND);
 	}
 	
Index: uspace/srv/hid/console/gcons.h
===================================================================
--- uspace/srv/hid/console/gcons.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/console/gcons.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -38,15 +38,15 @@
 #include <sys/types.h>
 
-void gcons_init(int phone);
+void gcons_init(int);
 
 void gcons_redraw_console(void);
-void gcons_change_console(size_t index);
-void gcons_notify_char(size_t index);
+void gcons_change_console(size_t);
+void gcons_notify_char(size_t);
 void gcons_in_kernel(void);
 
-void gcons_notify_connect(size_t index);
-void gcons_notify_disconnect(size_t index);
+void gcons_notify_connect(size_t);
+void gcons_notify_disconnect(size_t);
 
-void gcons_mouse_move(ssize_t dx, ssize_t dy);
+void gcons_mouse_move(ssize_t, ssize_t);
 int gcons_mouse_btn(bool state);
 
Index: uspace/srv/hid/console/keybuffer.h
===================================================================
--- uspace/srv/hid/console/keybuffer.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/console/keybuffer.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -47,7 +47,7 @@
 typedef struct {
 	console_event_t fifo[KEYBUFFER_SIZE];
-	unsigned long head;
-	unsigned long tail;
-	unsigned long items;
+	size_t head;
+	size_t tail;
+	size_t items;
 } keybuffer_t;
 
Index: uspace/srv/hid/console/screenbuffer.c
===================================================================
--- uspace/srv/hid/console/screenbuffer.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ 	(revision )
@@ -1,191 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 console
- * @{
- */
-/** @file
- */
-
-#include <io/style.h>
-#include <malloc.h>
-#include <unistd.h>
-#include "screenbuffer.h"
-
-/** Store one character to screenbuffer.
- *
- * Its position is determined by scr->position_x
- * and scr->position_y.
- *
- * @param scr Screenbuffer
- * @param c   Stored character
- *
- */
-void screenbuffer_putchar(screenbuffer_t *scr, wchar_t ch)
-{
-	keyfield_t *field =
-	    get_field_at(scr, scr->position_x, scr->position_y);
-	
-	field->character = ch;
-	field->attrs = scr->attrs;
-}
-
-/** Initilize screenbuffer.
- *
- * Allocate space for screen content in accordance to given size.
- *
- * @param scr    Initialized screenbuffer
- * @param size_x Width in characters
- * @param size_y Height in characters
- *
- * @return Pointer to screenbuffer (same as scr parameter) or NULL
- *
- */
-screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y)
-{
-	scr->buffer = (keyfield_t *) malloc(sizeof(keyfield_t) * size_x * size_y);
-	if (!scr->buffer)
-		return NULL;
-	
-	scr->size_x = size_x;
-	scr->size_y = size_y;
-	scr->attrs.t = at_style;
-	scr->attrs.a.s.style = STYLE_NORMAL;
-	scr->is_cursor_visible = 1;
-	
-	screenbuffer_clear(scr);
-	
-	return scr;
-}
-
-/** Clear screenbuffer.
- *
- * @param scr Screenbuffer
- *
- */
-void screenbuffer_clear(screenbuffer_t *scr)
-{
-	size_t i;
-	
-	for (i = 0; i < (scr->size_x * scr->size_y); i++) {
-		scr->buffer[i].character = ' ';
-		scr->buffer[i].attrs = scr->attrs;
-	}
-	
-	scr->top_line = 0;
-	scr->position_x = 0;
-	scr->position_y = 0;
-}
-
-/** Clear one buffer line.
- *
- * @param scr
- * @param line One buffer line (not a screen line!)
- *
- */
-void screenbuffer_clear_line(screenbuffer_t *scr, size_t line)
-{
-	size_t x;
-	
-	for (x = 0; x < scr->size_x; x++) {
-		scr->buffer[x + line * scr->size_x].character = ' ';
-		scr->buffer[x + line * scr->size_x].attrs = scr->attrs;
-	}
-}
-
-/** Copy content buffer from screenbuffer to given memory.
- *
- * @param scr  Source screenbuffer
- * @param dest Destination
- *
- */
-void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest)
-{
-	size_t i;
-	
-	for (i = 0; i < (scr->size_x * scr->size_y); i++)
-		dest[i] = scr->buffer[i];
-}
-
-/** Set new cursor position in screenbuffer.
- *
- * @param scr
- * @param x
- * @param y
- *
- */
-void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y)
-{
-	scr->position_x = x % scr->size_x;
-	scr->position_y = y % scr->size_y;
-}
-
-/** Set new style.
- *
- * @param scr
- * @param fg_color
- * @param bg_color
- *
- */
-void screenbuffer_set_style(screenbuffer_t *scr, uint8_t style)
-{
-	scr->attrs.t = at_style;
-	scr->attrs.a.s.style = style;
-}
-
-/** Set new color.
- *
- * @param scr
- * @param fg_color
- * @param bg_color
- *
- */
-void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color, uint8_t bg_color, uint8_t flags)
-{
-	scr->attrs.t = at_idx;
-	scr->attrs.a.i.fg_color = fg_color;
-	scr->attrs.a.i.bg_color = bg_color;
-	scr->attrs.a.i.flags = flags;
-}
-
-/** Set new RGB color.
- *
- * @param scr
- * @param fg_color
- * @param bg_color
- *
- */
-void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color, uint32_t bg_color)
-{
-	scr->attrs.t = at_rgb;
-	scr->attrs.a.r.fg_color = fg_color;
-	scr->attrs.a.r.bg_color = bg_color;
-}
-
-/** @}
- */
Index: uspace/srv/hid/console/screenbuffer.h
===================================================================
--- uspace/srv/hid/console/screenbuffer.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ 	(revision )
@@ -1,159 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 console
- * @{
- */
-/** @file
- */
-
-#ifndef SCREENBUFFER_H__
-#define SCREENBUFFER_H__
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <bool.h>
-
-#define DEFAULT_FOREGROUND  0x0       /**< default console foreground color */
-#define DEFAULT_BACKGROUND  0xf0f0f0  /**< default console background color */
-
-typedef struct {
-	uint8_t style;
-} attr_style_t;
-
-typedef struct {
-	uint8_t fg_color;
-	uint8_t bg_color;
-	uint8_t flags;
-} attr_idx_t;
-
-typedef struct {
-	uint32_t bg_color;  /**< background color */
-	uint32_t fg_color;  /**< foreground color */
-} attr_rgb_t;
-
-typedef struct {
-	enum {
-		at_style,
-		at_idx,
-		at_rgb
-	} t;
-	union {
-		attr_style_t s;
-		attr_idx_t i;
-		attr_rgb_t r;
-	} a;
-} attrs_t;
-
-/** One field on screen. It contain one character and its attributes. */
-typedef struct {
-	wchar_t character;  /**< Character itself */
-	attrs_t attrs;      /**< Character attributes */
-} keyfield_t;
-
-/** Structure for buffering state of one virtual console.
- */
-typedef struct {
-	keyfield_t *buffer;      /**< Screen content - characters and
-	                              their attributes (used as a circular buffer) */
-	size_t size_x;           /**< Number of columns  */
-	size_t size_y;           /**< Number of rows */
-	
-	/** Coordinates of last printed character for determining cursor position */
-	size_t position_x;
-	size_t position_y;
-	
-	attrs_t attrs;           /**< Current attributes. */
-	size_t top_line;         /**< Points to buffer[][] line that will
-	                              be printed at screen as the first line */
-	bool is_cursor_visible;  /**< Cursor state - default is visible */
-} screenbuffer_t;
-
-/** Returns keyfield for position on screen
- *
- * Screenbuffer->buffer is cyclic buffer so we
- * must couted in index of the topmost line.
- *
- * @param scr Screenbuffer
- * @param x   Position on screen
- * @param y   Position on screen
- *
- * @return Keyfield structure with character and its attributes on x, y
- *
- */
-static inline keyfield_t *get_field_at(screenbuffer_t *scr, size_t x, size_t y)
-{
-	return scr->buffer + x + ((y + scr->top_line) % scr->size_y) * scr->size_x;
-}
-
-/** Compares two sets of attributes.
- *
- * @param s1 First style
- * @param s2 Second style
- *
- * @return Nonzero on equality
- *
- */
-static inline int attrs_same(attrs_t a1, attrs_t a2)
-{
-	if (a1.t != a2.t)
-		return 0;
-	
-	switch (a1.t) {
-	case at_style:
-		return (a1.a.s.style == a2.a.s.style);
-	case at_idx:
-		return (a1.a.i.fg_color == a2.a.i.fg_color)
-		    && (a1.a.i.bg_color == a2.a.i.bg_color)
-		    && (a1.a.i.flags == a2.a.i.flags);
-	case at_rgb:
-		return (a1.a.r.fg_color == a2.a.r.fg_color)
-		    && (a1.a.r.bg_color == a2.a.r.bg_color);
-	}
-	
-	return 0;
-}
-
-
-void screenbuffer_putchar(screenbuffer_t *scr, wchar_t c);
-screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y);
-
-void screenbuffer_clear(screenbuffer_t *scr);
-void screenbuffer_clear_line(screenbuffer_t *scr, size_t line);
-void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest);
-void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y);
-void screenbuffer_set_style(screenbuffer_t *scr, uint8_t style);
-void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color,
-    uint8_t bg_color, uint8_t attr);
-void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color,
-    uint32_t bg_color);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/hid/fb/Makefile
===================================================================
--- uspace/srv/hid/fb/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/fb/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -28,13 +28,70 @@
 #
 
-include Makefile.common
+USPACE_PREFIX = ../../..
+ROOT_PATH = $(USPACE_PREFIX)/..
 
-.PHONY: all clean
+COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
+CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
 
-all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
-	-[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
-	$(MAKE) -f Makefile.build PRECHECK=$(PRECHECK)
+BINARY = fb
 
-clean:
-	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
-	find . -name '*.o' -follow -exec rm \{\} \;
+-include $(COMMON_MAKEFILE)
+-include $(CONFIG_MAKEFILE)
+
+SOURCES = \
+	main.c \
+	ppm.c
+
+ifneq ($(UARCH),ia64)
+	SOURCES += \
+		fb.c \
+		font-8x16.c
+	EXTRA_CFLAGS += -DFB_ENABLED
+endif
+
+ifeq ($(UARCH),ia32)
+	SOURCES += \
+		ega.c
+	EXTRA_CFLAGS += -DEGA_ENABLED
+endif
+
+ifeq ($(UARCH),ia64)
+	SOURCES += \
+		ega.c \
+		ski.c \
+		serial_console.c
+	EXTRA_CFLAGS += -DSKI_ENABLED -DEGA_ENABLED
+endif
+
+ifeq ($(UARCH),amd64)
+	SOURCES += \
+		ega.c
+	EXTRA_CFLAGS += -DEGA_ENABLED
+endif
+
+ifeq ($(UARCH),mips32)
+	SOURCES += \
+		msim.c \
+		serial_console.c
+	EXTRA_CFLAGS += -DMSIM_ENABLED
+endif
+
+ifeq ($(UARCH),sparc64)
+	ifeq ($(PROCESSOR),sun4v)
+		SOURCES += \
+			niagara.c \
+			serial_console.c
+		EXTRA_CFLAGS += -DNIAGARA_ENABLED
+	endif
+	
+	ifeq ($(MACHINE),serengeti)
+		SOURCES += \
+			sgcn.c \
+			serial_console.c
+		EXTRA_CFLAGS += -DSGCN_ENABLED
+	endif
+endif
+
+EXTRA_CFLAGS += -D$(UARCH)
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/fb/Makefile.build
===================================================================
--- uspace/srv/hid/fb/Makefile.build	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ 	(revision )
@@ -1,103 +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.
-#
-
-## Setup toolchain
-#
-
-include Makefile.common
-include $(LIBC_PREFIX)/Makefile.toolchain
-
-## Sources
-#
-
-SOURCES = \
-	main.c \
-	ppm.c
-
-ifneq ($(UARCH),ia64)
-	SOURCES += fb.c \
-		font-8x16.c
-	CFLAGS += -DFB_ENABLED
-endif
-
-ifeq ($(UARCH),ia32)
-	SOURCES += ega.c
-	CFLAGS += -DEGA_ENABLED
-endif
-
-ifeq ($(UARCH),ia64)
-	SOURCES += ega.c \
-		ski.c \
-		serial_console.c
-	CFLAGS += -DSKI_ENABLED
-	CFLAGS += -DEGA_ENABLED
-endif
-
-ifeq ($(UARCH),amd64)
-	SOURCES += ega.c
-	CFLAGS += -DEGA_ENABLED
-endif
-
-ifeq ($(UARCH),mips32)
-	SOURCES += msim.c \
-		serial_console.c
-	CFLAGS += -DMSIM_ENABLED
-endif
-
-ifeq ($(UARCH),sparc64)
-	SOURCES += sgcn.c \
-		serial_console.c
-	CFLAGS += -DSGCN_ENABLED
-endif
-
-CFLAGS += -D$(UARCH)
-
-OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
-
-.PHONY: all
-
-all: $(OUTPUT) $(OUTPUT).disasm
-
--include $(DEPEND)
-
-$(OUTPUT).disasm: $(OUTPUT)
-	$(OBJDUMP) -d $< > $@
-
-$(OUTPUT): $(OBJECTS) $(LIBS)
-	$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
-
-%.o: %.c $(DEPEND)
-	$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
-ifeq ($(PRECHECK),y)
-	$(JOBFILE) $(JOB) $< $@ cc core $(DEFS) $(CFLAGS)
-endif
-
-$(DEPEND):
-	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > $@ 2> /dev/null
-	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
Index: uspace/srv/hid/fb/Makefile.common
===================================================================
--- uspace/srv/hid/fb/Makefile.common	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ 	(revision )
@@ -1,40 +1,0 @@
-#
-# Copyright (c) 2005 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.
-#
-
-
-## Common names
-#
-
-LIBC_PREFIX = ../../../lib/libc
-SOFTINT_PREFIX = ../../../lib/softint
-LIBS = $(LIBC_PREFIX)/libc.a
-
-DEPEND = Makefile.depend
-DEPEND_PREV = $(DEPEND).prev
-JOB = fb.job
-OUTPUT = fb
Index: uspace/srv/hid/fb/ega.c
===================================================================
--- uspace/srv/hid/fb/ega.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/fb/ega.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -28,8 +28,8 @@
 
 /** @defgroup egafb EGA framebuffer
- * @brief	HelenOS EGA framebuffer.
+ * @brief HelenOS EGA framebuffer.
  * @ingroup fbs
  * @{
- */ 
+ */
 /** @file
  */
@@ -52,11 +52,12 @@
 #include <io/style.h>
 #include <io/color.h>
+#include <io/screenbuffer.h>
 #include <sys/types.h>
 
 #include "ega.h"
-#include "../console/screenbuffer.h"
 #include "main.h"
 
-#define MAX_SAVED_SCREENS 256
+#define MAX_SAVED_SCREENS  256
+
 typedef struct saved_screen {
 	short *data;
@@ -65,24 +66,70 @@
 saved_screen saved_screens[MAX_SAVED_SCREENS];
 
-#define EGA_IO_BASE ((ioport8_t *) 0x3d4)
-#define EGA_IO_SIZE 2
-
-int ega_normal_color = 0x0f;
-int ega_inverted_color = 0xf0;
-
-#define NORMAL_COLOR		ega_normal_color
-#define INVERTED_COLOR		ega_inverted_color
+#define EGA_IO_BASE  ((ioport8_t *) 0x3d4)
+#define EGA_IO_SIZE  2
 
 /* Allow only 1 connection */
 static int client_connected = 0;
 
-static unsigned int scr_width;
-static unsigned int scr_height;
+static sysarg_t scr_width;
+static sysarg_t scr_height;
 static uint8_t *scr_addr;
 
-static unsigned int style;
-
-static unsigned attr_to_ega_style(const attrs_t *a);
-static uint8_t ega_glyph(wchar_t ch);
+static uint8_t style_normal = 0xf0;
+static uint8_t style_inverted = 0x0f;
+static uint8_t style;
+
+static uint8_t style_to_ega_style(uint8_t style)
+{
+	switch (style) {
+	case STYLE_EMPHASIS:
+		return (style_normal | 0x04);
+	case STYLE_SELECTED:
+		return (style_inverted | 0x40);
+	case STYLE_INVERTED:
+		return style_inverted;
+	}
+	
+	return style_normal;
+}
+
+static uint8_t color_to_ega_style(uint8_t fg_color, uint8_t bg_color,
+    uint8_t attr)
+{
+	uint8_t style = (fg_color & 7) | ((bg_color & 7) << 4);
+	
+	if (attr & CATTR_BRIGHT)
+		style |= 0x08;
+	
+	return style;
+}
+
+static uint8_t rgb_to_ega_style(uint32_t fg, uint32_t bg)
+{
+	return (fg > bg) ? style_inverted : style_normal;
+}
+
+static uint8_t attr_to_ega_style(const attrs_t *attr)
+{
+	switch (attr->t) {
+	case at_style:
+		return style_to_ega_style(attr->a.s.style);
+	case at_idx:
+		return color_to_ega_style(attr->a.i.fg_color,
+		    attr->a.i.bg_color, attr->a.i.flags);
+	case at_rgb:
+		return rgb_to_ega_style(attr->a.r.fg_color, attr->a.r.bg_color);
+	default:
+		return style_normal;
+	}
+}
+
+static uint8_t ega_glyph(wchar_t ch)
+{
+	if (ch >= 0 && ch < 128)
+		return ch;
+	
+	return '?';
+}
 
 static void clrscr(void)
@@ -96,22 +143,20 @@
 }
 
-static void cursor_goto(unsigned int col, unsigned int row)
-{
-	int ega_cursor;
-
-	ega_cursor = col + scr_width * row;
+static void cursor_goto(sysarg_t col, sysarg_t row)
+{
+	sysarg_t cursor = col + scr_width * row;
 	
 	pio_write_8(EGA_IO_BASE, 0xe);
-	pio_write_8(EGA_IO_BASE + 1, (ega_cursor >> 8) & 0xff);
+	pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
 	pio_write_8(EGA_IO_BASE, 0xf);
-	pio_write_8(EGA_IO_BASE + 1, ega_cursor & 0xff);
+	pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
 }
 
 static void cursor_disable(void)
 {
-	uint8_t stat;
-
 	pio_write_8(EGA_IO_BASE, 0xa);
-	stat = pio_read_8(EGA_IO_BASE + 1);
+	
+	uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
+	
 	pio_write_8(EGA_IO_BASE, 0xa);
 	pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
@@ -120,16 +165,16 @@
 static void cursor_enable(void)
 {
-	uint8_t stat;
-
 	pio_write_8(EGA_IO_BASE, 0xa);
-	stat = pio_read_8(EGA_IO_BASE + 1);
+	
+	uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
+	
 	pio_write_8(EGA_IO_BASE, 0xa);
 	pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
 }
 
-static void scroll(int rows)
-{
-	unsigned i;
-
+static void scroll(ssize_t rows)
+{
+	size_t i;
+	
 	if (rows > 0) {
 		memmove(scr_addr, ((char *) scr_addr) + rows * scr_width * 2,
@@ -142,9 +187,9 @@
 		    scr_width * scr_height * 2 + rows * scr_width * 2);
 		for (i = 0; i < -rows * scr_width; i++)
-			((short *)scr_addr)[i] = ((style << 8 ) + ' ');
-	}
-}
-
-static void printchar(wchar_t c, unsigned int col, unsigned int row)
+			((short *) scr_addr)[i] = ((style << 8 ) + ' ');
+	}
+}
+
+static void printchar(wchar_t c, sysarg_t col, sysarg_t row)
 {
 	scr_addr[(row * scr_width + col) * 2] = ega_glyph(c);
@@ -158,21 +203,23 @@
  * @param vport Viewport id
  * @param data  Text data.
- * @param x	Leftmost column of the area.
- * @param y	Topmost row of the area.
- * @param w	Number of rows.
- * @param h	Number of columns.
+ * @param x     Leftmost column of the area.
+ * @param y     Topmost row of the area.
+ * @param w     Number of rows.
+ * @param h     Number of columns.
+ *
  */
-static void draw_text_data(keyfield_t *data, unsigned int x,
-    unsigned int y, unsigned int w, unsigned int h)
-{
-	unsigned int i, j;
+static void draw_text_data(keyfield_t *data, sysarg_t x, sysarg_t y,
+    sysarg_t w, sysarg_t h)
+{
+	sysarg_t i;
+	sysarg_t j;
 	keyfield_t *field;
 	uint8_t *dp;
-
+	
 	for (j = 0; j < h; j++) {
 		for (i = 0; i < w; i++) {
 			field = &data[j * w + i];
 			dp = &scr_addr[2 * ((y + j) * scr_width + (x + i))];
-
+			
 			dp[0] = ega_glyph(field->character);
 			dp[1] = attr_to_ega_style(&field->attrs);
@@ -183,111 +230,74 @@
 static int save_screen(void)
 {
-	int i;
-
-	for (i = 0; (i < MAX_SAVED_SCREENS) && (saved_screens[i].data); i++)
-		;
-	if (i == MAX_SAVED_SCREENS) 
+	ipcarg_t i;
+	
+	/* Find empty screen */
+	for (i = 0; (i < MAX_SAVED_SCREENS) && (saved_screens[i].data); i++);
+	
+	if (i == MAX_SAVED_SCREENS)
 		return EINVAL;
-	if (!(saved_screens[i].data = malloc(2 * scr_width * scr_height))) 
+	
+	if (!(saved_screens[i].data = malloc(2 * scr_width * scr_height)))
 		return ENOMEM;
+	
 	memcpy(saved_screens[i].data, scr_addr, 2 * scr_width * scr_height);
-
-	return i;
-}
-
-static int print_screen(int i)
-{
-	if (saved_screens[i].data)
+	return (int) i;
+}
+
+static int print_screen(ipcarg_t i)
+{
+	if ((i >= MAX_SAVED_SCREENS) || (saved_screens[i].data))
 		memcpy(scr_addr, saved_screens[i].data, 2 * scr_width *
 		    scr_height);
 	else
 		return EINVAL;
-	return i;
-}
-
-static int style_to_ega_style(int style)
-{
-	unsigned int ega_style;
-
-	switch (style) {
-	case STYLE_NORMAL:
-		ega_style = INVERTED_COLOR;
-		break;
-	case STYLE_EMPHASIS:
-		ega_style = INVERTED_COLOR | 4;
-		break;
-	default:
-		return INVERTED_COLOR;
-	}
-
-	return ega_style;
-}
-
-static unsigned int color_to_ega_style(int fg_color, int bg_color, int attr)
-{
-	unsigned int style;
-
-	style = (fg_color & 7) | ((bg_color & 7) << 4);
-	if (attr & CATTR_BRIGHT)
-		style = style | 0x08;
-
-	return style;
-}
-
-static unsigned int rgb_to_ega_style(uint32_t fg, uint32_t bg)
-{
-	return (fg > bg) ? NORMAL_COLOR : INVERTED_COLOR;
-}
-
-static unsigned attr_to_ega_style(const attrs_t *a)
-{
-	switch (a->t) {
-	case at_style:
-		return style_to_ega_style(a->a.s.style);
-	case at_rgb:
-		return rgb_to_ega_style(a->a.r.fg_color, a->a.r.bg_color);
-	case at_idx:
-		return color_to_ega_style(a->a.i.fg_color,
-		    a->a.i.bg_color, a->a.i.flags);
-	default:
-		return INVERTED_COLOR;
-	}
-}
-
-static uint8_t ega_glyph(wchar_t ch)
-{
-	if (ch >= 0 && ch < 128)
-		return ch;
-
-	return '?';
+	
+	return (int) i;
 }
 
 static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall)
 {
-	int retval;
-	ipc_callid_t callid;
-	ipc_call_t call;
-	wchar_t c;
-	unsigned int row, col, w, h;
-	int bg_color, fg_color, attr;
-	uint32_t bg_rgb, fg_rgb;
+	size_t intersize = 0;
 	keyfield_t *interbuf = NULL;
-	size_t intersize = 0;
-	int i;
-
+	
 	if (client_connected) {
 		ipc_answer_0(iid, ELIMIT);
 		return;
 	}
+	
+	/* Accept connection */
 	client_connected = 1;
-	ipc_answer_0(iid, EOK); /* Accept connection */
-
-	while (1) {
-		callid = async_get_call(&call);
- 		switch (IPC_GET_METHOD(call)) {
+	ipc_answer_0(iid, EOK);
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		wchar_t c;
+		
+		ipcarg_t col;
+		ipcarg_t row;
+		ipcarg_t w;
+		ipcarg_t h;
+		
+		ssize_t rows;
+		
+		uint8_t bg_color;
+		uint8_t fg_color;
+		uint8_t attr;
+		
+		uint32_t fg_rgb;
+		uint32_t bg_rgb;
+		
+		ipcarg_t scr;
+		int retval;
+		
+		switch (IPC_GET_METHOD(call)) {
 		case IPC_M_PHONE_HUNGUP:
 			client_connected = 0;
 			ipc_answer_0(callid, EOK);
-			return; /* Exit thread */
+			
+			/* Exit thread */
+			return;
 		case IPC_M_SHARE_OUT:
 			/* We accept one area for data interchange */
@@ -299,19 +309,23 @@
 				continue;
 			}
+			
 			retval = EINVAL;
 			break;
 		case FB_DRAW_TEXT_DATA:
+			if (!interbuf) {
+				retval = EINVAL;
+				break;
+			}
+			
 			col = IPC_GET_ARG1(call);
 			row = IPC_GET_ARG2(call);
 			w = IPC_GET_ARG3(call);
 			h = IPC_GET_ARG4(call);
-			if (!interbuf) {
+			
+			if ((col + w > scr_width) || (row + h > scr_height)) {
 				retval = EINVAL;
 				break;
 			}
-			if (col + w > scr_width || row + h > scr_height) {
-				retval = EINVAL;
-				break;
-			}
+			
 			draw_text_data(interbuf, col, row, w, h);
 			retval = 0;
@@ -331,28 +345,41 @@
 			col = IPC_GET_ARG2(call);
 			row = IPC_GET_ARG3(call);
-			if (col >= scr_width || row >= scr_height) {
+			
+			if ((col >= scr_width) || (row >= scr_height)) {
 				retval = EINVAL;
 				break;
 			}
+			
 			printchar(c, col, row);
 			retval = 0;
 			break;
- 		case FB_CURSOR_GOTO:
- 			col = IPC_GET_ARG1(call);
+		case FB_CURSOR_GOTO:
+			col = IPC_GET_ARG1(call);
 			row = IPC_GET_ARG2(call);
-			if (row >= scr_height || col >= scr_width) {
+			
+			if ((row >= scr_height) || (col >= scr_width)) {
 				retval = EINVAL;
 				break;
 			}
+			
 			cursor_goto(col, row);
- 			retval = 0;
- 			break;
+			retval = 0;
+			break;
 		case FB_SCROLL:
-			i = IPC_GET_ARG1(call);
-			if (i > (int) scr_height || i < -((int) scr_height)) {
-				retval = EINVAL;
-				break;
-			}
-			scroll(i);
+			rows = IPC_GET_ARG1(call);
+			
+			if (rows >= 0) {
+				if ((ipcarg_t) rows > scr_height) {
+					retval = EINVAL;
+					break;
+				}
+			} else {
+				if ((ipcarg_t) (-rows) > scr_height) {
+					retval = EINVAL;
+					break;
+				}
+			}
+			
+			scroll(rows);
 			retval = 0;
 			break;
@@ -362,4 +389,5 @@
 			else
 				cursor_disable();
+			
 			retval = 0;
 			break;
@@ -372,4 +400,5 @@
 			bg_color = IPC_GET_ARG2(call);
 			attr = IPC_GET_ARG3(call);
+			
 			style = color_to_ega_style(fg_color, bg_color, attr);
 			retval = 0;
@@ -378,10 +407,11 @@
 			fg_rgb = IPC_GET_ARG1(call);
 			bg_rgb = IPC_GET_ARG2(call);
+			
 			style = rgb_to_ega_style(fg_rgb, bg_rgb);
 			retval = 0;
 			break;
 		case FB_VP_DRAW_PIXMAP:
-			i = IPC_GET_ARG2(call);
-			retval = print_screen(i);
+			scr = IPC_GET_ARG2(call);
+			retval = print_screen(scr);
 			break;
 		case FB_VP2PIXMAP:
@@ -389,13 +419,16 @@
 			break;
 		case FB_DROP_PIXMAP:
-			i = IPC_GET_ARG1(call);
-			if (i >= MAX_SAVED_SCREENS) {
+			scr = IPC_GET_ARG1(call);
+			
+			if (scr >= MAX_SAVED_SCREENS) {
 				retval = EINVAL;
 				break;
 			}
-			if (saved_screens[i].data) {
-				free(saved_screens[i].data);
-				saved_screens[i].data = NULL;
-			}
+			
+			if (saved_screens[scr].data) {
+				free(saved_screens[scr].data);
+				saved_screens[scr].data = NULL;
+			}
+			
 			retval = 0;
 			break;
@@ -413,32 +446,39 @@
 int ega_init(void)
 {
-	void *ega_ph_addr;
-	size_t sz;
-
-	ega_ph_addr = (void *) sysinfo_value("fb.address.physical");
-	scr_width = sysinfo_value("fb.width");
-	scr_height = sysinfo_value("fb.height");
-
-	if (sysinfo_value("fb.blinking")) {
-		ega_normal_color &= 0x77;
-		ega_inverted_color &= 0x77;
-	}
-
-	style = NORMAL_COLOR;
-
+	sysarg_t paddr;
+	if (sysinfo_get_value("fb.address.physical", &paddr) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("fb.width", &scr_width) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("fb.height", &scr_height) != EOK)
+		return -1;
+	
+	sysarg_t blinking;
+	if (sysinfo_get_value("fb.blinking", &blinking) != EOK)
+		blinking = false;
+	
+	void *ega_ph_addr = (void *) paddr;
+	if (blinking) {
+		style_normal &= 0x77;
+		style_inverted &= 0x77;
+	}
+	
+	style = style_normal;
+	
 	iospace_enable(task_get_id(), (void *) EGA_IO_BASE, 2);
-
-	sz = scr_width * scr_height * 2;
+	
+	size_t sz = scr_width * scr_height * 2;
 	scr_addr = as_get_mappable_page(sz);
-
+	
 	if (physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >>
 	    PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0)
 		return -1;
-
+	
 	async_set_client_connection(ega_client_connection);
-
+	
 	return 0;
 }
-
 
 /**
Index: uspace/srv/hid/fb/fb.c
===================================================================
--- uspace/srv/hid/fb/fb.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/fb/fb.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -41,5 +41,5 @@
 #include <stdlib.h>
 #include <unistd.h>
-#include <string.h>
+#include <str.h>
 #include <ddi.h>
 #include <sysinfo.h>
@@ -59,9 +59,9 @@
 #include <stdio.h>
 #include <byteorder.h>
+#include <io/screenbuffer.h>
 
 #include "font-8x16.h"
 #include "fb.h"
 #include "main.h"
-#include "../console/screenbuffer.h"
 #include "ppm.h"
 
@@ -72,10 +72,10 @@
 #define DEFAULT_FGCOLOR  0x000000
 
-#define GLYPH_UNAVAIL    '?'
-
-#define MAX_ANIM_LEN     8
-#define MAX_ANIMATIONS   4
-#define MAX_PIXMAPS      256  /**< Maximum number of saved pixmaps */
-#define MAX_VIEWPORTS    128  /**< Viewport is a rectangular area on the screen */
+#define GLYPH_UNAVAIL  '?'
+
+#define MAX_ANIM_LEN    8
+#define MAX_ANIMATIONS  4
+#define MAX_PIXMAPS     256  /**< Maximum number of saved pixmaps */
+#define MAX_VIEWPORTS   128  /**< Viewport is a rectangular area on the screen */
 
 /** Function to render a pixel from a RGB value. */
@@ -956,5 +956,4 @@
 	bb_cell_t *bbp;
 	attrs_t *a;
-	attr_rgb_t rgb;
 	
 	for (j = 0; j < h; j++) {
@@ -966,4 +965,8 @@
 			
 			a = &data[j * w + i].attrs;
+			
+			attr_rgb_t rgb;
+			rgb.fg_color = 0;
+			rgb.bg_color = 0;
 			rgb_from_attr(&rgb, a);
 			
@@ -1511,8 +1514,16 @@
 		rgb->bg_color = color_table[COLOR_WHITE];
 		break;
+	case STYLE_INVERTED:
+		rgb->fg_color = color_table[COLOR_WHITE];
+		rgb->bg_color = color_table[COLOR_BLACK];
+		break;
+	case STYLE_SELECTED:
+		rgb->fg_color = color_table[COLOR_WHITE];
+		rgb->bg_color = color_table[COLOR_RED];
+		break;
 	default:
 		return EINVAL;
 	}
-
+	
 	return EOK;
 }
@@ -1756,21 +1767,38 @@
 	async_set_client_connection(fb_client_connection);
 	
-	void *fb_ph_addr = (void *) sysinfo_value("fb.address.physical");
-	unsigned int fb_offset = sysinfo_value("fb.offset");
-	unsigned int fb_width = sysinfo_value("fb.width");
-	unsigned int fb_height = sysinfo_value("fb.height");
-	unsigned int fb_scanline = sysinfo_value("fb.scanline");
-	unsigned int fb_visual = sysinfo_value("fb.visual");
-
-	unsigned int fbsize = fb_scanline * fb_height;
+	sysarg_t fb_ph_addr;
+	if (sysinfo_get_value("fb.address.physical", &fb_ph_addr) != EOK)
+		return -1;
+	
+	sysarg_t fb_offset;
+	if (sysinfo_get_value("fb.offset", &fb_offset) != EOK)
+		fb_offset = 0;
+	
+	sysarg_t fb_width;
+	if (sysinfo_get_value("fb.width", &fb_width) != EOK)
+		return -1;
+	
+	sysarg_t fb_height;
+	if (sysinfo_get_value("fb.height", &fb_height) != EOK)
+		return -1;
+	
+	sysarg_t fb_scanline;
+	if (sysinfo_get_value("fb.scanline", &fb_scanline) != EOK)
+		return -1;
+	
+	sysarg_t fb_visual;
+	if (sysinfo_get_value("fb.visual", &fb_visual) != EOK)
+		return -1;
+	
+	sysarg_t fbsize = fb_scanline * fb_height;
 	void *fb_addr = as_get_mappable_page(fbsize);
-
-	if (physmem_map(fb_ph_addr + fb_offset, fb_addr,
+	
+	if (physmem_map((void *) fb_ph_addr + fb_offset, fb_addr,
 	    ALIGN_UP(fbsize, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0)
 		return -1;
-
+	
 	if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual))
 		return 0;
-
+	
 	return -1;
 }
Index: uspace/srv/hid/fb/main.c
===================================================================
--- uspace/srv/hid/fb/main.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/fb/main.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -41,4 +41,5 @@
 #include "ski.h"
 #include "sgcn.h"
+#include "niagara.h"
 #include "main.h"
 
@@ -59,11 +60,20 @@
 int main(int argc, char *argv[])
 {
-	printf(NAME ": HelenOS Framebuffer service\n");
+	printf("%s: HelenOS Framebuffer service\n", NAME);
 	
-	ipcarg_t phonead;
 	bool initialized = false;
+	sysarg_t fb_present;
+	sysarg_t fb_kind;
+	
+	if (sysinfo_get_value("fb", &fb_present) != EOK)
+		fb_present = false;
+	
+	if (sysinfo_get_value("fb.kind", &fb_kind) != EOK) {
+		printf("%s: Unable to detect framebuffer configuration\n", NAME);
+		return -1;
+	}
 	
 #ifdef FB_ENABLED
-	if (sysinfo_value("fb.kind") == 1) {
+	if ((!initialized) && (fb_kind == 1)) {
 		if (fb_init() == 0)
 			initialized = true;
@@ -71,5 +81,5 @@
 #endif
 #ifdef EGA_ENABLED
-	if ((!initialized) && (sysinfo_value("fb.kind") == 2)) {
+	if ((!initialized) && (fb_kind == 2)) {
 		if (ega_init() == 0)
 			initialized = true;
@@ -77,5 +87,5 @@
 #endif
 #ifdef MSIM_ENABLED
-	if ((!initialized) && (sysinfo_value("fb.kind") == 3)) {
+	if ((!initialized) && (fb_kind == 3)) {
 		if (msim_init() == 0)
 			initialized = true;
@@ -83,11 +93,17 @@
 #endif
 #ifdef SGCN_ENABLED
-	if ((!initialized) && (sysinfo_value("fb.kind") == 4)) {
+	if ((!initialized) && (fb_kind == 4)) {
 		if (sgcn_init() == 0)
 			initialized = true;
 	}
 #endif
+#ifdef NIAGARA_ENABLED
+	if ((!initialized) && (fb_kind == 5)) {
+		if (niagara_init() == 0)
+			initialized = true;
+	}
+#endif
 #ifdef SKI_ENABLED
-	if ((!initialized) && (sysinfo_value("fb") != true)) {
+	if ((!initialized) && (!fb_present)) {
 		if (ski_init() == 0)
 			initialized = true;
@@ -98,8 +114,9 @@
 		return -1;
 	
+	ipcarg_t phonead;
 	if (ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, 0, &phonead) != 0) 
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
 	async_manager();
 	
Index: uspace/srv/hid/fb/msim.c
===================================================================
--- uspace/srv/hid/fb/msim.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/fb/msim.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,8 +29,8 @@
 
 /** @defgroup msimfb MSIM text console
- * @brief	HelenOS MSIM text console.
+ * @brief HelenOS MSIM text console.
  * @ingroup fbs
  * @{
- */ 
+ */
 /** @file
  */
@@ -41,4 +41,5 @@
 #include <as.h>
 #include <ddi.h>
+#include <errno.h>
 
 #include "serial_console.h"
@@ -57,8 +58,12 @@
 int msim_init(void)
 {
-	void *phys_addr = (void *) sysinfo_value("fb.address.physical");
+	sysarg_t phys_addr;
+	if (sysinfo_get_value("fb.address.physical", &phys_addr) != EOK)
+		return -1;
+	
 	virt_addr = (char *) as_get_mappable_page(1);
 	
-	if (physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE) != 0)
+	if (physmem_map((void *) phys_addr, virt_addr, 1,
+	    AS_AREA_READ | AS_AREA_WRITE) != 0)
 		return -1;
 	
@@ -69,5 +74,4 @@
 }
 
-/** 
- * @}
+/** @}
  */
Index: uspace/srv/hid/fb/niagara.c
===================================================================
--- uspace/srv/hid/fb/niagara.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hid/fb/niagara.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2008 Pavel Rimsky
+ * 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.
+ */
+
+/** @defgroup niagarafb SGCN
+ * @brief	userland driver of the Niagara console output
+ * @{
+ */ 
+/** @file
+ */
+
+#include <async.h>
+#include <sysinfo.h>
+#include <as.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ddi.h>
+
+#include "serial_console.h"
+#include "niagara.h"
+
+#define WIDTH 80
+#define HEIGHT 24
+
+/**
+ * Virtual address mapped to the buffer shared with the kernel counterpart.
+ */
+static uintptr_t output_buffer_addr;
+
+/*
+ * Kernel counterpart of the driver reads characters to be printed from here.
+ * Keep in sync with the definition from
+ * kernel/arch/sparc64/src/drivers/niagara.c.
+ */
+#define OUTPUT_BUFFER_SIZE	((PAGE_SIZE) - 2 * 8)
+typedef volatile struct {
+	uint64_t read_ptr;
+	uint64_t write_ptr;
+	char data[OUTPUT_BUFFER_SIZE];
+}
+	__attribute__ ((packed))
+	__attribute__ ((aligned(PAGE_SIZE)))
+	*output_buffer_t;
+
+output_buffer_t output_buffer;
+
+/**
+ * Pushes the character to the Niagara serial.
+ * @param c	character to be pushed
+ */
+static void niagara_putc(char c)
+{
+	while (output_buffer->write_ptr ==
+	       (output_buffer->read_ptr + OUTPUT_BUFFER_SIZE - 1)
+	       % OUTPUT_BUFFER_SIZE)
+		;
+	output_buffer->data[output_buffer->write_ptr] = (uint64_t) c;
+	output_buffer->write_ptr =
+		((output_buffer->write_ptr) + 1) % OUTPUT_BUFFER_SIZE;
+}
+
+/**
+ * Initializes the Niagara serial driver.
+ */
+int niagara_init(void)
+{
+	sysarg_t paddr;
+	if (sysinfo_get_value("niagara.outbuf.address", &paddr) != EOK)
+		return -1;
+	
+	output_buffer_addr = (uintptr_t) as_get_mappable_page(PAGE_SIZE);
+	int result = physmem_map((void *) paddr,
+	    (void *) output_buffer_addr, 1,
+	    AS_AREA_READ | AS_AREA_WRITE);
+
+	if (result != 0) {
+		printf("Niagara: uspace driver couldn't map physical memory: %d\n",
+			result);
+	}
+
+	output_buffer = (output_buffer_t) output_buffer_addr;
+
+	serial_console_init(niagara_putc, WIDTH, HEIGHT);
+	async_set_client_connection(serial_client_connection);
+	return 0;
+}
+
+/** 
+ * @}
+ */
+ 
Index: uspace/srv/hid/fb/niagara.h
===================================================================
--- uspace/srv/hid/fb/niagara.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hid/fb/niagara.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2008 Pavel Rimsky
+ * 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.
+ */
+
+/** @defgroup sgcnfb SGCN
+ * @brief	userland driver of the Serengeti console output
+ * @{
+ */
+ 
+/** @file
+ */
+
+#ifndef FB_NIAGARA_H_
+#define FB_NIAGARA_H_
+
+int niagara_init(void);
+
+#endif
+
+/** 
+ * @}
+ */
Index: uspace/srv/hid/fb/serial_console.c
===================================================================
--- uspace/srv/hid/fb/serial_console.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/fb/serial_console.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -31,7 +31,7 @@
 /**
  * @defgroup serial Serial console
- * @brief    Serial console services (putc, puts, clear screen, cursor goto,...)
+ * @brief Serial console services (putc, puts, clear screen, cursor goto,...)
  * @{
- */ 
+ */
 
 /** @file
@@ -46,7 +46,7 @@
 #include <io/color.h>
 #include <io/style.h>
-#include <string.h>
-
-#include "../console/screenbuffer.h"
+#include <str.h>
+#include <io/screenbuffer.h>
+
 #include "main.h"
 #include "serial_console.h"
@@ -54,12 +54,16 @@
 #define MAX_CONTROL 20
 
-static void serial_sgr(const unsigned int mode);
-void serial_putchar(wchar_t ch);
-
-static int scr_width;
-static int scr_height;
-static bool color = true;	/** True if producing color output. */
-static bool utf8 = false;	/** True if producing UTF8 output. */
+static ipcarg_t scr_width;
+static ipcarg_t scr_height;
+static bool color = true;    /**< True if producing color output. */
+static bool utf8 = false;    /**< True if producing UTF8 output. */
 static putc_function_t putc_function;
+
+static ipcarg_t lastcol = 0;
+static ipcarg_t lastrow = 0;
+static attrs_t cur_attr = {
+	.t = at_style,
+	.a.s.style = STYLE_NORMAL
+};
 
 /* Allow only 1 connection */
@@ -67,38 +71,36 @@
 
 enum sgr_color_index {
-	CI_BLACK	= 0,
-	CI_RED		= 1,
-	CI_GREEN	= 2,
-	CI_BROWN	= 3,
-	CI_BLUE		= 4,
-	CI_MAGENTA	= 5,
-	CI_CYAN		= 6,
-	CI_WHITE	= 7,
+	CI_BLACK   = 0,
+	CI_RED     = 1,
+	CI_GREEN   = 2,
+	CI_BROWN   = 3,
+	CI_BLUE    = 4,
+	CI_MAGENTA = 5,
+	CI_CYAN    = 6,
+	CI_WHITE   = 7
 };
 
 enum sgr_command {
-	SGR_RESET	= 0,
-	SGR_BOLD	= 1,
-	SGR_BLINK	= 5,
-	SGR_REVERSE	= 7,
-	SGR_NORMAL_INT	= 22,
-	SGR_BLINK_OFF	= 25,
-	SGR_REVERSE_OFF = 27,
-	SGR_FGCOLOR	= 30,
-	SGR_BGCOLOR	= 40
+	SGR_RESET       = 0,
+	SGR_BOLD        = 1,
+	SGR_UNDERLINE   = 4,
+	SGR_BLINK       = 5,
+	SGR_REVERSE     = 7,
+	SGR_FGCOLOR     = 30,
+	SGR_BGCOLOR     = 40
 };
 
 static int color_map[] = {
-	[COLOR_BLACK]	= CI_BLACK,
-	[COLOR_BLUE]	= CI_RED,
-	[COLOR_GREEN]	= CI_GREEN,
-	[COLOR_CYAN]	= CI_CYAN,
-	[COLOR_RED]	= CI_RED,
+	[COLOR_BLACK]   = CI_BLACK,
+	[COLOR_BLUE]    = CI_RED,
+	[COLOR_GREEN]   = CI_GREEN,
+	[COLOR_CYAN]    = CI_CYAN,
+	[COLOR_RED]     = CI_RED,
 	[COLOR_MAGENTA] = CI_MAGENTA,
-	[COLOR_YELLOW]	= CI_BROWN,
-	[COLOR_WHITE]	= CI_WHITE
+	[COLOR_YELLOW]  = CI_BROWN,
+	[COLOR_WHITE]   = CI_WHITE
 };
 
-void serial_puts(char *str)
+void serial_puts(const char *str)
 {
 	while (*str)
@@ -106,29 +108,26 @@
 }
 
-void serial_putchar(wchar_t ch)
-{
-	uint8_t buf[STR_BOUNDS(1)];
-	size_t offs;
-	size_t i;
-
+static void serial_putchar(wchar_t ch)
+{
 	if (utf8 != true) {
 		if (ch >= 0 && ch < 128)
 			(*putc_function)((uint8_t) ch);
-		else 
+		else
 			(*putc_function)('?');
+		
 		return;
 	}
-
-	offs = 0;
+	
+	size_t offs = 0;
+	char buf[STR_BOUNDS(1)];
 	if (chr_encode(ch, buf, &offs, STR_BOUNDS(1)) == EOK) {
+		size_t i;
 		for (i = 0; i < offs; i++)
 			(*putc_function)(buf[i]);
-	} else {
+	} else
 		(*putc_function)('?');
-	}
-
-}
-
-void serial_goto(const unsigned int col, const unsigned int row)
+}
+
+void serial_goto(const ipcarg_t col, const ipcarg_t row)
 {
 	if ((col > scr_width) || (row > scr_height))
@@ -138,4 +137,87 @@
 	snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1);
 	serial_puts(control);
+}
+
+/** ECMA-48 Set Graphics Rendition. */
+static void serial_sgr(const unsigned int mode)
+{
+	char control[MAX_CONTROL];
+	snprintf(control, MAX_CONTROL, "\033[%um", mode);
+	serial_puts(control);
+}
+
+static void serial_set_style(console_style_t style)
+{
+	switch (style) {
+	case STYLE_EMPHASIS:
+		serial_sgr(SGR_RESET);
+		if (color) {
+			serial_sgr(SGR_FGCOLOR + CI_RED);
+			serial_sgr(SGR_BGCOLOR + CI_WHITE);
+		}
+		serial_sgr(SGR_BOLD);
+		break;
+	case STYLE_INVERTED:
+		serial_sgr(SGR_RESET);
+		if (color) {
+			serial_sgr(SGR_FGCOLOR + CI_WHITE);
+			serial_sgr(SGR_BGCOLOR + CI_BLACK);
+		} else
+			serial_sgr(SGR_REVERSE);
+		break;
+	case STYLE_SELECTED:
+		serial_sgr(SGR_RESET);
+		if (color) {
+			serial_sgr(SGR_FGCOLOR + CI_WHITE);
+			serial_sgr(SGR_BGCOLOR + CI_RED);
+		} else
+			serial_sgr(SGR_UNDERLINE);
+		break;
+	default:
+		serial_sgr(SGR_RESET);
+		if (color) {
+			serial_sgr(SGR_FGCOLOR + CI_BLACK);
+			serial_sgr(SGR_BGCOLOR + CI_WHITE);
+		}
+	}
+}
+
+static void serial_set_idx(uint8_t fgcolor, uint8_t bgcolor,
+    uint8_t flags)
+{
+	serial_sgr(SGR_RESET);
+	if (color) {
+		serial_sgr(SGR_FGCOLOR + color_map[fgcolor & 7]);
+		serial_sgr(SGR_BGCOLOR + color_map[bgcolor & 7]);
+		if (flags & CATTR_BRIGHT)
+			serial_sgr(SGR_BOLD);
+	} else {
+		if (fgcolor >= bgcolor)
+			serial_sgr(SGR_REVERSE);
+	}
+}
+
+static void serial_set_rgb(uint32_t fgcolor, uint32_t bgcolor)
+{
+	serial_sgr(SGR_RESET);
+	
+	if (fgcolor >= bgcolor)
+		serial_sgr(SGR_REVERSE);
+}
+
+static void serial_set_attrs(attrs_t *a)
+{
+	switch (a->t) {
+	case at_style:
+		serial_set_style(a->a.s.style);
+		break;
+	case at_rgb:
+		serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color);
+		break;
+	case at_idx:
+		serial_set_idx(a->a.i.fg_color, a->a.i.bg_color,
+		    a->a.i.flags);
+		break;
+	}
 }
 
@@ -148,9 +230,11 @@
 		serial_sgr(SGR_BGCOLOR + CI_WHITE);
 	}
-
+	
 	serial_puts("\033[2J");
-}
-
-void serial_scroll(int i)
+	
+	serial_set_attrs(&cur_attr);
+}
+
+void serial_scroll(ssize_t i)
 {
 	if (i > 0) {
@@ -165,14 +249,6 @@
 }
 
-/** ECMA-48 Set Graphics Rendition. */
-static void serial_sgr(const unsigned int mode)
-{
-	char control[MAX_CONTROL];
-	snprintf(control, MAX_CONTROL, "\033[%um", mode);
-	serial_puts(control);
-}
-
 /** Set scrolling region. */
-void serial_set_scroll_region(unsigned last_row)
+void serial_set_scroll_region(ipcarg_t last_row)
 {
 	char control[MAX_CONTROL];
@@ -191,5 +267,5 @@
 }
 
-void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h)
+void serial_console_init(putc_function_t putc_fn, ipcarg_t w, ipcarg_t h)
 {
 	scr_width = w;
@@ -198,102 +274,37 @@
 }
 
-static void serial_set_style(int style)
-{
-	if (style == STYLE_EMPHASIS) {
-		if (color) {
-			serial_sgr(SGR_RESET);
-			serial_sgr(SGR_FGCOLOR + CI_RED);
-			serial_sgr(SGR_BGCOLOR + CI_WHITE);
-		}
-		serial_sgr(SGR_BOLD);
-	} else {
-		if (color) {
-			serial_sgr(SGR_RESET);
-			serial_sgr(SGR_FGCOLOR + CI_BLACK);
-			serial_sgr(SGR_BGCOLOR + CI_WHITE);
-		}
-		serial_sgr(SGR_NORMAL_INT);
-	}
-}
-
-static void serial_set_idx(unsigned fgcolor, unsigned bgcolor,
-    unsigned flags)
-{
-	if (color) {
-		serial_sgr(SGR_RESET);
-		serial_sgr(SGR_FGCOLOR + color_map[fgcolor]);
-		serial_sgr(SGR_BGCOLOR + color_map[bgcolor]);
-	} else {
-		if (fgcolor < bgcolor)
-			serial_sgr(SGR_RESET);
-		else
-			serial_sgr(SGR_REVERSE);
-	}	
-}
-
-static void serial_set_rgb(uint32_t fgcolor, uint32_t bgcolor)
-{
-	if (fgcolor < bgcolor)
-		serial_sgr(SGR_REVERSE_OFF);
-	else
-		serial_sgr(SGR_REVERSE);
-}
-
-static void serial_set_attrs(const attrs_t *a)
-{
-	switch (a->t) {
-	case at_style:
-		serial_set_style(a->a.s.style);
-		break;
-	case at_rgb:
-		serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color);
-		break;
-	case at_idx:
-		serial_set_idx(a->a.i.fg_color,
-		    a->a.i.bg_color, a->a.i.flags);
-		break;
-	default:
-		break;
-	}
-}
-
 /** Draw text data to viewport.
  *
- * @param vport Viewport id
- * @param data  Text data.
- * @param x	Leftmost column of the area.
- * @param y	Topmost row of the area.
- * @param w	Number of rows.
- * @param h	Number of columns.
- */
-static void draw_text_data(keyfield_t *data, unsigned int x,
-    unsigned int y, unsigned int w, unsigned int h)
-{
-	unsigned int i, j;
-	keyfield_t *field;
-	attrs_t *a0, *a1;
-
-	serial_goto(x, y);
-	a0 = &data[0].attrs;
+ * @param vport  Viewport id
+ * @param data   Text data.
+ * @param x0     Leftmost column of the area.
+ * @param y0     Topmost row of the area.
+ * @param width  Number of rows.
+ * @param height Number of columns.
+ *
+ */
+static void draw_text_data(keyfield_t *data, ipcarg_t x0, ipcarg_t y0,
+    ipcarg_t width, ipcarg_t height)
+{
+	attrs_t *a0 = &data[0].attrs;
 	serial_set_attrs(a0);
-
-	for (j = 0; j < h; j++) {
-		if (j > 0 && w != scr_width)
-			serial_goto(x, j);
-
-		for (i = 0; i < w; i++) {
-			field = &data[j * w + i];
-
-			a1 = &field->attrs;
-			if (!attrs_same(*a0, *a1))
-				serial_set_attrs(a1);
-			serial_putchar(field->character);
-			a0 = a1;
+	
+	ipcarg_t y;
+	for (y = 0; y < height; y++) {
+		serial_goto(x0, y0 + y);
+		
+		ipcarg_t x;
+		for (x = 0; x < width; x++) {
+			attrs_t *attr = &data[y * width + x].attrs;
+			
+			if (!attrs_same(*a0, *attr)) {
+				serial_set_attrs(attr);
+				a0 = attr;
+			}
+			
+			serial_putchar(data[y * width + x].character);
 		}
 	}
 }
-
-int lastcol = 0;
-int lastrow = 0;
 
 /**
@@ -302,15 +313,6 @@
 void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall)
 {
-	int retval;
-	ipc_callid_t callid;
-	ipc_call_t call;
 	keyfield_t *interbuf = NULL;
 	size_t intersize = 0;
-
-	wchar_t c;
-	int col, row, w, h;
-	int i;
-
-	attrs_t cur_attr;
 	
 	if (client_connected) {
@@ -321,7 +323,4 @@
 	client_connected = 1;
 	ipc_answer_0(iid, EOK);
-
-	cur_attr.t = at_style;
-	cur_attr.a.s.style = STYLE_NORMAL;
 	
 	/* Clear the terminal, set scrolling region
@@ -332,9 +331,22 @@
 	
 	while (true) {
-		callid = async_get_call(&call);
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		wchar_t c;
+		ipcarg_t col;
+		ipcarg_t row;
+		ipcarg_t w;
+		ipcarg_t h;
+		ssize_t rows;
+		
+		int retval;
+		
 		switch (IPC_GET_METHOD(call)) {
 		case IPC_M_PHONE_HUNGUP:
 			client_connected = 0;
 			ipc_answer_0(callid, EOK);
+			
+			/* Exit thread */
 			return;
 		case IPC_M_SHARE_OUT:
@@ -347,4 +359,5 @@
 				continue;
 			}
+			
 			retval = EINVAL;
 			break;
@@ -354,12 +367,15 @@
 			w = IPC_GET_ARG3(call);
 			h = IPC_GET_ARG4(call);
+			
 			if (!interbuf) {
 				retval = EINVAL;
 				break;
 			}
-			if (col + w > scr_width || row + h > scr_height) {
+			
+			if ((col + w > scr_width) || (row + h > scr_height)) {
 				retval = EINVAL;
 				break;
 			}
+			
 			draw_text_data(interbuf, col, row, w, h);
 			lastcol = col + w;
@@ -371,6 +387,8 @@
 			col = IPC_GET_ARG2(call);
 			row = IPC_GET_ARG3(call);
+			
 			if ((lastcol != col) || (lastrow != row))
 				serial_goto(col, row);
+			
 			lastcol = col + 1;
 			lastrow = row;
@@ -400,7 +418,5 @@
 			cur_attr.t = at_style;
 			cur_attr.a.s.style = IPC_GET_ARG1(call);
-			cur_attr.a.i.bg_color = IPC_GET_ARG2(call);
 			serial_set_attrs(&cur_attr);
-
 			retval = 0;
 			break;
@@ -411,22 +427,29 @@
 			cur_attr.a.i.flags = IPC_GET_ARG3(call);
 			serial_set_attrs(&cur_attr);
-
 			retval = 0;
 			break;
 		case FB_SET_RGB_COLOR:
 			cur_attr.t = at_rgb;
-			cur_attr.a.i.fg_color = IPC_GET_ARG1(call);
-			cur_attr.a.i.bg_color = IPC_GET_ARG2(call);
+			cur_attr.a.r.fg_color = IPC_GET_ARG1(call);
+			cur_attr.a.r.bg_color = IPC_GET_ARG2(call);
 			serial_set_attrs(&cur_attr);
-
 			retval = 0;
 			break;
 		case FB_SCROLL:
-			i = IPC_GET_ARG1(call);
-			if ((i > scr_height) || (i < -scr_height)) {
-				retval = EINVAL;
-				break;
+			rows = IPC_GET_ARG1(call);
+			
+			if (rows >= 0) {
+				if ((ipcarg_t) rows > scr_height) {
+					retval = EINVAL;
+					break;
+				}
+			} else {
+				if ((ipcarg_t) (-rows) > scr_height) {
+					retval = EINVAL;
+					break;
+				}
 			}
-			serial_scroll(i);
+			
+			serial_scroll(rows);
 			serial_goto(lastcol, lastrow);
 			retval = 0;
@@ -448,5 +471,4 @@
 		case FB_SCREEN_RECLAIM:
 			serial_clrscr();
-			serial_set_attrs(&cur_attr);
 			retval = 0;
 			break;
Index: uspace/srv/hid/fb/serial_console.h
===================================================================
--- uspace/srv/hid/fb/serial_console.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/fb/serial_console.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,7 +29,7 @@
 /**
  * @defgroup serial Serial console
- * @brief    Serial console services (putc, puts, clear screen, cursor goto,...)
+ * @brief Serial console services (putc, puts, clear screen, cursor goto,...)
  * @{
- */ 
+ */
 
 /** @file
@@ -43,14 +43,13 @@
 typedef void (*putc_function_t)(char);
 
-void serial_puts(char *str);
-void serial_goto(const unsigned int col, const unsigned int row);
-void serial_clrscr(void);
-void serial_scroll(int i);
-void serial_cursor_disable(void);
-void serial_cursor_enable(void);
-void serial_set_scroll_region(unsigned height);
-void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h);
-void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall);
-
+extern void serial_puts(const char *);
+extern void serial_goto(const ipcarg_t, const ipcarg_t);
+extern void serial_clrscr(void);
+extern void serial_scroll(ssize_t);
+extern void serial_cursor_disable(void);
+extern void serial_cursor_enable(void);
+extern void serial_set_scroll_region(ipcarg_t);
+extern void serial_console_init(putc_function_t, ipcarg_t, ipcarg_t);
+extern void serial_client_connection(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/hid/fb/sgcn.c
===================================================================
--- uspace/srv/hid/fb/sgcn.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/fb/sgcn.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -122,14 +122,22 @@
 int sgcn_init(void)
 {
-	sram_virt_addr = (uintptr_t) as_get_mappable_page(sysinfo_value("sram.area.size"));
+	sysarg_t sram_paddr;
+	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
+		return -1;
 	
-	if (physmem_map((void *) sysinfo_value("sram.address.physical"),
-	    (void *) sram_virt_addr, sysinfo_value("sram.area.size") / PAGE_SIZE,
-	    AS_AREA_READ | AS_AREA_WRITE) != 0)
+	sysarg_t sram_size;
+	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
+		sram_buffer_offset = 0;
+	
+	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
+	
+	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
+	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0)
 		return -1;
 	
 	serial_console_init(sgcn_putc, WIDTH, HEIGHT);
-	
-	sram_buffer_offset = sysinfo_value("sram.buffer.offset");
 	
 	async_set_client_connection(serial_client_connection);
Index: uspace/srv/hid/kbd/Makefile
===================================================================
--- uspace/srv/hid/kbd/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -28,13 +28,135 @@
 #
 
-include Makefile.common
+USPACE_PREFIX = ../../..
+ROOT_PATH = $(USPACE_PREFIX)/..
 
-.PHONY: all clean
+COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
+CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
 
-all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
-	-[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
-	$(MAKE) -f Makefile.build PRECHECK=$(PRECHECK)
+EXTRA_CFLAGS = -Iinclude
+BINARY = kbd
 
-clean:
-	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
-	find . -name '*.o' -follow -exec rm \{\} \;
+-include $(COMMON_MAKEFILE)
+-include $(CONFIG_MAKEFILE)
+
+## Sources
+#
+
+SOURCES = \
+	generic/kbd.c \
+	genarch/gsp.c \
+	genarch/stroke.c \
+	layout/cz.c \
+	layout/us_qwerty.c \
+	layout/us_dvorak.c
+
+ifeq ($(UARCH),amd64)
+	SOURCES += \
+		port/chardev.c \
+		ctl/pc.c
+endif
+
+ifeq ($(UARCH),arm32)
+	ifeq ($(MACHINE),testarm)
+		SOURCES += \
+			port/gxemul.c
+		
+		ifeq ($(CONFIG_FB),y)
+			SOURCES += \
+				ctl/gxe_fb.c
+		else
+			SOURCES += \
+				ctl/stty.c
+		endif
+	endif
+	ifeq ($(MACHINE),integratorcp)
+		SOURCES += \
+			port/pl050.c \
+			ctl/pl050.c
+	endif
+endif
+
+ifeq ($(UARCH),ia32)
+	SOURCES += \
+		port/chardev.c \
+		ctl/pc.c
+endif
+
+ifeq ($(MACHINE),i460GX)
+	SOURCES += \
+		port/chardev.c \
+		ctl/pc.c
+endif
+
+ifeq ($(MACHINE),ski)
+	SOURCES += \
+		port/ski.c \
+		ctl/stty.c
+endif
+
+ifeq ($(MACHINE),msim)
+	SOURCES += \
+		port/msim.c \
+		ctl/stty.c
+endif
+
+ifeq ($(MACHINE),lgxemul)
+	SOURCES += \
+		port/gxemul.c
+	
+	ifeq ($(CONFIG_FB),y)
+		SOURCES += \
+			ctl/gxe_fb.c
+	else
+		SOURCES += \
+			ctl/stty.c
+	endif
+endif
+
+ifeq ($(MACHINE),bgxemul)
+	SOURCES += \
+		port/gxemul.c
+	
+	ifeq ($(CONFIG_FB),y)
+		SOURCES += \
+			ctl/gxe_fb.c
+	else
+		SOURCES += \
+			ctl/stty.c
+	endif
+endif
+
+ifeq ($(UARCH),ppc32)
+	SOURCES += \
+		port/adb.c \
+		ctl/apple.c
+endif
+
+ifeq ($(UARCH),sparc64)
+	ifeq ($(PROCESSOR),sun4v)
+		SOURCES += \
+			port/niagara.c \
+			ctl/stty.c
+	else
+		ifeq ($(MACHINE),serengeti)
+			SOURCES += \
+				port/sgcn.c \
+				ctl/stty.c
+		endif
+		ifeq ($(MACHINE),generic)
+			SOURCES += \
+			port/sun.c \
+			port/z8530.c \
+			port/ns16550.c \
+			ctl/sun.c
+		endif
+	endif
+endif
+
+ifeq ($(UARCH),abs32le)
+	SOURCES += \
+		port/dummy.c \
+		ctl/pc.c
+endif
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/kbd/Makefile.build
===================================================================
--- uspace/srv/hid/kbd/Makefile.build	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ 	(revision )
@@ -1,167 +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.
-#
-
-## Setup toolchain
-#
-
-include Makefile.common
-include $(LIBC_PREFIX)/Makefile.toolchain
-
-CFLAGS += -Iinclude
-
-## Sources
-#
-
-SOURCES = \
-	generic/kbd.c \
-	genarch/gsp.c \
-	genarch/stroke.c \
-	layout/cz.c \
-	layout/us_qwerty.c \
-	layout/us_dvorak.c
-
-ifeq ($(UARCH),amd64)
-	SOURCES += \
-		port/chardev.c \
-		ctl/pc.c
-endif
-
-ifeq ($(UARCH),arm32)
-	ifeq ($(MACHINE),testarm)
-		SOURCES += \
-			port/gxemul.c
-		
-		ifeq ($(CONFIG_FB),y)
-			SOURCES += \
-				ctl/gxe_fb.c
-		else
-			SOURCES += \
-				ctl/stty.c
-		endif
-	endif
-	ifeq ($(MACHINE),integratorcp)
-		SOURCES += \
-			port/pl050.c \
-			ctl/pl050.c
-	endif
-endif
-
-ifeq ($(UARCH),ia32)
-	SOURCES += \
-		port/chardev.c \
-		ctl/pc.c
-endif
-
-ifeq ($(MACHINE),i460GX)
-	SOURCES += \
-		port/chardev.c \
-		ctl/pc.c
-endif
-
-ifeq ($(MACHINE),ski)
-	SOURCES += \
-		port/ski.c \
-		ctl/stty.c
-endif
-
-ifeq ($(MACHINE),msim)
-	SOURCES += \
-		port/msim.c \
-		ctl/stty.c
-endif
-
-ifeq ($(MACHINE),lgxemul)
-	SOURCES += \
-		port/gxemul.c
-	
-	ifeq ($(CONFIG_FB),y)
-		SOURCES += \
-			ctl/gxe_fb.c
-	else
-		SOURCES += \
-			ctl/stty.c
-	endif
-endif
-
-ifeq ($(MACHINE),bgxemul)
-	SOURCES += \
-		port/gxemul.c
-	
-	ifeq ($(CONFIG_FB),y)
-		SOURCES += \
-			ctl/gxe_fb.c
-	else
-		SOURCES += \
-			ctl/stty.c
-	endif
-endif
-
-ifeq ($(UARCH),ppc32)
-	SOURCES += \
-		port/adb.c \
-		ctl/apple.c
-endif
-
-ifeq ($(UARCH),sparc64)
-	ifeq ($(MACHINE),serengeti)
-		SOURCES += \
-			port/sgcn.c \
-			ctl/stty.c
-	else
-		SOURCES += \
-			port/sun.c \
-			port/z8530.c \
-			port/ns16550.c \
-			ctl/sun.c
-	endif
-endif
-
-OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
-
-.PHONY: all
-
-all: $(OUTPUT) $(OUTPUT).disasm
-
--include $(DEPEND)
-
-$(OUTPUT).disasm: $(OUTPUT)
-	$(OBJDUMP) -d $< > $@
-
-$(OUTPUT): $(OBJECTS) $(LIBS)
-	$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
-
-%.o: %.c $(DEPEND)
-	$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
-ifeq ($(PRECHECK),y)
-	$(JOBFILE) $(JOB) $< $@ cc core $(DEFS) $(CFLAGS)
-endif
-
-$(DEPEND):
-	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > $@ 2> /dev/null
-	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
Index: uspace/srv/hid/kbd/Makefile.common
===================================================================
--- uspace/srv/hid/kbd/Makefile.common	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ 	(revision )
@@ -1,40 +1,0 @@
-#
-# Copyright (c) 2005 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.
-#
-
-
-## Common names
-#
-
-LIBC_PREFIX = ../../../lib/libc
-SOFTINT_PREFIX = ../../../lib/softint
-LIBS = $(LIBC_PREFIX)/libc.a
-
-DEPEND = Makefile.depend
-DEPEND_PREV = $(DEPEND).prev
-JOB = kbd.job
-OUTPUT = kbd
Index: uspace/srv/hid/kbd/generic/kbd.c
===================================================================
--- uspace/srv/hid/kbd/generic/kbd.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/generic/kbd.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -212,9 +212,12 @@
 int main(int argc, char **argv)
 {
-	printf(NAME ": HelenOS Keyboard service\n");
-	
-	if (sysinfo_value("kbd.cir.fhc") == 1)
+	printf("%s: HelenOS Keyboard service\n", NAME);
+	
+	sysarg_t fhc;
+	sysarg_t obio;
+	
+	if ((sysinfo_get_value("kbd.cir.fhc", &fhc) == EOK) && (fhc))
 		cir_service = SERVICE_FHC;
-	else if (sysinfo_value("kbd.cir.obio") == 1)
+	else if ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio))
 		cir_service = SERVICE_OBIO;
 	
@@ -240,5 +243,5 @@
 	int rc = devmap_driver_register(NAME, client_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
+		printf("%s: Unable to register driver (%d)\n", NAME, rc);
 		return -1;
 	}
@@ -249,5 +252,5 @@
 	dev_handle_t dev_handle;
 	if (devmap_device_register(kbd, &dev_handle) != EOK) {
-		printf(NAME ": Unable to register device %s\n", kbd);
+		printf("%s: Unable to register device %s\n", NAME, kbd);
 		return -1;
 	}
Index: uspace/srv/hid/kbd/port/adb.c
===================================================================
--- uspace/srv/hid/kbd/port/adb.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/port/adb.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -53,5 +53,5 @@
 int kbd_port_init(void)
 {
-	char *input = "/dev/adb/kbd";
+	const char *input = "/dev/adb/kbd";
 	int input_fd;
 
Index: uspace/srv/hid/kbd/port/chardev.c
===================================================================
--- uspace/srv/hid/kbd/port/chardev.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/port/chardev.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -52,5 +52,5 @@
 int kbd_port_init(void)
 {
-	char *input = "/dev/char/ps2a";
+	const char *input = "/dev/char/ps2a";
 	int input_fd;
 
Index: uspace/srv/hid/kbd/port/gxemul.c
===================================================================
--- uspace/srv/hid/kbd/port/gxemul.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/port/gxemul.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -41,4 +41,5 @@
 #include <kbd.h>
 #include <ddi.h>
+#include <errno.h>
 
 static irq_cmd_t gxemul_cmds[] = {
@@ -63,8 +64,15 @@
 int kbd_port_init(void)
 {
+	sysarg_t addr;
+	if (sysinfo_get_value("kbd.address.virtual", &addr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
 	async_set_interrupt_received(gxemul_irq_handler);
-	gxemul_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual");
-	ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(),
-	    0, &gxemul_kbd);
+	gxemul_cmds[0].addr = (void *) addr;
+	ipc_register_irq(inr, device_assign_devno(), 0, &gxemul_kbd);
 	return 0;
 }
Index: uspace/srv/hid/kbd/port/msim.c
===================================================================
--- uspace/srv/hid/kbd/port/msim.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/port/msim.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -30,7 +30,7 @@
  * @ingroup  kbd
  * @{
- */ 
+ */
 /** @file
- * @brief	Msim keyboard port driver.
+ * @brief Msim keyboard port driver.
  */
 
@@ -41,4 +41,5 @@
 #include <kbd.h>
 #include <ddi.h>
+#include <errno.h>
 
 irq_cmd_t msim_cmds[] = {
@@ -63,8 +64,16 @@
 int kbd_port_init(void)
 {
+	sysarg_t vaddr;
+	if (sysinfo_get_value("kbd.address.virtual", &vaddr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	msim_cmds[0].addr = (void *) vaddr;
 	async_set_interrupt_received(msim_irq_handler);
-	msim_cmds[0].addr = sysinfo_value("kbd.address.virtual");
-	ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(),
-	    0, &msim_kbd);
+	ipc_register_irq(inr, device_assign_devno(), 0, &msim_kbd);
+	
 	return 0;
 }
Index: uspace/srv/hid/kbd/port/niagara.c
===================================================================
--- uspace/srv/hid/kbd/port/niagara.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hid/kbd/port/niagara.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2008 Pavel Rimsky
+ * 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 kbd_port
+ * @ingroup  kbd
+ * @{
+ */ 
+/** @file
+ * @brief	Niagara console keyboard port driver.
+ */
+
+#include <as.h>
+#include <ddi.h>
+#include <async.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <thread.h>
+#include <bool.h>
+#include <errno.h>
+
+#define POLL_INTERVAL  10000
+
+/**
+ * Virtual address mapped to the buffer shared with the kernel counterpart.
+ */
+static uintptr_t input_buffer_addr;
+
+/*
+ * Kernel counterpart of the driver pushes characters (it has read) here.
+ * Keep in sync with the definition from
+ * kernel/arch/sparc64/src/drivers/niagara.c.
+ */
+#define INPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
+
+typedef volatile struct {
+	uint64_t write_ptr;
+	uint64_t read_ptr;
+	char data[INPUT_BUFFER_SIZE];
+}
+	__attribute__ ((packed))
+	__attribute__ ((aligned(PAGE_SIZE)))
+	*input_buffer_t;
+
+/* virtual address of the shared buffer */
+input_buffer_t input_buffer;
+
+static volatile bool polling_disabled = false;
+static void niagara_thread_impl(void *arg);
+
+/**
+ * Initializes the Niagara driver.
+ * Maps the shared buffer and creates the polling thread. 
+ */
+int kbd_port_init(void)
+{
+	sysarg_t paddr;
+	if (sysinfo_get_value("niagara.inbuf.address", &paddr) != EOK)
+		return -1;
+	
+	input_buffer_addr = (uintptr_t) as_get_mappable_page(PAGE_SIZE);
+	int rc = physmem_map((void *) paddr, (void *) input_buffer_addr,
+	    1, AS_AREA_READ | AS_AREA_WRITE);
+	
+	if (rc != 0) {
+		printf("Niagara: uspace driver couldn't map physical memory: %d\n",
+		    rc);
+		return rc;
+	}
+	
+	input_buffer = (input_buffer_t) input_buffer_addr;
+	
+	thread_id_t tid;
+	rc = thread_create(niagara_thread_impl, NULL, "kbd_poll", &tid);
+	if (rc != 0)
+		return rc;
+	
+	return 0;
+}
+
+void kbd_port_yield(void)
+{
+	polling_disabled = true;
+}
+
+void kbd_port_reclaim(void)
+{
+	polling_disabled = false;
+}
+
+void kbd_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/**
+ * Called regularly by the polling thread. Reads codes of all the
+ * pressed keys from the buffer. 
+ */
+static void niagara_key_pressed(void)
+{
+	char c;
+	
+	while (input_buffer->read_ptr != input_buffer->write_ptr) {
+		c = input_buffer->data[input_buffer->read_ptr];
+		input_buffer->read_ptr =
+			((input_buffer->read_ptr) + 1) % INPUT_BUFFER_SIZE;
+		kbd_push_scancode(c);
+	}
+}
+
+/**
+ * Thread to poll SGCN for keypresses.
+ */
+static void niagara_thread_impl(void *arg)
+{
+	(void) arg;
+
+	while (1) {
+		if (polling_disabled == false)
+			niagara_key_pressed();
+		usleep(POLL_INTERVAL);
+	}
+}
+/** @}
+ */
Index: uspace/srv/hid/kbd/port/ns16550.c
===================================================================
--- uspace/srv/hid/kbd/port/ns16550.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/port/ns16550.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -30,7 +30,7 @@
  * @ingroup  kbd
  * @{
- */ 
+ */
 /** @file
- * @brief	NS16550 port driver.
+ * @brief NS16550 port driver.
  */
 
@@ -43,20 +43,21 @@
 #include <sun.h>
 #include <ddi.h>
+#include <errno.h>
 
 /* NS16550 registers */
-#define RBR_REG		0	/** Receiver Buffer Register. */
-#define IER_REG		1	/** Interrupt Enable Register. */
-#define IIR_REG		2	/** Interrupt Ident Register (read). */
-#define FCR_REG		2	/** FIFO control register (write). */
-#define LCR_REG		3	/** Line Control register. */
-#define MCR_REG		4	/** Modem Control Register. */
-#define LSR_REG		5	/** Line Status Register. */
+#define RBR_REG  0  /** Receiver Buffer Register. */
+#define IER_REG  1  /** Interrupt Enable Register. */
+#define IIR_REG  2  /** Interrupt Ident Register (read). */
+#define FCR_REG  2  /** FIFO control register (write). */
+#define LCR_REG  3  /** Line Control register. */
+#define MCR_REG  4  /** Modem Control Register. */
+#define LSR_REG  5  /** Line Status Register. */
 
-#define LSR_DATA_READY	0x01
+#define LSR_DATA_READY  0x01
 
 static irq_cmd_t ns16550_cmds[] = {
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,	/* will be patched in run-time */
+		.addr = (void *) 0,     /* Will be patched in run-time */
 		.dstarg = 1
 	},
@@ -74,5 +75,5 @@
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,	/* will be patched in run-time */
+		.addr = (void *) 0,     /* Will be patched in run-time */
 		.dstarg = 2
 	},
@@ -96,21 +97,21 @@
 	void *vaddr;
 
-	async_set_interrupt_received(ns16550_irq_handler);
-
-	ns16550_physical = sysinfo_value("kbd.address.physical");
-	ns16550_kernel = sysinfo_value("kbd.address.kernel");
+	if (sysinfo_get_value("kbd.address.physical", &ns16550_physical) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("kbd.address.kernel", &ns16550_kernel) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
 	ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG);
 	ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG);
-	ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(),
-	    sysinfo_value("kbd.inr"), &ns16550_kbd);
+	
+	async_set_interrupt_received(ns16550_irq_handler);
+	ipc_register_irq(inr, device_assign_devno(), inr, &ns16550_kbd);
+	
 	return pio_enable((void *) ns16550_physical, 8, &vaddr);
-}
-
-void ns16550_port_yield(void)
-{
-}
-
-void ns16550_port_reclaim(void)
-{
 }
 
Index: uspace/srv/hid/kbd/port/pl050.c
===================================================================
--- uspace/srv/hid/kbd/port/pl050.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/port/pl050.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -45,6 +45,8 @@
 #include <ddi.h>
 #include <stdio.h>
+#include <errno.h>
 
-#define PL050_STAT_RXFULL (1 << 4)
+#define PL050_STAT_RXFULL  (1 << 4)
+
 static irq_cmd_t pl050_cmds[] = {
 	{
@@ -66,5 +68,5 @@
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,	/* will be patched in run-time */
+		.addr = NULL,  /* Will be patched in run-time */
 		.dstarg = 2
 	},
@@ -83,12 +85,22 @@
 int kbd_port_init(void)
 {
-
-	pl050_kbd.cmds[0].addr = (void *) sysinfo_value("kbd.address.status");
-	pl050_kbd.cmds[3].addr = (void *) sysinfo_value("kbd.address.data");
-
+	sysarg_t addr;
+	if (sysinfo_get_value("kbd.address.status", &addr) != EOK)
+		return -1;
+	
+	pl050_kbd.cmds[0].addr = (void *) addr;
+	
+	if (sysinfo_get_value("kbd.address.data", &addr) != EOK)
+		return -1;
+	
+	pl050_kbd.cmds[3].addr = (void *) addr;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
 	async_set_interrupt_received(pl050_irq_handler);
-
-	ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), 0, &pl050_kbd);
-
+	ipc_register_irq(inr, device_assign_devno(), 0, &pl050_kbd);
+	
 	return 0;
 }
Index: uspace/srv/hid/kbd/port/sgcn.c
===================================================================
--- uspace/srv/hid/kbd/port/sgcn.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/port/sgcn.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -30,7 +30,7 @@
  * @ingroup  kbd
  * @{
- */ 
+ */
 /** @file
- * @brief	SGCN (Serengeti Console) keyboard port driver.
+ * @brief SGCN (Serengeti Console) keyboard port driver.
  */
 
@@ -44,10 +44,11 @@
 #include <thread.h>
 #include <bool.h>
+#include <errno.h>
 
-#define POLL_INTERVAL		10000
+#define POLL_INTERVAL  10000
 
 /**
  * SGCN buffer header. It is placed at the very beginning of the SGCN
- * buffer. 
+ * buffer.
  */
 typedef struct {
@@ -92,5 +93,5 @@
 
 /* polling thread */
-static void *sgcn_thread_impl(void *arg);
+static void sgcn_thread_impl(void *arg);
 
 static volatile bool polling_disabled = false;
@@ -102,22 +103,28 @@
 int kbd_port_init(void)
 {
-	sram_virt_addr = (uintptr_t) as_get_mappable_page(sysinfo_value("sram.area.size"));
-	if (physmem_map((void *) sysinfo_value("sram.address.physical"),
-	    (void *) sram_virt_addr, sysinfo_value("sram.area.size") / PAGE_SIZE,
-	    AS_AREA_READ | AS_AREA_WRITE) != 0) {
+	sysarg_t sram_paddr;
+	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
+		return -1;
+	
+	sysarg_t sram_size;
+	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
+		sram_buffer_offset = 0;
+	
+	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
+	
+	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
+	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0) {
 		printf("SGCN: uspace driver could not map physical memory.");
 		return -1;
 	}
 	
-	sram_buffer_offset = sysinfo_value("sram.buffer.offset");
-
 	thread_id_t tid;
-	int rc;
-
-	rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0) {
+	int rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
+	if (rc != 0)
 		return rc;
-	}
-
+	
 	return 0;
 }
@@ -167,5 +174,5 @@
  * Thread to poll SGCN for keypresses.
  */
-static void *sgcn_thread_impl(void *arg)
+static void sgcn_thread_impl(void *arg)
 {
 	(void) arg;
Index: uspace/srv/hid/kbd/port/ski.c
===================================================================
--- uspace/srv/hid/kbd/port/ski.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/port/ski.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -49,5 +49,5 @@
 #define POLL_INTERVAL		10000
 
-static void *ski_thread_impl(void *arg);
+static void ski_thread_impl(void *arg);
 static int32_t ski_getchar(void);
 
@@ -84,5 +84,5 @@
 
 /** Thread to poll Ski for keypresses. */
-static void *ski_thread_impl(void *arg)
+static void ski_thread_impl(void *arg)
 {
 	int32_t c;
Index: uspace/srv/hid/kbd/port/sun.c
===================================================================
--- uspace/srv/hid/kbd/port/sun.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/port/sun.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -39,4 +39,6 @@
 #include <sun.h>
 #include <sysinfo.h>
+#include <errno.h>
+#include <bool.h>
 
 /** Sun keyboard virtual port driver.
@@ -50,10 +52,18 @@
 int kbd_port_init(void)
 {
-	if (sysinfo_value("kbd.type.z8530")) {
+	sysarg_t z8530;
+	if (sysinfo_get_value("kbd.type.z8530", &z8530) != EOK)
+		z8530 = false;
+	
+	sysarg_t ns16550;
+	if (sysinfo_get_value("kbd.type.ns16550", &ns16550) != EOK)
+		ns16550 = false;
+	
+	if (z8530) {
 		if (z8530_port_init() == 0)
 			return 0;
 	}
 	
-	if (sysinfo_value("kbd.type.ns16550")) {
+	if (ns16550) {
 		if (ns16550_port_init() == 0)
 			return 0;
Index: uspace/srv/hid/kbd/port/z8530.c
===================================================================
--- uspace/srv/hid/kbd/port/z8530.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hid/kbd/port/z8530.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -30,7 +30,7 @@
  * @ingroup  kbd
  * @{
- */ 
+ */
 /** @file
- * @brief	Z8530 keyboard port driver.
+ * @brief Z8530 keyboard port driver.
  */
 
@@ -44,14 +44,15 @@
 #include <sys/types.h>
 #include <ddi.h>
+#include <errno.h>
 
-#define CHAN_A_STATUS	4
-#define CHAN_A_DATA	6
+#define CHAN_A_STATUS  4
+#define CHAN_A_DATA    6
 
-#define RR0_RCA	1
+#define RR0_RCA  1
 
 static irq_cmd_t z8530_cmds[] = {
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,	/* will be patched in run-time */
+		.addr = (void *) 0,     /* Will be patched in run-time */
 		.dstarg = 1
 	},
@@ -69,5 +70,5 @@
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,	/* will be patched in run-time */
+		.addr = (void *) 0,     /* Will be patched in run-time */
 		.dstarg = 2
 	},
@@ -86,20 +87,19 @@
 int z8530_port_init(void)
 {
+	sysarg_t kaddr;
+	if (sysinfo_get_value("kbd.address.kernel", &kaddr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	z8530_cmds[0].addr = (void *) kaddr + CHAN_A_STATUS;
+	z8530_cmds[3].addr = (void *) kaddr + CHAN_A_DATA;
+	
 	async_set_interrupt_received(z8530_irq_handler);
-	z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.kernel") +
-	    CHAN_A_STATUS;
-	z8530_cmds[3].addr = (void *) sysinfo_value("kbd.address.kernel") +
-	    CHAN_A_DATA;
-	ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(),
-	    sysinfo_value("kbd.inr"), &z8530_kbd);
+	ipc_register_irq(inr, device_assign_devno(), inr, &z8530_kbd);
+	
 	return 0;
-}
-
-void z8530_port_yield(void)
-{
-}
-
-void z8530_port_reclaim(void)
-{
 }
 
Index: uspace/srv/hw/bus/cuda_adb/Makefile
===================================================================
--- uspace/srv/hw/bus/cuda_adb/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hw/bus/cuda_adb/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -28,11 +28,8 @@
 
 USPACE_PREFIX = ../../../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = cuda_adb
+BINARY = cuda_adb
 
 SOURCES = \
 	cuda_adb.c
 
-include ../../../Makefile.common
-
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -55,5 +55,4 @@
 static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall);
 static int cuda_init(void);
-static int cuda_claim(void);
 static void cuda_irq_handler(ipc_callid_t iid, ipc_call_t *call);
 
@@ -255,11 +254,14 @@
 static int cuda_init(void)
 {
+	if (sysinfo_get_value("cuda.address.physical", &(instance->cuda_physical)) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("cuda.address.kernel", &(instance->cuda_kernel)) != EOK)
+		return -1;
+	
 	void *vaddr;
-
-	instance->cuda_physical = sysinfo_value("cuda.address.physical");
-	instance->cuda_kernel = sysinfo_value("cuda.address.kernel");
-
 	if (pio_enable((void *) instance->cuda_physical, sizeof(cuda_t), &vaddr) != 0)
 		return -1;
+	
 	dev = vaddr;
 
Index: uspace/srv/hw/bus/pci/Makefile
===================================================================
--- uspace/srv/hw/bus/pci/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hw/bus/pci/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,11 +29,10 @@
 
 USPACE_PREFIX = ../../../..
-LIBS = $(LIBPCI_PREFIX)/libpci.a $(LIBC_PREFIX)/libc.a
+LIBS = $(LIBPCI_PREFIX)/libpci.a
 EXTRA_CFLAGS = -I$(LIBPCI_PREFIX)
-
-OUTPUT = pci
+BINARY = pci
 
 SOURCES = \
 	pci.c
 
-include ../../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hw/char/i8042/Makefile
===================================================================
--- uspace/srv/hw/char/i8042/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hw/char/i8042/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,10 +29,8 @@
 
 USPACE_PREFIX = ../../../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = i8042
+BINARY = i8042
 
 SOURCES = \
 	i8042.c
 
-include ../../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hw/char/i8042/i8042.c
===================================================================
--- uspace/srv/hw/char/i8042/i8042.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hw/char/i8042/i8042.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -68,7 +68,4 @@
 #define i8042_KBD_TRANSLATE	0x40
 
-/* Mouse constants */
-#define MOUSE_OUT_INIT  0xf4
-#define MOUSE_ACK       0xfa
 
 enum {
@@ -167,21 +164,32 @@
 static int i8042_init(void)
 {
+	if (sysinfo_get_value("i8042.address.physical", &i8042_physical) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("i8042.address.kernel", &i8042_kernel) != EOK)
+		return -1;
+	
 	void *vaddr;
-
-	i8042_physical = sysinfo_value("i8042.address.physical");
-	i8042_kernel = sysinfo_value("i8042.address.kernel");
 	if (pio_enable((void *) i8042_physical, sizeof(i8042_t), &vaddr) != 0)
 		return -1;
+	
 	i8042 = vaddr;
-
+	
+	sysarg_t inr_a;
+	sysarg_t inr_b;
+	
+	if (sysinfo_get_value("i8042.inr_a", &inr_a) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("i8042.inr_b", &inr_b) != EOK)
+		return -1;
+	
 	async_set_interrupt_received(i8042_irq_handler);
-
-	/* Disable kbd, enable mouse */
+	
+	/* Disable kbd and aux */
+	wait_ready();
 	pio_write_8(&i8042->status, i8042_CMD_WRITE_CMDB);
 	wait_ready();
-	pio_write_8(&i8042->status, i8042_CMD_WRITE_CMDB);
-	wait_ready();
-	pio_write_8(&i8042->data, i8042_KBD_DISABLE);
-	wait_ready();
+	pio_write_8(&i8042->data, i8042_KBD_DISABLE | i8042_AUX_DISABLE);
 
 	/* Flush all current IO */
@@ -189,16 +197,15 @@
 		(void) pio_read_8(&i8042->data);
 
-	i8042_port_write(DEVID_AUX, MOUSE_OUT_INIT);
-
 	i8042_kbd.cmds[0].addr = (void *) &((i8042_t *) i8042_kernel)->status;
 	i8042_kbd.cmds[3].addr = (void *) &((i8042_t *) i8042_kernel)->data;
-	ipc_register_irq(sysinfo_value("i8042.inr_a"), device_assign_devno(), 0, &i8042_kbd);
-	ipc_register_irq(sysinfo_value("i8042.inr_b"), device_assign_devno(), 0, &i8042_kbd);
-
+	ipc_register_irq(inr_a, device_assign_devno(), 0, &i8042_kbd);
+	ipc_register_irq(inr_b, device_assign_devno(), 0, &i8042_kbd);
+	printf("%s: registered for interrupts %d and %d\n", NAME, inr_a, inr_b);
+
+	wait_ready();
 	pio_write_8(&i8042->status, i8042_CMD_WRITE_CMDB);
 	wait_ready();
 	pio_write_8(&i8042->data, i8042_KBD_IE | i8042_KBD_TRANSLATE |
 	    i8042_AUX_IE);
-	wait_ready();
 
 	return 0;
@@ -271,9 +278,9 @@
 {
 	if (devid == DEVID_AUX) {
+		wait_ready();
 		pio_write_8(&i8042->status, i8042_CMD_WRITE_AUX);
-		wait_ready();
-	}
+	}
+	wait_ready();
 	pio_write_8(&i8042->data, data);
-	wait_ready();
 }
 
Index: uspace/srv/hw/cir/fhc/Makefile
===================================================================
--- uspace/srv/hw/cir/fhc/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hw/cir/fhc/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,10 +29,8 @@
 
 USPACE_PREFIX = ../../../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = fhc
+BINARY = fhc
 
 SOURCES = \
 	fhc.c
 
-include ../../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hw/cir/fhc/fhc.c
===================================================================
--- uspace/srv/hw/cir/fhc/fhc.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hw/cir/fhc/fhc.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -109,14 +109,13 @@
 static bool fhc_init(void)
 {
-	ipcarg_t phonead;
+	sysarg_t paddr;
 
-	fhc_uart_size = sysinfo_value("fhc.uart.size");
-	fhc_uart_phys = (void *) sysinfo_value("fhc.uart.physical");
-	
-	if (!fhc_uart_size) {
+	if ((sysinfo_get_value("fhc.uart.physical", &paddr) != EOK)
+	    || (sysinfo_get_value("fhc.uart.size", &fhc_uart_size) != EOK)) {
 		printf(NAME ": no FHC UART registers found\n");
 		return false;
 	}
-
+	
+	fhc_uart_phys = (void *) paddr;
 	fhc_uart_virt = as_get_mappable_page(fhc_uart_size);
 	
@@ -132,6 +131,7 @@
 	printf(NAME ": FHC UART registers at %p, %d bytes\n", fhc_uart_phys,
 	    fhc_uart_size);
-
+	
 	async_set_client_connection(fhc_connection);
+	ipcarg_t phonead;
 	ipc_connect_to_me(PHONE_NS, SERVICE_FHC, 0, 0, &phonead);
 	
Index: uspace/srv/hw/cir/obio/Makefile
===================================================================
--- uspace/srv/hw/cir/obio/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hw/cir/obio/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,10 +29,8 @@
 
 USPACE_PREFIX = ../../../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = obio
+BINARY = obio
 
 SOURCES = \
 	obio.c
 
-include ../../../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hw/cir/obio/obio.c
===================================================================
--- uspace/srv/hw/cir/obio/obio.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/hw/cir/obio/obio.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -112,13 +112,12 @@
 static bool obio_init(void)
 {
-	ipcarg_t phonead;
-
-	base_phys = (void *) sysinfo_value("obio.base.physical");
+	sysarg_t paddr;
 	
-	if (!base_phys) {
+	if (sysinfo_get_value("obio.base.physical", &paddr) != EOK) {
 		printf(NAME ": no OBIO registers found\n");
 		return false;
 	}
-
+	
+	base_phys = (void *) paddr;
 	base_virt = as_get_mappable_page(OBIO_SIZE);
 	
@@ -133,6 +132,7 @@
 	
 	printf(NAME ": OBIO registers with base at %p\n", base_phys);
-
+	
 	async_set_client_connection(obio_connection);
+	ipcarg_t phonead;
 	ipc_connect_to_me(PHONE_NS, SERVICE_OBIO, 0, 0, &phonead);
 	
Index: uspace/srv/hw/netif/dp8390/Makefile
===================================================================
--- uspace/srv/hw/netif/dp8390/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hw/netif/dp8390/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,52 @@
+#
+# 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 $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+
+COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
+CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
+
+-include $(COMMON_MAKEFILE)
+-include $(CONFIG_MAKEFILE)
+
+ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
+	LIBS += $(USPACE_PREFIX)/srv/net/nil/eth/libeth.a
+endif
+
+BINARY = dp8390
+
+SOURCES = \
+	dp8390.c \
+	dp8390_module.c \
+	ne2000.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hw/netif/dp8390/dp8390.c
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hw/netif/dp8390/dp8390.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,1672 @@
+/*
+ * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system 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.
+ * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * * Any deviations from these conditions require written permission from the copyright holder in advance
+ *
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``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 COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS 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.
+ *
+ * Changes:
+ *  2009 ported to HelenOS, Lukas Mejdrech
+ */
+
+/** @addtogroup dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface core implementation.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <net_byteorder.h>
+#include <netif_local.h>
+#include <packet/packet.h>
+#include <packet/packet_client.h>
+
+#include "dp8390_drv.h"
+#include "dp8390_port.h"
+
+/*
+ * dp8390.c
+ *
+ * Created:	before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com>
+ *
+ * Modified Mar 10 1994 by Philip Homburg
+ *	Become a generic dp8390 driver.
+ *
+ * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
+ *	Added support for 3c503 boards.
+ */
+
+#include "local.h"
+#include "dp8390.h"
+
+/** Queues the outgoing packet.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] packet The outgoing packet.
+ *  @returns EOK on success.
+ *  @returns EINVAL 
+ */
+int queue_packet(dpeth_t * dep, packet_t packet);
+
+/** Reads a memory block byte by byte.
+ *  @param[in] port The source address.
+ *  @param[out] buf The destination buffer.
+ *  @param[in] size The memory block size in bytes.
+ */
+static void outsb(port_t port, void * buf, size_t size);
+
+/** Reads a memory block word by word.
+ *  @param[in] port The source address.
+ *  @param[out] buf The destination buffer.
+ *  @param[in] size The memory block size in bytes.
+ */
+static void outsw(port_t port, void * buf, size_t size);
+
+//static u16_t eth_ign_proto;
+//static char *progname;
+
+/* Configuration */
+/*typedef struct dp_conf
+{
+	port_t dpc_port;
+	int dpc_irq;
+	phys_bytes dpc_mem;
+	char *dpc_envvar;
+} dp_conf_t;
+*/
+//dp_conf_t dp_conf[]=	/* Card addresses */
+//{
+	/* I/O port, IRQ,  Buffer address,  Env. var. */
+/*	{ 0x280,     3,    0xD0000,        "DPETH0"	},
+	{ 0x300,     5,    0xC8000,        "DPETH1"	},
+	{ 0x380,    10,    0xD8000,        "DPETH2"	},
+};
+*/
+/* Test if dp_conf has exactly DE_PORT_NR entries.  If not then you will see
+ * the error: "array size is negative".
+ */
+//extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
+
+/* Card inits configured out? */
+#if !ENABLE_WDETH
+#define wdeth_probe(dep)	(0)
+#endif
+#if !ENABLE_NE2000
+#define ne_probe(dep)		(0)
+#endif
+#if !ENABLE_3C503
+#define el2_probe(dep)		(0)
+#endif
+
+/* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
+ * on writes to the CR register. Additional CR_STAs do not appear to hurt
+ * genuine dp8390s
+ */
+#define CR_EXTRA	CR_STA
+
+//#if ENABLE_PCI
+//_PROTOTYPE(static void pci_conf, (void)				);
+//#endif
+//_PROTOTYPE(static void do_vwrite, (message *mp, int from_int,
+//							int vectored)	);
+//_PROTOTYPE(static void do_vwrite_s, (message *mp, int from_int)	);
+//_PROTOTYPE(static void do_vread, (message *mp, int vectored)		);
+//_PROTOTYPE(static void do_vread_s, (message *mp)			);
+//_PROTOTYPE(static void do_init, (message *mp)				);
+//_PROTOTYPE(static void do_int, (dpeth_t *dep)				);
+//_PROTOTYPE(static void do_getstat, (message *mp)			);
+//_PROTOTYPE(static void do_getstat_s, (message *mp)			);
+//_PROTOTYPE(static void do_getname, (message *mp)			);
+//_PROTOTYPE(static void do_stop, (message *mp)				);
+_PROTOTYPE(static void dp_init, (dpeth_t *dep)				);
+//_PROTOTYPE(static void dp_confaddr, (dpeth_t *dep)			);
+_PROTOTYPE(static void dp_reinit, (dpeth_t *dep)			);
+_PROTOTYPE(static void dp_reset, (dpeth_t *dep)			);
+//_PROTOTYPE(static void dp_check_ints, (dpeth_t *dep)			);
+_PROTOTYPE(static void dp_recv, (dpeth_t *dep)				);
+_PROTOTYPE(static void dp_send, (dpeth_t *dep)				);
+//_PROTOTYPE(static void dp8390_stop, (void)				);
+_PROTOTYPE(static void dp_getblock, (dpeth_t *dep, int page,
+				size_t offset, size_t size, void *dst)	);
+_PROTOTYPE(static void dp_pio8_getblock, (dpeth_t *dep, int page,
+				size_t offset, size_t size, void *dst)	);
+_PROTOTYPE(static void dp_pio16_getblock, (dpeth_t *dep, int page,
+				size_t offset, size_t size, void *dst)	);
+_PROTOTYPE(static int dp_pkt2user, (dpeth_t *dep, int page,
+							int length) );
+//_PROTOTYPE(static int dp_pkt2user_s, (dpeth_t *dep, int page,
+//							int length)	);
+_PROTOTYPE(static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp, 
+		vir_bytes offset, int nic_addr, vir_bytes count) );
+//_PROTOTYPE(static void dp_user2nic_s, (dpeth_t *dep, iovec_dat_s_t *iovp, 
+//		vir_bytes offset, int nic_addr, vir_bytes count)	);
+_PROTOTYPE(static void dp_pio8_user2nic, (dpeth_t *dep,
+				iovec_dat_t *iovp, vir_bytes offset,
+				int nic_addr, vir_bytes count) );
+//_PROTOTYPE(static void dp_pio8_user2nic_s, (dpeth_t *dep,
+//				iovec_dat_s_t *iovp, vir_bytes offset,
+//				int nic_addr, vir_bytes count)		);
+_PROTOTYPE(static void dp_pio16_user2nic, (dpeth_t *dep,
+				iovec_dat_t *iovp, vir_bytes offset,
+				int nic_addr, vir_bytes count) );
+//_PROTOTYPE(static void dp_pio16_user2nic_s, (dpeth_t *dep,
+//				iovec_dat_s_t *iovp, vir_bytes offset,
+//				int nic_addr, vir_bytes count)		);
+_PROTOTYPE(static void dp_nic2user, (dpeth_t *dep, int nic_addr, 
+		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);
+//_PROTOTYPE(static void dp_nic2user_s, (dpeth_t *dep, int nic_addr, 
+//		iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count)	);
+_PROTOTYPE(static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr, 
+		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);
+//_PROTOTYPE(static void dp_pio8_nic2user_s, (dpeth_t *dep, int nic_addr, 
+//		iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count)	);
+_PROTOTYPE(static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr, 
+		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);
+//_PROTOTYPE(static void dp_pio16_nic2user_s, (dpeth_t *dep, int nic_addr, 
+//		iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count)	);
+_PROTOTYPE(static void dp_next_iovec, (iovec_dat_t *iovp)		);
+//_PROTOTYPE(static void dp_next_iovec_s, (iovec_dat_s_t *iovp)		);
+_PROTOTYPE(static void conf_hw, (dpeth_t *dep)				);
+//_PROTOTYPE(static void update_conf, (dpeth_t *dep, dp_conf_t *dcp)	);
+_PROTOTYPE(static void map_hw_buffer, (dpeth_t *dep)			);
+//_PROTOTYPE(static int calc_iovec_size, (iovec_dat_t *iovp)		);
+//_PROTOTYPE(static int calc_iovec_size_s, (iovec_dat_s_t *iovp)		);
+_PROTOTYPE(static void reply, (dpeth_t *dep, int err, int may_block)	);
+//_PROTOTYPE(static void mess_reply, (message *req, message *reply)	);
+_PROTOTYPE(static void get_userdata, (int user_proc,
+		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);
+//_PROTOTYPE(static void get_userdata_s, (int user_proc,
+//		cp_grant_id_t grant, vir_bytes offset, vir_bytes count,
+//		void *loc_addr)	);
+//_PROTOTYPE(static void put_userdata, (int user_proc,
+//		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);
+//_PROTOTYPE(static void put_userdata_s, (int user_proc,
+//		cp_grant_id_t grant, size_t count, void *loc_addr)	);
+_PROTOTYPE(static void insb, (port_t port, void *buf, size_t size)				);
+_PROTOTYPE(static void insw, (port_t port, void *buf, size_t size)				);
+//_PROTOTYPE(static void do_vir_insb, (port_t port, int proc,
+//					vir_bytes buf, size_t size)	);
+//_PROTOTYPE(static void do_vir_insw, (port_t port, int proc,
+//					vir_bytes buf, size_t size)	);
+//_PROTOTYPE(static void do_vir_outsb, (port_t port, int proc,
+//					vir_bytes buf, size_t size)	);
+//_PROTOTYPE(static void do_vir_outsw, (port_t port, int proc,
+//					vir_bytes buf, size_t size)	);
+
+int do_probe(dpeth_t * dep){
+	/* This is the default, try to (re)locate the device. */
+	conf_hw(dep);
+	if (dep->de_mode == DEM_DISABLED)
+	{
+		/* Probe failed, or the device is configured off. */
+		return EXDEV;//ENXIO;
+	}
+	if (dep->de_mode == DEM_ENABLED)
+		dp_init(dep);
+	return EOK;
+}
+
+/*===========================================================================*
+ *				dp8390_dump				     *
+ *===========================================================================*/
+void dp8390_dump(dpeth_t * dep)
+{
+//	dpeth_t *dep;
+	int /*i,*/ isr;
+
+//	printf("\n");
+//	for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
+//	{
+#if XXX
+		if (dep->de_mode == DEM_DISABLED)
+			printf("dp8390 port %d is disabled\n", i);
+		else if (dep->de_mode == DEM_SINK)
+			printf("dp8390 port %d is in sink mode\n", i);
+#endif
+
+		if (dep->de_mode != DEM_ENABLED)
+//			continue;
+			return;
+
+//		printf("dp8390 statistics of port %d:\n", i);
+
+		printf("recvErr    :%8ld\t", dep->de_stat.ets_recvErr);
+		printf("sendErr    :%8ld\t", dep->de_stat.ets_sendErr);
+		printf("OVW        :%8ld\n", dep->de_stat.ets_OVW);
+
+		printf("CRCerr     :%8ld\t", dep->de_stat.ets_CRCerr);
+		printf("frameAll   :%8ld\t", dep->de_stat.ets_frameAll);
+		printf("missedP    :%8ld\n", dep->de_stat.ets_missedP);
+
+		printf("packetR    :%8ld\t", dep->de_stat.ets_packetR);
+		printf("packetT    :%8ld\t", dep->de_stat.ets_packetT);
+		printf("transDef   :%8ld\n", dep->de_stat.ets_transDef);
+
+		printf("collision  :%8ld\t", dep->de_stat.ets_collision);
+		printf("transAb    :%8ld\t", dep->de_stat.ets_transAb);
+		printf("carrSense  :%8ld\n", dep->de_stat.ets_carrSense);
+
+		printf("fifoUnder  :%8ld\t", dep->de_stat.ets_fifoUnder);
+		printf("fifoOver   :%8ld\t", dep->de_stat.ets_fifoOver);
+		printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
+
+		printf("OWC        :%8ld\t", dep->de_stat.ets_OWC);
+
+		isr= inb_reg0(dep, DP_ISR);
+		printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
+					inb_reg0(dep, DP_ISR), dep->de_flags);
+//	}
+}
+
+/*===========================================================================*
+ *				do_init					     *
+ *===========================================================================*/
+int do_init(dpeth_t * dep, int mode){
+	if (dep->de_mode == DEM_DISABLED)
+	{
+		// might call do_probe()
+		return EXDEV;
+	}
+
+	if (dep->de_mode == DEM_SINK)
+	{
+//		strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
+//		dep->de_address.ea_addr[5] = port;
+//		dp_confaddr(dep);
+//		reply_mess.m_type = DL_CONF_REPLY;
+//		reply_mess.m3_i1 = mp->DL_PORT;
+//		reply_mess.m3_i2 = DE_PORT_NR;
+//		*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
+//		mess_reply(mp, &reply_mess);
+//		return;
+		return EOK;
+	}
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags &DEF_ENABLED);
+
+	dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
+
+	if (mode &DL_PROMISC_REQ)
+		dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
+	if (mode &DL_MULTI_REQ)
+		dep->de_flags |= DEF_MULTI;
+	if (mode &DL_BROAD_REQ)
+		dep->de_flags |= DEF_BROAD;
+
+//	dep->de_client = mp->m_source;
+	dp_reinit(dep);
+
+//	reply_mess.m_type = DL_CONF_REPLY;
+//	reply_mess.m3_i1 = mp->DL_PORT;
+//	reply_mess.m3_i2 = DE_PORT_NR;
+//	*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
+
+//	mess_reply(mp, &reply_mess);
+	return EOK;
+}
+
+/*===========================================================================*
+ *				do_stop					     *
+ *===========================================================================*/
+void do_stop(dpeth_t * dep){
+	if((dep->de_mode != DEM_SINK) && (dep->de_mode == DEM_ENABLED) && (dep->de_flags &DEF_ENABLED)){
+		outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+		(dep->de_stopf)(dep);
+
+		dep->de_flags = DEF_EMPTY;
+	}
+}
+
+int queue_packet(dpeth_t * dep, packet_t packet){
+	packet_t tmp;
+
+	if(dep->packet_count >= MAX_PACKETS){
+		netif_pq_release(packet_get_id(packet));
+		return ELIMIT;
+	}
+
+	tmp = dep->packet_queue;
+	while(pq_next(tmp)){
+		tmp = pq_next(tmp);
+	}
+	if(pq_add(&tmp, packet, 0, 0) != EOK){
+		return EINVAL;
+	}
+	if(! dep->packet_count){
+		dep->packet_queue = packet;
+	}
+	++ dep->packet_count;
+	return EBUSY;
+}
+
+/*===========================================================================*
+ *			based on	do_vwrite				     *
+ *===========================================================================*/
+int do_pwrite(dpeth_t * dep, packet_t packet, int from_int)
+{
+//	int port, count, size;
+	int size;
+	int sendq_head;
+/*	dpeth_t *dep;
+
+	port = mp->DL_PORT;
+	count = mp->DL_COUNT;
+	if (port < 0 || port >= DE_PORT_NR)
+		panic("", "dp8390: illegal port", port);
+	dep= &de_table[port];
+	dep->de_client= mp->DL_PROC;
+*/
+	if (dep->de_mode == DEM_SINK)
+	{
+		assert(!from_int);
+//		dep->de_flags |= DEF_PACK_SEND;
+		reply(dep, OK, FALSE);
+//		return;
+		return EOK;
+	}
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags &DEF_ENABLED);
+	if(dep->packet_queue && (! from_int)){
+//	if (dep->de_flags &DEF_SEND_AVAIL){
+//		panic("", "dp8390: send already in progress", NO_NUM);
+		return queue_packet(dep, packet);
+	}
+
+	sendq_head= dep->de_sendq_head;
+//	if (dep->de_sendq[sendq_head].sq_filled)
+//	{
+//		if (from_int)
+//			panic("", "dp8390: should not be sending\n", NO_NUM);
+//		dep->de_sendmsg= *mp;
+//		dep->de_flags |= DEF_SEND_AVAIL;
+//		reply(dep, OK, FALSE);
+//		return;
+//		return queue_packet(dep, packet);
+//	}
+//	assert(!(dep->de_flags &DEF_PACK_SEND));
+
+/*	if (vectored)
+	{
+		get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+			(count > IOVEC_NR ? IOVEC_NR : count) *
+			sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
+		dep->de_write_iovec.iod_iovec_s = count;
+		dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
+		dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
+
+		dep->de_tmp_iovec = dep->de_write_iovec;
+		size = calc_iovec_size(&dep->de_tmp_iovec);
+	}
+	else
+	{ 
+		dep->de_write_iovec.iod_iovec[0].iov_addr =
+			(vir_bytes) mp->DL_ADDR;
+		dep->de_write_iovec.iod_iovec[0].iov_size =
+			mp->DL_COUNT;
+		dep->de_write_iovec.iod_iovec_s = 1;
+		dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
+		dep->de_write_iovec.iod_iovec_addr = 0;
+		size= mp->DL_COUNT;
+	}
+*/
+	size = packet_get_data_length(packet);
+	dep->de_write_iovec.iod_iovec[0].iov_addr = (vir_bytes) packet_get_data(packet);
+	dep->de_write_iovec.iod_iovec[0].iov_size = size;
+	dep->de_write_iovec.iod_iovec_s = 1;
+	dep->de_write_iovec.iod_iovec_addr = NULL;
+
+	if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
+	{
+		panic("", "dp8390: invalid packet size", size);
+		return EINVAL;
+	}
+	(dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
+		dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
+		size);
+	dep->de_sendq[sendq_head].sq_filled= TRUE;
+	if (dep->de_sendq_tail == sendq_head)
+	{
+		outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
+		outb_reg0(dep, DP_TBCR1, size >> 8);
+		outb_reg0(dep, DP_TBCR0, size &0xff);
+		outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
+	}
+	else
+		dep->de_sendq[sendq_head].sq_size= size;
+	
+	if (++sendq_head == dep->de_sendq_nr)
+		sendq_head= 0;
+	assert(sendq_head < SENDQ_NR);
+	dep->de_sendq_head= sendq_head;
+
+//	dep->de_flags |= DEF_PACK_SEND;
+
+	/* If the interrupt handler called, don't send a reply. The reply
+	 * will be sent after all interrupts are handled. 
+	 */
+	if (from_int)
+		return EOK;
+	reply(dep, OK, FALSE);
+
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags &DEF_ENABLED);
+	return EOK;
+}
+
+/*===========================================================================*
+ *				dp_init					     *
+ *===========================================================================*/
+void dp_init(dep)
+dpeth_t *dep;
+{
+	int dp_rcr_reg;
+	int i;//, r;
+
+	/* General initialization */
+	dep->de_flags = DEF_EMPTY;
+	(*dep->de_initf)(dep);
+
+//	dp_confaddr(dep);
+
+	if (debug)
+	{
+		printf("%s: Ethernet address ", dep->de_name);
+		for (i= 0; i < 6; i++)
+			printf("%x%c", dep->de_address.ea_addr[i],
+							i < 5 ? ':' : '\n');
+	}
+
+	/* Map buffer */
+	map_hw_buffer(dep);
+
+	/* Initialization of the dp8390 following the mandatory procedure
+	 * in reference manual ("DP8390D/NS32490D NIC Network Interface
+	 * Controller", National Semiconductor, July 1995, Page 29).
+	 */
+	/* Step 1: */
+	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
+	/* Step 2: */
+	if (dep->de_16bit)
+		outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
+	else
+		outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
+	/* Step 3: */
+	outb_reg0(dep, DP_RBCR0, 0);
+	outb_reg0(dep, DP_RBCR1, 0);
+	/* Step 4: */
+	dp_rcr_reg = 0;
+	if (dep->de_flags &DEF_PROMISC)
+		dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
+	if (dep->de_flags &DEF_BROAD)
+		dp_rcr_reg |= RCR_AB;
+	if (dep->de_flags &DEF_MULTI)
+		dp_rcr_reg |= RCR_AM;
+	outb_reg0(dep, DP_RCR, dp_rcr_reg);
+	/* Step 5: */
+	outb_reg0(dep, DP_TCR, TCR_INTERNAL);
+	/* Step 6: */
+	outb_reg0(dep, DP_BNRY, dep->de_startpage);
+	outb_reg0(dep, DP_PSTART, dep->de_startpage);
+	outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
+	/* Step 7: */
+	outb_reg0(dep, DP_ISR, 0xFF);
+	/* Step 8: */
+	outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
+		IMR_OVWE | IMR_CNTE);
+	/* Step 9: */
+	outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
+
+	outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
+	outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
+	outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
+	outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
+	outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
+	outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
+
+	outb_reg1(dep, DP_MAR0, 0xff);
+	outb_reg1(dep, DP_MAR1, 0xff);
+	outb_reg1(dep, DP_MAR2, 0xff);
+	outb_reg1(dep, DP_MAR3, 0xff);
+	outb_reg1(dep, DP_MAR4, 0xff);
+	outb_reg1(dep, DP_MAR5, 0xff);
+	outb_reg1(dep, DP_MAR6, 0xff);
+	outb_reg1(dep, DP_MAR7, 0xff);
+
+	outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
+	/* Step 10: */
+	outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
+	/* Step 11: */
+	outb_reg0(dep, DP_TCR, TCR_NORMAL);
+
+	inb_reg0(dep, DP_CNTR0);		/* reset counters by reading */
+	inb_reg0(dep, DP_CNTR1);
+	inb_reg0(dep, DP_CNTR2);
+
+	/* Finish the initialization. */
+	dep->de_flags |= DEF_ENABLED;
+	for (i= 0; i<dep->de_sendq_nr; i++)
+		dep->de_sendq[i].sq_filled= 0;
+	dep->de_sendq_head= 0;
+	dep->de_sendq_tail= 0;
+	if (!dep->de_prog_IO)
+	{
+		dep->de_user2nicf= dp_user2nic;
+//		dep->de_user2nicf_s= dp_user2nic_s;
+		dep->de_nic2userf= dp_nic2user;
+//		dep->de_nic2userf_s= dp_nic2user_s;
+		dep->de_getblockf= dp_getblock;
+	}
+	else if (dep->de_16bit)
+	{
+		dep->de_user2nicf= dp_pio16_user2nic;
+//		dep->de_user2nicf_s= dp_pio16_user2nic_s;
+		dep->de_nic2userf= dp_pio16_nic2user;
+//		dep->de_nic2userf_s= dp_pio16_nic2user_s;
+		dep->de_getblockf= dp_pio16_getblock;
+	}
+	else
+	{
+		dep->de_user2nicf= dp_pio8_user2nic;
+//		dep->de_user2nicf_s= dp_pio8_user2nic_s;
+		dep->de_nic2userf= dp_pio8_nic2user;
+//		dep->de_nic2userf_s= dp_pio8_nic2user_s;
+		dep->de_getblockf= dp_pio8_getblock;
+	}
+
+	/* Set the interrupt handler and policy. Do not automatically 
+	 * reenable interrupts. Return the IRQ line number on interrupts.
+ 	 */
+/* 	dep->de_hook = dep->de_irq;
+	r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
+	if (r != OK)
+		panic("DP8390", "sys_irqsetpolicy failed", r);
+
+	r= sys_irqenable(&dep->de_hook);
+	if (r != OK)
+	{
+		panic("DP8390", "unable enable interrupts", r);
+	}
+*/
+}
+
+/*===========================================================================*
+ *				dp_reinit				     *
+ *===========================================================================*/
+static void dp_reinit(dep)
+dpeth_t *dep;
+{
+	int dp_rcr_reg;
+
+	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
+
+	dp_rcr_reg = 0;
+	if (dep->de_flags &DEF_PROMISC)
+		dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
+	if (dep->de_flags &DEF_BROAD)
+		dp_rcr_reg |= RCR_AB;
+	if (dep->de_flags &DEF_MULTI)
+		dp_rcr_reg |= RCR_AM;
+	outb_reg0(dep, DP_RCR, dp_rcr_reg);
+}
+
+/*===========================================================================*
+ *				dp_reset				     *
+ *===========================================================================*/
+static void dp_reset(dep)
+dpeth_t *dep;
+{
+	int i;
+
+	/* Stop chip */
+	outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+	outb_reg0(dep, DP_RBCR0, 0);
+	outb_reg0(dep, DP_RBCR1, 0);
+	for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RST) == 0); i++)
+		; /* Do nothing */
+	outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
+	outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
+	outb_reg0(dep, DP_TCR, TCR_NORMAL);
+
+	/* Acknowledge the ISR_RDC (remote dma) interrupt. */
+	for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RDC) == 0); i++)
+		; /* Do nothing */
+	outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) &~ISR_RDC);
+
+	/* Reset the transmit ring. If we were transmitting a packet, we
+	 * pretend that the packet is processed. Higher layers will
+	 * retransmit if the packet wasn't actually sent.
+	 */
+	dep->de_sendq_head= dep->de_sendq_tail= 0;
+	for (i= 0; i<dep->de_sendq_nr; i++)
+		dep->de_sendq[i].sq_filled= 0;
+	dp_send(dep);
+	dep->de_flags &= ~DEF_STOPPED;
+}
+
+/*===========================================================================*
+ *				dp_check_ints				     *
+ *===========================================================================*/
+void dp_check_ints(dep, isr)
+dpeth_t *dep;
+int isr;
+{
+	int /*isr,*/ tsr;
+	int size, sendq_tail;
+
+	if (!(dep->de_flags &DEF_ENABLED))
+		panic("", "dp8390: got premature interrupt", NO_NUM);
+
+	for(;;)
+	{
+//		isr = inb_reg0(dep, DP_ISR);
+		if (!isr)
+			break;
+		outb_reg0(dep, DP_ISR, isr);
+		if (isr &(ISR_PTX|ISR_TXE))
+		{
+			if (isr &ISR_TXE)
+			{
+#if DEBUG
+ {printf("%s: got send Error\n", dep->de_name);}
+#endif
+				dep->de_stat.ets_sendErr++;
+			}
+			else
+			{
+				tsr = inb_reg0(dep, DP_TSR);
+
+				if (tsr &TSR_PTX) dep->de_stat.ets_packetT++;
+#if 0	/* Reserved in later manuals, should be ignored */
+				if (!(tsr &TSR_DFR))
+				{
+					/* In most (all?) implementations of
+					 * the dp8390, this bit is set
+					 * when the packet is not deferred
+					 */
+					dep->de_stat.ets_transDef++;
+				}
+#endif
+				if (tsr &TSR_COL) dep->de_stat.ets_collision++;
+				if (tsr &TSR_ABT) dep->de_stat.ets_transAb++;
+				if (tsr &TSR_CRS) dep->de_stat.ets_carrSense++;
+				if (tsr &TSR_FU
+					&& ++dep->de_stat.ets_fifoUnder <= 10)
+				{
+					printf("%s: fifo underrun\n",
+						dep->de_name);
+				}
+				if (tsr &TSR_CDH
+					&& ++dep->de_stat.ets_CDheartbeat <= 10)
+				{
+					printf("%s: CD heart beat failure\n",
+						dep->de_name);
+				}
+				if (tsr &TSR_OWC) dep->de_stat.ets_OWC++;
+			}
+			sendq_tail= dep->de_sendq_tail;
+
+			if (!(dep->de_sendq[sendq_tail].sq_filled))
+			{
+				/* Software bug? */
+				assert(!debug);
+
+				/* Or hardware bug? */
+				printf(
+				"%s: transmit interrupt, but not sending\n",
+					dep->de_name);
+				continue;
+			}
+			dep->de_sendq[sendq_tail].sq_filled= 0;
+			if (++sendq_tail == dep->de_sendq_nr)
+				sendq_tail= 0;
+			dep->de_sendq_tail= sendq_tail;
+			if (dep->de_sendq[sendq_tail].sq_filled)
+			{
+				size= dep->de_sendq[sendq_tail].sq_size;
+				outb_reg0(dep, DP_TPSR,
+					dep->de_sendq[sendq_tail].sq_sendpage);
+				outb_reg0(dep, DP_TBCR1, size >> 8);
+				outb_reg0(dep, DP_TBCR0, size &0xff);
+				outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
+			}
+//			if (dep->de_flags &DEF_SEND_AVAIL)
+				dp_send(dep);
+		}
+
+		if (isr &ISR_PRX)
+		{
+			/* Only call dp_recv if there is a read request */
+//			if (dep->de_flags) &DEF_READING)
+				dp_recv(dep);
+		}
+		
+		if (isr &ISR_RXE) dep->de_stat.ets_recvErr++;
+		if (isr &ISR_CNT)
+		{
+			dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
+			dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
+			dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
+		}
+		if (isr &ISR_OVW)
+		{
+			dep->de_stat.ets_OVW++;
+#if 0
+			{printW(); printf(
+				"%s: got overwrite warning\n", dep->de_name);}
+#endif
+/*			if (dep->de_flags &DEF_READING)
+			{
+				printf(
+"dp_check_ints: strange: overwrite warning and pending read request\n");
+				dp_recv(dep);
+			}
+*/		}
+		if (isr &ISR_RDC)
+		{
+			/* Nothing to do */
+		}
+		if (isr &ISR_RST)
+		{
+			/* this means we got an interrupt but the ethernet 
+			 * chip is shutdown. We set the flag DEF_STOPPED,
+			 * and continue processing arrived packets. When the
+			 * receive buffer is empty, we reset the dp8390.
+			 */
+#if 0
+			 {printW(); printf(
+				"%s: NIC stopped\n", dep->de_name);}
+#endif
+			dep->de_flags |= DEF_STOPPED;
+			break;
+		}
+		isr = inb_reg0(dep, DP_ISR);
+	}
+//	if ((dep->de_flags &(DEF_READING|DEF_STOPPED)) == 
+//						(DEF_READING|DEF_STOPPED))
+	if ((dep->de_flags &DEF_STOPPED) == DEF_STOPPED)
+	{
+		/* The chip is stopped, and all arrived packets are 
+		 * delivered.
+		 */
+		dp_reset(dep);
+	}
+}
+
+/*===========================================================================*
+ *				dp_recv					     *
+ *===========================================================================*/
+static void dp_recv(dep)
+dpeth_t *dep;
+{
+	dp_rcvhdr_t header;
+	//unsigned pageno, curr, next;
+	int pageno, curr, next;
+	vir_bytes length;
+	int packet_processed, r;
+	u16_t eth_type;
+
+	packet_processed = FALSE;
+	pageno = inb_reg0(dep, DP_BNRY) + 1;
+	if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
+
+	do
+	{
+		outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
+		curr = inb_reg1(dep, DP_CURR);
+		outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
+
+		if (curr == pageno) break;
+
+		(dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
+			&header);
+		(dep->de_getblockf)(dep, pageno, sizeof(header) +
+			2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
+
+		length = (header.dr_rbcl | (header.dr_rbch << 8)) -
+			sizeof(dp_rcvhdr_t);
+		next = header.dr_next;
+		if (length < ETH_MIN_PACK_SIZE ||
+			length > ETH_MAX_PACK_SIZE_TAGGED)
+		{
+			printf("%s: packet with strange length arrived: %d\n",
+				dep->de_name, (int) length);
+			next= curr;
+		}
+		else if (next < dep->de_startpage || next >= dep->de_stoppage)
+		{
+			printf("%s: strange next page\n", dep->de_name);
+			next= curr;
+		}
+/*		else if (eth_type == eth_ign_proto)
+		{
+*/			/* Hack: ignore packets of a given protocol, useful
+			 * if you share a net with 80 computers sending
+			 * Amoeba FLIP broadcasts.  (Protocol 0x8146.)
+			 */
+/*			static int first= 1;
+			if (first)
+			{
+				first= 0;
+				printf("%s: dropping proto 0x%04x packets\n",
+					dep->de_name,
+					ntohs(eth_ign_proto));
+			}
+			dep->de_stat.ets_packetR++;
+		}
+*/		else if (header.dr_status &RSR_FO)
+		{
+			/* This is very serious, so we issue a warning and
+			 * reset the buffers */
+			printf("%s: fifo overrun, resetting receive buffer\n",
+				dep->de_name);
+			dep->de_stat.ets_fifoOver++;
+			next = curr;
+		}
+		else if ((header.dr_status &RSR_PRX) && 
+					   (dep->de_flags &DEF_ENABLED))
+		{
+//			if (dep->de_safecopy_read)
+//				r = dp_pkt2user_s(dep, pageno, length);
+//			else
+				r = dp_pkt2user(dep, pageno, length);
+			if (r != OK)
+				return;
+
+			packet_processed = TRUE;
+			dep->de_stat.ets_packetR++;
+		}
+		if (next == dep->de_startpage)
+			outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
+		else
+			outb_reg0(dep, DP_BNRY, next - 1);
+
+		pageno = next;
+	}
+	while (!packet_processed);
+}
+
+/*===========================================================================*
+ *				dp_send					     *
+ *===========================================================================*/
+static void dp_send(dep)
+dpeth_t *dep;
+{
+	packet_t packet;
+
+//	if (!(dep->de_flags &DEF_SEND_AVAIL))
+//		return;
+
+	if(dep->packet_queue){
+		packet = dep->packet_queue;
+		dep->packet_queue = pq_detach(packet);
+		do_pwrite(dep, packet, TRUE);
+		netif_pq_release(packet_get_id(packet));
+		-- dep->packet_count;
+	}
+//	if(! dep->packet_queue){
+//		dep->de_flags &= ~DEF_SEND_AVAIL;
+//	}
+/*	switch(dep->de_sendmsg.m_type)
+	{
+	case DL_WRITE:	do_vwrite(&dep->de_sendmsg, TRUE, FALSE);	break;
+	case DL_WRITEV:	do_vwrite(&dep->de_sendmsg, TRUE, TRUE);	break;
+	case DL_WRITEV_S: do_vwrite_s(&dep->de_sendmsg, TRUE);	break;
+	default:
+		panic("", "dp8390: wrong type", dep->de_sendmsg.m_type);
+		break;
+	}
+*/
+}
+
+/*===========================================================================*
+ *				dp_getblock				     *
+ *===========================================================================*/
+static void dp_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+//	int r;
+
+	offset = page * DP_PAGESIZE + offset;
+
+	memcpy(dst, dep->de_locmem + offset, size);
+}
+
+/*===========================================================================*
+ *				dp_pio8_getblock			     *
+ *===========================================================================*/
+static void dp_pio8_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+	offset = page * DP_PAGESIZE + offset;
+	outb_reg0(dep, DP_RBCR0, size &0xFF);
+	outb_reg0(dep, DP_RBCR1, size >> 8);
+	outb_reg0(dep, DP_RSAR0, offset &0xFF);
+	outb_reg0(dep, DP_RSAR1, offset >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	insb(dep->de_data_port, dst, size);
+}
+
+/*===========================================================================*
+ *				dp_pio16_getblock			     *
+ *===========================================================================*/
+static void dp_pio16_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+	offset = page * DP_PAGESIZE + offset;
+	outb_reg0(dep, DP_RBCR0, size &0xFF);
+	outb_reg0(dep, DP_RBCR1, size >> 8);
+	outb_reg0(dep, DP_RSAR0, offset &0xFF);
+	outb_reg0(dep, DP_RSAR1, offset >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	assert (!(size &1));
+	insw(dep->de_data_port, dst, size);
+}
+
+/*===========================================================================*
+ *				dp_pkt2user				     *
+ *===========================================================================*/
+static int dp_pkt2user(dep, page, length)
+dpeth_t *dep;
+int page, length;
+{
+	int last, count;
+	packet_t packet;
+
+//	if (!(dep->de_flags &DEF_READING))
+//		return EGENERIC;
+
+	packet = netif_packet_get_1(length);
+	if(! packet){
+		return ENOMEM;
+	}
+	dep->de_read_iovec.iod_iovec[0].iov_addr = (vir_bytes) packet_suffix(packet, length);
+	dep->de_read_iovec.iod_iovec[0].iov_size = length;
+	dep->de_read_iovec.iod_iovec_s = 1;
+	dep->de_read_iovec.iod_iovec_addr = NULL;
+
+	last = page + (length - 1) / DP_PAGESIZE;
+	if (last >= dep->de_stoppage)
+	{
+		count = (dep->de_stoppage - page) * DP_PAGESIZE -
+			sizeof(dp_rcvhdr_t);
+
+		/* Save read_iovec since we need it twice. */
+		dep->de_tmp_iovec = dep->de_read_iovec;
+		(dep->de_nic2userf)(dep, page * DP_PAGESIZE +
+			sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
+		(dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE, 
+			&dep->de_read_iovec, count, length - count);
+	}
+	else
+	{
+		(dep->de_nic2userf)(dep, page * DP_PAGESIZE +
+			sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
+	}
+
+	dep->de_read_s = length;
+	dep->de_flags |= DEF_PACK_RECV;
+//	dep->de_flags &= ~DEF_READING;
+
+	if(dep->received_count >= MAX_PACKETS){
+		netif_pq_release(packet_get_id(packet));
+		return ELIMIT;
+	}else{
+		if(pq_add(&dep->received_queue, packet, 0, 0) == EOK){
+			++ dep->received_count;
+		}else{
+			netif_pq_release(packet_get_id(packet));
+		}
+	}
+	return OK;
+}
+
+/*===========================================================================*
+ *				dp_user2nic				     *
+ *===========================================================================*/
+static void dp_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+	vir_bytes vir_hw;//, vir_user;
+	//int bytes, i, r;
+	int i, r;
+	vir_bytes bytes;
+
+	vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		r= sys_vircopy(iovp->iod_proc_nr, D,
+			iovp->iod_iovec[i].iov_addr + offset,
+			SELF, D, vir_hw, bytes);
+		if (r != OK)
+			panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
+
+		count -= bytes;
+		vir_hw += bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_pio8_user2nic			     *
+ *===========================================================================*/
+static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+//	phys_bytes phys_user;
+	int i;
+	vir_bytes bytes;
+
+	outb_reg0(dep, DP_ISR, ISR_RDC);
+
+	outb_reg0(dep, DP_RBCR0, count &0xFF);
+	outb_reg0(dep, DP_RBCR1, count >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
+			iovp->iod_iovec[i].iov_addr + offset, bytes);
+		count -= bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+
+	for (i= 0; i<100; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) &ISR_RDC)
+			break;
+	}
+	if (i == 100)
+	{
+		panic("", "dp8390: remote dma failed to complete", NO_NUM);
+	}
+}
+
+/*===========================================================================*
+ *				dp_pio16_user2nic			     *
+ *===========================================================================*/
+static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+	vir_bytes vir_user;
+	vir_bytes ecount;
+	int i, r, user_proc;
+	vir_bytes bytes;
+	//u8_t two_bytes[2];
+	u16_t two_bytes;
+	int odd_byte;
+
+	ecount= (count+1) &~1;
+	odd_byte= 0;
+
+	outb_reg0(dep, DP_ISR, ISR_RDC);
+	outb_reg0(dep, DP_RBCR0, ecount &0xFF);
+	outb_reg0(dep, DP_RBCR1, ecount >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		user_proc= iovp->iod_proc_nr;
+		vir_user= iovp->iod_iovec[i].iov_addr + offset;
+		if (odd_byte)
+		{
+			r= sys_vircopy(user_proc, D, vir_user, 
+			//	SELF, D, (vir_bytes)&two_bytes[1], 1);
+				SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[1]), 1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_user2nic: sys_vircopy failed",
+					r);
+			}
+			//outw(dep->de_data_port, *(u16_t *)two_bytes);
+			outw(dep->de_data_port, two_bytes);
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 0;
+			if (!bytes)
+				continue;
+		}
+		ecount= bytes &~1;
+		if (ecount != 0)
+		{
+			do_vir_outsw(dep->de_data_port, user_proc, vir_user,
+				ecount);
+			count -= ecount;
+			offset += ecount;
+			bytes -= ecount;
+			vir_user += ecount;
+		}
+		if (bytes)
+		{
+			assert(bytes == 1);
+			r= sys_vircopy(user_proc, D, vir_user, 
+			//	SELF, D, (vir_bytes)&two_bytes[0], 1);
+				SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[0]), 1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_user2nic: sys_vircopy failed",
+					r);
+			}
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 1;
+		}
+	}
+	assert(count == 0);
+
+	if (odd_byte)
+		//outw(dep->de_data_port, *(u16_t *)two_bytes);
+		outw(dep->de_data_port, two_bytes);
+
+	for (i= 0; i<100; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) &ISR_RDC)
+			break;
+	}
+	if (i == 100)
+	{
+		panic("", "dp8390: remote dma failed to complete", NO_NUM);
+	}
+}
+
+/*===========================================================================*
+ *				dp_nic2user				     *
+ *===========================================================================*/
+static void dp_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+	vir_bytes vir_hw;//, vir_user;
+	vir_bytes bytes;
+	int i, r;
+
+	vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		r= sys_vircopy(SELF, D, vir_hw,
+			iovp->iod_proc_nr, D,
+			iovp->iod_iovec[i].iov_addr + offset, bytes);
+		if (r != OK)
+			panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
+
+		count -= bytes;
+		vir_hw += bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_pio8_nic2user			     *
+ *===========================================================================*/
+static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+//	phys_bytes phys_user;
+	int i;
+	vir_bytes bytes;
+
+	outb_reg0(dep, DP_RBCR0, count &0xFF);
+	outb_reg0(dep, DP_RBCR1, count >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
+			iovp->iod_iovec[i].iov_addr + offset, bytes);
+		count -= bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_pio16_nic2user			     *
+ *===========================================================================*/
+static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+	vir_bytes vir_user;
+	vir_bytes ecount;
+	int i, r, user_proc;
+	vir_bytes bytes;
+	//u8_t two_bytes[2];
+	u16_t two_bytes;
+	int odd_byte;
+
+	ecount= (count+1) &~1;
+	odd_byte= 0;
+
+	outb_reg0(dep, DP_RBCR0, ecount &0xFF);
+	outb_reg0(dep, DP_RBCR1, ecount >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		user_proc= iovp->iod_proc_nr;
+		vir_user= iovp->iod_iovec[i].iov_addr + offset;
+		if (odd_byte)
+		{
+			//r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
+			r= sys_vircopy(SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[1]),
+				user_proc, D, vir_user,  1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_nic2user: sys_vircopy failed",
+					r);
+			}
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 0;
+			if (!bytes)
+				continue;
+		}
+		ecount= bytes &~1;
+		if (ecount != 0)
+		{
+			do_vir_insw(dep->de_data_port, user_proc, vir_user,
+				ecount);
+			count -= ecount;
+			offset += ecount;
+			bytes -= ecount;
+			vir_user += ecount;
+		}
+		if (bytes)
+		{
+			assert(bytes == 1);
+			//*(u16_t *)two_bytes= inw(dep->de_data_port);
+			two_bytes= inw(dep->de_data_port);
+			//r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
+			r= sys_vircopy(SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[0]),
+				user_proc, D, vir_user,  1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_nic2user: sys_vircopy failed",
+					r);
+			}
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 1;
+		}
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_next_iovec				     *
+ *===========================================================================*/
+static void dp_next_iovec(iovp)
+iovec_dat_t *iovp;
+{
+	assert(iovp->iod_iovec_s > IOVEC_NR);
+
+	iovp->iod_iovec_s -= IOVEC_NR;
+
+	iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
+
+	get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr, 
+		(iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
+		sizeof(iovec_t), iovp->iod_iovec); 
+}
+
+/*===========================================================================*
+ *				conf_hw					     *
+ *===========================================================================*/
+static void conf_hw(dep)
+dpeth_t *dep;
+{
+//	static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 	/* ,... */};
+
+//	int ifnr;
+//	dp_conf_t *dcp;
+
+//	dep->de_mode= DEM_DISABLED;	/* Superfluous */
+//	ifnr= dep-de_table;
+
+//	dcp= &dp_conf[ifnr];
+//	update_conf(dep, dcp);
+//	if (dep->de_mode != DEM_ENABLED)
+//		return;
+	if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
+	{
+		printf("%s: No ethernet card found at 0x%x\n", 
+			dep->de_name, dep->de_base_port);
+		dep->de_mode= DEM_DISABLED;
+		return;
+	}
+
+/* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
+
+	dep->de_mode = DEM_ENABLED;
+
+	dep->de_flags = DEF_EMPTY;
+//	dep->de_stat = empty_stat;
+}
+
+/*===========================================================================*
+ *				map_hw_buffer				     *
+ *===========================================================================*/
+static void map_hw_buffer(dep)
+dpeth_t *dep;
+{
+//	int r;
+//	size_t o, size;
+//	char *buf, *abuf;
+
+	if (dep->de_prog_IO)
+	{
+#if 0
+		if(debug){
+			printf(
+			"map_hw_buffer: programmed I/O, no need to map buffer\n");
+		}
+#endif
+		dep->de_locmem = (char *)-dep->de_ramsize; /* trap errors */
+		return;
+	}else{
+		printf("map_hw_buffer: no buffer!\n");
+	}
+
+//	size = dep->de_ramsize + PAGE_SIZE;	/* Add PAGE_SIZE for
+//						 * alignment
+//						 */
+//	buf= malloc(size);
+//	if (buf == NULL)
+//		panic(__FILE__, "map_hw_buffer: cannot malloc size", size);
+//	o= PAGE_SIZE - ((vir_bytes)buf % PAGE_SIZE);
+//	abuf= buf + o;
+//	printf("buf at 0x%x, abuf at 0x%x\n", buf, abuf);
+
+//	r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)abuf,
+//			dep->de_ramsize, (phys_bytes)dep->de_linmem);
+//	if (r != OK)
+//		panic(__FILE__, "map_hw_buffer: sys_vm_map failed", r);
+//	dep->de_locmem = abuf;
+}
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+static void reply(dep, err, may_block)
+dpeth_t *dep;
+int err;
+int may_block;
+{
+/*	message reply;
+	int status;
+	int r;
+
+	status = 0;
+	if (dep->de_flags &DEF_PACK_SEND)
+		status |= DL_PACK_SEND;
+	if (dep->de_flags &DEF_PACK_RECV)
+		status |= DL_PACK_RECV;
+
+	reply.m_type = DL_TASK_REPLY;
+	reply.DL_PORT = dep - de_table;
+	reply.DL_PROC = dep->de_client;
+	reply.DL_STAT = status | ((u32_t) err << 16);
+	reply.DL_COUNT = dep->de_read_s;
+	reply.DL_CLCK = 0;	*//* Don't know */
+/*	r= send(dep->de_client, &reply);
+
+	if (r == ELOCKED && may_block)
+	{
+#if 0
+		printf("send locked\n");
+#endif
+		return;
+	}
+
+	if (r < 0)
+		panic("", "dp8390: send failed:", r);
+	
+*/	dep->de_read_s = 0;
+//	dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
+}
+
+/*===========================================================================*
+ *				get_userdata				     *
+ *===========================================================================*/
+static void get_userdata(user_proc, user_addr, count, loc_addr)
+int user_proc;
+vir_bytes user_addr;
+vir_bytes count;
+void *loc_addr;
+{
+	int r;
+
+	r= sys_vircopy(user_proc, D, user_addr,
+		SELF, D, (vir_bytes)loc_addr, count);
+	if (r != OK)
+		panic("DP8390", "get_userdata: sys_vircopy failed", r);
+}
+
+static void insb(port_t port, void *buf, size_t size)
+{
+	size_t i;
+
+	for(i = 0; i < size; ++ i){
+		*((uint8_t *) buf + i) = inb(port);
+	}
+}
+
+static void insw(port_t port, void *buf, size_t size)
+{
+	size_t i;
+
+	for(i = 0; i * 2 < size; ++ i){
+		*((uint16_t *) buf + i) = inw(port);
+	}
+}
+
+static void outsb(port_t port, void *buf, size_t size)
+{
+	size_t i;
+
+	for(i = 0; i < size; ++ i){
+		outb(port, *((uint8_t *) buf + i));
+	}
+}
+
+static void outsw(port_t port, void *buf, size_t size)
+{
+	size_t i;
+
+	for(i = 0; i * 2 < size; ++ i){
+		outw(port, *((uint16_t *) buf + i));
+	}
+}
+
+/*
+ * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
+ */
+
+/** @}
+ */
Index: uspace/srv/hw/netif/dp8390/dp8390.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hw/netif/dp8390/dp8390.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system 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.
+ * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * * Any deviations from these conditions require written permission from the copyright holder in advance
+ *
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``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 COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS 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.
+ *
+ * Changes:
+ *  2009 ported to HelenOS, Lukas Mejdrech
+ */
+
+/** @addtogroup dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface definitions.
+ */
+
+#ifndef __NET_NETIF_DP8390_H__
+#define __NET_NETIF_DP8390_H__
+
+#include <packet/packet.h>
+
+#include "dp8390_port.h"
+#include "local.h"
+
+/** Input/output size.
+ */
+#define DP8390_IO_SIZE	0x01f
+
+/*
+dp8390.h
+
+Created:	before Dec 28, 1992 by Philip Homburg
+*/
+
+/* National Semiconductor DP8390 Network Interface Controller. */
+
+				/* Page 0, for reading ------------- */
+#define	DP_CR		0x0	/* Read side of Command Register     */
+#define	DP_CLDA0	0x1	/* Current Local Dma Address 0       */
+#define	DP_CLDA1	0x2	/* Current Local Dma Address 1       */
+#define	DP_BNRY		0x3	/* Boundary Pointer                  */
+#define	DP_TSR		0x4	/* Transmit Status Register          */
+#define	DP_NCR		0x5	/* Number of Collisions Register     */
+#define	DP_FIFO		0x6	/* Fifo ??                           */
+#define	DP_ISR		0x7	/* Interrupt Status Register         */
+#define	DP_CRDA0	0x8	/* Current Remote Dma Address 0      */
+#define	DP_CRDA1	0x9	/* Current Remote Dma Address 1      */
+#define	DP_DUM1		0xA	/* unused                            */
+#define	DP_DUM2		0xB	/* unused                            */
+#define	DP_RSR		0xC	/* Receive Status Register           */
+#define	DP_CNTR0	0xD	/* Tally Counter 0                   */
+#define	DP_CNTR1	0xE	/* Tally Counter 1                   */
+#define	DP_CNTR2	0xF	/* Tally Counter 2                   */
+
+				/* Page 0, for writing ------------- */
+#define	DP_CR		0x0	/* Write side of Command Register    */
+#define	DP_PSTART	0x1	/* Page Start Register               */
+#define	DP_PSTOP	0x2	/* Page Stop Register                */
+#define	DP_BNRY		0x3	/* Boundary Pointer                  */
+#define	DP_TPSR		0x4	/* Transmit Page Start Register      */
+#define	DP_TBCR0	0x5	/* Transmit Byte Count Register 0    */
+#define	DP_TBCR1	0x6	/* Transmit Byte Count Register 1    */
+#define	DP_ISR		0x7	/* Interrupt Status Register         */
+#define	DP_RSAR0	0x8	/* Remote Start Address Register 0   */
+#define	DP_RSAR1	0x9	/* Remote Start Address Register 1   */
+#define	DP_RBCR0	0xA	/* Remote Byte Count Register 0      */
+#define	DP_RBCR1	0xB	/* Remote Byte Count Register 1      */
+#define	DP_RCR		0xC	/* Receive Configuration Register    */
+#define	DP_TCR		0xD	/* Transmit Configuration Register   */
+#define	DP_DCR		0xE	/* Data Configuration Register       */
+#define	DP_IMR		0xF	/* Interrupt Mask Register           */
+
+				/* Page 1, read/write -------------- */
+#define	DP_CR		0x0	/* Command Register                  */
+#define	DP_PAR0		0x1	/* Physical Address Register 0       */
+#define	DP_PAR1		0x2	/* Physical Address Register 1       */
+#define	DP_PAR2		0x3	/* Physical Address Register 2       */
+#define	DP_PAR3		0x4	/* Physical Address Register 3       */
+#define	DP_PAR4		0x5	/* Physical Address Register 4       */
+#define	DP_PAR5		0x6	/* Physical Address Register 5       */
+#define	DP_CURR		0x7	/* Current Page Register             */
+#define	DP_MAR0		0x8	/* Multicast Address Register 0      */
+#define	DP_MAR1		0x9	/* Multicast Address Register 1      */
+#define	DP_MAR2		0xA	/* Multicast Address Register 2      */
+#define	DP_MAR3		0xB	/* Multicast Address Register 3      */
+#define	DP_MAR4		0xC	/* Multicast Address Register 4      */
+#define	DP_MAR5		0xD	/* Multicast Address Register 5      */
+#define	DP_MAR6		0xE	/* Multicast Address Register 6      */
+#define	DP_MAR7		0xF	/* Multicast Address Register 7      */
+
+/* Bits in dp_cr */
+#define CR_STP		0x01	/* Stop: software reset              */
+#define CR_STA		0x02	/* Start: activate NIC               */
+#define CR_TXP		0x04	/* Transmit Packet                   */
+#define CR_DMA		0x38	/* Mask for DMA control              */
+#define CR_DM_NOP	0x00	/* DMA: No Operation                 */
+#define CR_DM_RR	0x08	/* DMA: Remote Read                  */
+#define CR_DM_RW	0x10	/* DMA: Remote Write                 */
+#define CR_DM_SP	0x18	/* DMA: Send Packet                  */
+#define CR_DM_ABORT	0x20	/* DMA: Abort Remote DMA Operation   */
+#define CR_PS		0xC0	/* Mask for Page Select              */
+#define CR_PS_P0	0x00	/* Register Page 0                   */
+#define CR_PS_P1	0x40	/* Register Page 1                   */
+#define CR_PS_P2	0x80	/* Register Page 2                   */
+#define CR_PS_T1	0xC0	/* Test Mode Register Map            */
+
+/* Bits in dp_isr */
+#define ISR_PRX		0x01	/* Packet Received with no errors    */
+#define ISR_PTX		0x02	/* Packet Transmitted with no errors */
+#define ISR_RXE		0x04	/* Receive Error                     */
+#define ISR_TXE		0x08	/* Transmit Error                    */
+#define ISR_OVW		0x10	/* Overwrite Warning                 */
+#define ISR_CNT		0x20	/* Counter Overflow                  */
+#define ISR_RDC		0x40	/* Remote DMA Complete               */
+#define ISR_RST		0x80	/* Reset Status                      */
+
+/* Bits in dp_imr */
+#define IMR_PRXE	0x01	/* Packet Received iEnable           */
+#define IMR_PTXE	0x02	/* Packet Transmitted iEnable        */
+#define IMR_RXEE	0x04	/* Receive Error iEnable             */
+#define IMR_TXEE	0x08	/* Transmit Error iEnable            */
+#define IMR_OVWE	0x10	/* Overwrite Warning iEnable         */
+#define IMR_CNTE	0x20	/* Counter Overflow iEnable          */
+#define IMR_RDCE	0x40	/* DMA Complete iEnable              */
+
+/* Bits in dp_dcr */
+#define DCR_WTS		0x01	/* Word Transfer Select              */
+#define DCR_BYTEWIDE	0x00	/* WTS: byte wide transfers          */
+#define DCR_WORDWIDE	0x01	/* WTS: word wide transfers          */
+#define DCR_BOS		0x02	/* Byte Order Select                 */
+#define DCR_LTLENDIAN	0x00	/* BOS: Little Endian                */
+#define DCR_BIGENDIAN	0x02	/* BOS: Big Endian                   */
+#define DCR_LAS		0x04	/* Long Address Select               */
+#define DCR_BMS		0x08	/* Burst Mode Select
+				 * Called Loopback Select (LS) in 
+				 * later manuals. Should be set.     */
+#define DCR_AR		0x10	/* Autoinitialize Remote             */
+#define DCR_FTS		0x60	/* Fifo Threshold Select             */
+#define DCR_2BYTES	0x00	/* 2 bytes                           */
+#define DCR_4BYTES	0x40	/* 4 bytes                           */
+#define DCR_8BYTES	0x20	/* 8 bytes                           */
+#define DCR_12BYTES	0x60	/* 12 bytes                          */
+
+/* Bits in dp_tcr */
+#define TCR_CRC		0x01	/* Inhibit CRC                       */
+#define TCR_ELC		0x06	/* Encoded Loopback Control          */
+#define TCR_NORMAL	0x00	/* ELC: Normal Operation             */
+#define TCR_INTERNAL	0x02	/* ELC: Internal Loopback            */
+#define TCR_0EXTERNAL	0x04	/* ELC: External Loopback LPBK=0     */
+#define TCR_1EXTERNAL	0x06	/* ELC: External Loopback LPBK=1     */
+#define TCR_ATD		0x08	/* Auto Transmit Disable             */
+#define TCR_OFST	0x10	/* Collision Offset Enable (be nice) */
+
+/* Bits in dp_tsr */
+#define TSR_PTX		0x01	/* Packet Transmitted (without error)*/
+#define TSR_DFR		0x02	/* Transmit Deferred, reserved in
+				 * later manuals.		     */
+#define TSR_COL		0x04	/* Transmit Collided                 */
+#define TSR_ABT		0x08	/* Transmit Aborted                  */
+#define TSR_CRS		0x10	/* Carrier Sense Lost                */
+#define TSR_FU		0x20	/* FIFO Underrun                     */
+#define TSR_CDH		0x40	/* CD Heartbeat                      */
+#define TSR_OWC		0x80	/* Out of Window Collision           */
+
+/* Bits in tp_rcr */
+#define RCR_SEP		0x01	/* Save Errored Packets              */
+#define RCR_AR		0x02	/* Accept Runt Packets               */
+#define RCR_AB		0x04	/* Accept Broadcast                  */
+#define RCR_AM		0x08	/* Accept Multicast                  */
+#define RCR_PRO		0x10	/* Physical Promiscuous              */
+#define RCR_MON		0x20	/* Monitor Mode                      */
+
+/* Bits in dp_rsr */
+#define RSR_PRX		0x01	/* Packet Received Intact            */
+#define RSR_CRC		0x02	/* CRC Error                         */
+#define RSR_FAE		0x04	/* Frame Alignment Error             */
+#define RSR_FO		0x08	/* FIFO Overrun                      */
+#define RSR_MPA		0x10	/* Missed Packet                     */
+#define RSR_PHY		0x20	/* Multicast Address Match           */
+#define RSR_DIS		0x40	/* Receiver Disabled                 */
+#define RSR_DFR		0x80	/* In later manuals: Deferring       */
+
+/** Type definition of the receive header.
+ */
+typedef struct dp_rcvhdr
+{
+	/** Copy of rsr.
+	 */
+	u8_t dr_status;
+	/** Pointer to next packet.
+	 */
+	u8_t dr_next;
+	/** Receive Byte Count Low.
+	 */
+	u8_t dr_rbcl;
+	/** Receive Byte Count High.
+	 */
+	u8_t dr_rbch;
+} dp_rcvhdr_t;
+
+/** Page size.
+ */
+#define DP_PAGESIZE	256
+
+/* Some macros to simplify accessing the dp8390 */
+/** Reads 1 byte from the zero page register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @returns The read value.
+ */
+#define inb_reg0(dep, reg)		(inb(dep->de_dp8390_port+reg))
+
+/** Writes 1 byte zero page register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @param[in] data The value to be written.
+ */
+#define outb_reg0(dep, reg, data)	(outb(dep->de_dp8390_port+reg, data))
+
+/** Reads 1 byte from the first page register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @returns The read value.
+ */
+#define inb_reg1(dep, reg)		(inb(dep->de_dp8390_port+reg))
+
+/** Writes 1 byte first page register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @param[in] data The value to be written.
+ */
+#define outb_reg1(dep, reg, data)	(outb(dep->de_dp8390_port+reg, data))
+
+/* Software interface to the dp8390 driver */
+
+struct dpeth;
+struct iovec_dat;
+//struct iovec_dat_s;
+_PROTOTYPE(typedef void (*dp_initf_t), (struct dpeth *dep)		);
+_PROTOTYPE(typedef void (*dp_stopf_t), (struct dpeth *dep)		);
+_PROTOTYPE(typedef void (*dp_user2nicf_t), (struct dpeth *dep,
+			struct iovec_dat *iovp, vir_bytes offset,
+			int nic_addr, vir_bytes count) );
+//_PROTOTYPE(typedef void (*dp_user2nicf_s_t), (struct dpeth *dep,
+//			struct iovec_dat_s *iovp, vir_bytes offset,
+//			int nic_addr, vir_bytes count)			);
+_PROTOTYPE(typedef void (*dp_nic2userf_t), (struct dpeth *dep,
+			int nic_addr, struct iovec_dat *iovp,
+			vir_bytes offset, vir_bytes count) );
+//_PROTOTYPE(typedef void (*dp_nic2userf_s_t), (struct dpeth *dep,
+//			int nic_addr, struct iovec_dat_s *iovp,
+//			vir_bytes offset, vir_bytes count)		);
+//#if 0
+//_PROTOTYPE(typedef void (*dp_getheaderf_t), (struct dpeth *dep,
+//			int page, struct dp_rcvhdr *h, u16_t *eth_type)	);
+//#endif
+_PROTOTYPE(typedef void (*dp_getblock_t), (struct dpeth *dep,
+		int page, size_t offset, size_t size, void *dst)	);
+
+/* iovectors are handled IOVEC_NR entries at a time. */
+//#define IOVEC_NR	16
+// no vectors allowed
+#define IOVEC_NR	1
+
+/*
+typedef int irq_hook_t;
+*/
+typedef struct iovec_dat
+{
+  iovec_t iod_iovec[IOVEC_NR];
+  int iod_iovec_s;
+  // no direct process access
+  int iod_proc_nr;
+  vir_bytes iod_iovec_addr;
+} iovec_dat_t;
+/*
+typedef struct iovec_dat_s
+{
+  iovec_s_t iod_iovec[IOVEC_NR];
+  int iod_iovec_s;
+  int iod_proc_nr;
+  cp_grant_id_t iod_grant;
+  vir_bytes iod_iovec_offset;
+} iovec_dat_s_t;
+*/
+#define SENDQ_NR	1	/* Maximum size of the send queue */
+#define SENDQ_PAGES	6	/* 6 * DP_PAGESIZE >= 1514 bytes */
+
+/** Maximum number of waiting packets to be sent or received.
+ */
+#define MAX_PACKETS	4
+
+typedef struct dpeth
+{
+	/** Outgoing packets queue.
+	 */
+	packet_t packet_queue;
+	/** Outgoing packets count.
+	 */
+	int packet_count;
+
+	/** Received packets queue.
+	 */
+	packet_t received_queue;
+	/** Received packets count.
+	 */
+	int received_count;
+
+	/* The de_base_port field is the starting point of the probe.
+	 * The conf routine also fills de_linmem and de_irq. If the probe
+	 * routine knows the irq and/or memory address because they are
+	 * hardwired in the board, the probe should modify these fields.
+	 * Futhermore, the probe routine should also fill in de_initf and
+	 * de_stopf fields with the appropriate function pointers and set
+	 * de_prog_IO iff programmed I/O is to be used.
+	 */
+	port_t de_base_port;
+	phys_bytes de_linmem;
+	char *de_locmem;
+	int de_irq;
+	int de_int_pending;
+//	irq_hook_t de_hook;
+	dp_initf_t de_initf; 
+	dp_stopf_t de_stopf; 
+	int de_prog_IO;
+	char de_name[sizeof("dp8390#n")];
+
+	/* The initf function fills the following fields. Only cards that do
+	 * programmed I/O fill in the de_pata_port field.
+	 * In addition, the init routine has to fill in the sendq data
+	 * structures.
+	 */
+	ether_addr_t de_address;
+	port_t de_dp8390_port;
+	port_t de_data_port;
+	int de_16bit;
+	long de_ramsize;
+	int de_offset_page;
+	int de_startpage;
+	int de_stoppage;
+
+	/* should be here - read even for ne2k isa init... */
+	char de_pci;			/* TRUE iff PCI device */
+
+#if ENABLE_PCI
+	/* PCI config */
+//	char de_pci;			/* TRUE iff PCI device */
+//	u8_t de_pcibus;	
+//	u8_t de_pcidev;	
+//	u8_t de_pcifunc;	
+#endif
+
+	/* Do it yourself send queue */
+	struct sendq
+	{
+		int sq_filled;		/* this buffer contains a packet */
+		int sq_size;		/* with this size */
+		int sq_sendpage;	/* starting page of the buffer */
+	} de_sendq[SENDQ_NR];
+	int de_sendq_nr;
+	int de_sendq_head;		/* Enqueue at the head */
+	int de_sendq_tail;		/* Dequeue at the tail */
+
+	/* Fields for internal use by the dp8390 driver. */
+	int de_flags;
+	int de_mode;
+	eth_stat_t de_stat;
+	iovec_dat_t de_read_iovec;
+//	iovec_dat_s_t de_read_iovec_s;
+//	int de_safecopy_read;
+	iovec_dat_t de_write_iovec;
+//	iovec_dat_s_t de_write_iovec_s;
+	iovec_dat_t de_tmp_iovec;
+//	iovec_dat_s_t de_tmp_iovec_s;
+	vir_bytes de_read_s;
+//	int de_client;
+//	message de_sendmsg;
+	dp_user2nicf_t de_user2nicf; 
+//	dp_user2nicf_s_t de_user2nicf_s; 
+	dp_nic2userf_t de_nic2userf;
+//	dp_nic2userf_s_t de_nic2userf_s; 
+	dp_getblock_t de_getblockf;
+} dpeth_t;
+
+#define DEI_DEFAULT	0x8000
+
+#define DEF_EMPTY	0x000
+#define DEF_PACK_SEND	0x001
+#define DEF_PACK_RECV	0x002
+#define DEF_SEND_AVAIL	0x004
+#define DEF_READING	0x010
+#define DEF_PROMISC	0x040
+#define DEF_MULTI	0x080
+#define DEF_BROAD	0x100
+#define DEF_ENABLED	0x200
+#define DEF_STOPPED	0x400
+
+#define DEM_DISABLED	0x0
+#define DEM_SINK	0x1
+#define DEM_ENABLED	0x2
+
+//#if !__minix_vmd
+#define debug		1	/* Standard Minix lacks debug variable */
+//#endif
+
+/*
+ * $PchId: dp8390.h,v 1.10 2005/02/10 17:26:06 philip Exp $
+ */
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hw/netif/dp8390/dp8390_drv.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_drv.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hw/netif/dp8390/dp8390_drv.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface driver interface.
+ */
+
+#ifndef __NET_NETIF_DP8390_DRIVER_H__
+#define __NET_NETIF_DP8390_DRIVER_H__
+
+#include "dp8390.h"
+
+/** Initializes and/or starts the network interface.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] mode The state mode.
+ *  @returns EOK on success.
+ *  @returns EXDEV if the network interface is disabled.
+ */
+int do_init(dpeth_t *dep, int mode);
+
+/** Stops the network interface.
+ *  @param[in,out] dep The network interface structure.
+ */
+void do_stop(dpeth_t *dep);
+
+/** Processes the interrupt.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] isr The interrupt status register.
+ */
+void dp_check_ints(dpeth_t *dep, int isr);
+
+/** Probes and initializes the network interface.
+ *  @param[in,out] dep The network interface structure.
+ *  @returns EOK on success.
+ *  @returns EXDEV if the network interface was not recognized.
+ */
+int do_probe(dpeth_t * dep);
+
+/** Sends a packet.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] packet The packet t be sent.
+ *  @param[in] from_int The value indicating whether the sending is initialized from the interrupt handler.
+ *  @returns 
+ */
+int do_pwrite(dpeth_t * dep, packet_t packet, int from_int);
+
+/** Prints out network interface information.
+ *  @param[in] dep The network interface structure.
+ */
+void dp8390_dump(dpeth_t * dep);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hw/netif/dp8390/dp8390_module.c
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hw/netif/dp8390/dp8390_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface implementation.
+ */
+
+#include <assert.h>
+#include <async.h>
+#include <ddi.h>
+#include <errno.h>
+#include <malloc.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_messages.h>
+#include <net_modules.h>
+#include <packet/packet_client.h>
+#include <adt/measured_strings.h>
+#include <net_device.h>
+#include <nil_interface.h>
+#include <netif_interface.h>
+#include <netif_local.h>
+
+#include "dp8390.h"
+#include "dp8390_drv.h"
+#include "dp8390_port.h"
+
+/** DP8390 module name.
+ */
+#define NAME  "dp8390"
+
+/** Returns the device from the interrupt call.
+ *  @param[in] call The interrupt call.
+ */
+#define IRQ_GET_DEVICE(call)			(device_id_t) IPC_GET_METHOD(*call)
+
+/** Returns the interrupt status register from the interrupt call.
+ *  @param[in] call The interrupt call.
+ */
+#define IPC_GET_ISR(call)				(int) IPC_GET_ARG2(*call)
+
+/** DP8390 kernel interrupt command sequence.
+ */
+static irq_cmd_t	dp8390_cmds[] = {
+	{	.cmd = CMD_PIO_READ_8,
+		.addr = NULL,
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 1,
+		.srcarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+/** DP8390 kernel interrupt code.
+ */
+static irq_code_t	dp8390_code = {
+	sizeof(dp8390_cmds) / sizeof(irq_cmd_t),
+	dp8390_cmds
+};
+
+/** Handles the interrupt messages.
+ *  This is the interrupt handler callback function.
+ *  @param[in] iid The interrupt message identifier.
+ *  @param[in] call The interrupt message.
+ */
+static void irq_handler(ipc_callid_t iid, ipc_call_t * call)
+{
+	netif_device_t * device;
+	dpeth_t * dep;
+	packet_t received;
+	device_id_t device_id;
+	int phone;
+
+	device_id = IRQ_GET_DEVICE(call);
+	fibril_rwlock_write_lock(&netif_globals.lock);
+	if(find_device(device_id, &device) != EOK){
+		fibril_rwlock_write_unlock(&netif_globals.lock);
+		return;
+	}
+	dep = (dpeth_t *) device->specific;
+	if (dep->de_mode != DEM_ENABLED){
+		fibril_rwlock_write_unlock(&netif_globals.lock);
+		return;
+	}
+	assert(dep->de_flags &DEF_ENABLED);
+	dep->de_int_pending = 0;
+	dp_check_ints(dep, IPC_GET_ISR(call));
+	if(dep->received_queue){
+		received = dep->received_queue;
+		phone = device->nil_phone;
+		dep->received_queue = NULL;
+		dep->received_count = 0;
+		fibril_rwlock_write_unlock(&netif_globals.lock);
+		nil_received_msg(phone, device_id, received, NULL);
+	}else{
+		fibril_rwlock_write_unlock(&netif_globals.lock);
+	}
+	ipc_answer_0(iid, EOK);
+}
+
+/** Changes the network interface state.
+ *  @param[in,out] device The network interface.
+ *  @param[in] state The new state.
+ *  @returns The new state.
+ */
+static int change_state(netif_device_t * device, device_state_t state)
+{
+	if (device->state != state) {
+		device->state = state;
+		
+		printf("%s: State changed to %s\n", NAME,
+		    (state == NETIF_ACTIVE) ? "active" : "stopped");
+		
+		return state;
+	}
+	
+	return EOK;
+}
+
+int netif_specific_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	return ENOTSUP;
+}
+
+int netif_get_device_stats(device_id_t device_id, device_stats_ref stats){
+	ERROR_DECLARE;
+
+	netif_device_t * device;
+	eth_stat_t * de_stat;
+
+	if(! stats){
+		return EBADMEM;
+	}
+	ERROR_PROPAGATE(find_device(device_id, &device));
+	de_stat = &((dpeth_t *) device->specific)->de_stat;
+	null_device_stats(stats);
+	stats->receive_errors = de_stat->ets_recvErr;
+	stats->send_errors = de_stat->ets_sendErr;
+	stats->receive_crc_errors = de_stat->ets_CRCerr;
+	stats->receive_frame_errors = de_stat->ets_frameAll;
+	stats->receive_missed_errors = de_stat->ets_missedP;
+	stats->receive_packets = de_stat->ets_packetR;
+	stats->send_packets = de_stat->ets_packetT;
+	stats->collisions = de_stat->ets_collision;
+	stats->send_aborted_errors = de_stat->ets_transAb;
+	stats->send_carrier_errors = de_stat->ets_carrSense;
+	stats->send_heartbeat_errors = de_stat->ets_CDheartbeat;
+	stats->send_window_errors = de_stat->ets_OWC;
+	return EOK;
+}
+
+int netif_get_addr_message(device_id_t device_id, measured_string_ref address){
+	ERROR_DECLARE;
+
+	netif_device_t * device;
+
+	if(! address){
+		return EBADMEM;
+	}
+	ERROR_PROPAGATE(find_device(device_id, &device));
+	address->value = (char *) (&((dpeth_t *) device->specific)->de_address);
+	address->length = CONVERT_SIZE(ether_addr_t, char, 1);
+	return EOK;
+}
+
+
+
+int netif_probe_message(device_id_t device_id, int irq, uintptr_t io){
+	ERROR_DECLARE;
+
+	netif_device_t * device;
+	dpeth_t * dep;
+
+	device = (netif_device_t *) malloc(sizeof(netif_device_t));
+	if(! device){
+		return ENOMEM;
+	}
+	dep = (dpeth_t *) malloc(sizeof(dpeth_t));
+	if(! dep){
+		free(device);
+		return ENOMEM;
+	}
+	bzero(device, sizeof(netif_device_t));
+	bzero(dep, sizeof(dpeth_t));
+	device->device_id = device_id;
+	device->nil_phone = -1;
+	device->specific = (void *) dep;
+	device->state = NETIF_STOPPED;
+	dep->de_irq = irq;
+	dep->de_mode = DEM_DISABLED;
+	//TODO address?
+	if(ERROR_OCCURRED(pio_enable((void *) io, DP8390_IO_SIZE, (void **) &dep->de_base_port))
+		|| ERROR_OCCURRED(do_probe(dep))){
+		free(dep);
+		free(device);
+		return ERROR_CODE;
+	}
+	if(ERROR_OCCURRED(netif_device_map_add(&netif_globals.device_map, device->device_id, device))){
+		free(dep);
+		free(device);
+		return ERROR_CODE;
+	}
+	return EOK;
+}
+
+int netif_send_message(device_id_t device_id, packet_t packet, services_t sender){
+	ERROR_DECLARE;
+
+	netif_device_t * device;
+	dpeth_t * dep;
+	packet_t next;
+
+	ERROR_PROPAGATE(find_device(device_id, &device));
+	if(device->state != NETIF_ACTIVE){
+		netif_pq_release(packet_get_id(packet));
+		return EFORWARD;
+	}
+	dep = (dpeth_t *) device->specific;
+	// process packet queue
+	do{
+		next = pq_detach(packet);
+		if(do_pwrite(dep, packet, FALSE) != EBUSY){
+			netif_pq_release(packet_get_id(packet));
+		}
+		packet = next;
+	}while(packet);
+	return EOK;
+}
+
+int netif_start_message(netif_device_t * device){
+	ERROR_DECLARE;
+
+	dpeth_t * dep;
+
+	if(device->state != NETIF_ACTIVE){
+		dep = (dpeth_t *) device->specific;
+		dp8390_cmds[0].addr = (void *) (uintptr_t) (dep->de_dp8390_port + DP_ISR);
+		dp8390_cmds[2].addr = dp8390_cmds[0].addr;
+		ERROR_PROPAGATE(ipc_register_irq(dep->de_irq, device->device_id, device->device_id, &dp8390_code));
+		if(ERROR_OCCURRED(do_init(dep, DL_BROAD_REQ))){
+			ipc_unregister_irq(dep->de_irq, device->device_id);
+			return ERROR_CODE;
+		}
+		return change_state(device, NETIF_ACTIVE);
+	}
+	return EOK;
+}
+
+int netif_stop_message(netif_device_t * device){
+	dpeth_t * dep;
+
+	if(device->state != NETIF_STOPPED){
+		dep = (dpeth_t *) device->specific;
+		do_stop(dep);
+		ipc_unregister_irq(dep->de_irq, device->device_id);
+		return change_state(device, NETIF_STOPPED);
+	}
+	return EOK;
+}
+
+int netif_initialize(void){
+	ipcarg_t phonehash;
+
+	async_set_interrupt_received(irq_handler);
+
+	return REGISTER_ME(SERVICE_DP8390, &phonehash);
+}
+
+/** Default thread for new connections.
+ *
+ *  @param[in] iid The initial message identifier.
+ *  @param[in] icall The initial message call structure.
+ *
+ */
+static void netif_client_connection(ipc_callid_t iid, ipc_call_t * icall)
+{
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0(iid, EOK);
+	
+	while(true) {
+		ipc_call_t answer;
+		int answer_count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &answer_count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = netif_module_message(NAME, callid, &call, &answer,
+		    &answer_count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, answer_count);
+	}
+}
+
+/** Starts the module.
+ *
+ *  @param argc The count of the command line arguments. Ignored parameter.
+ *  @param argv The command line parameters. Ignored parameter.
+ *
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module start function.
+ *
+ */
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	/* Start the module */
+	if (ERROR_OCCURRED(netif_module_start(netif_client_connection)))
+		return ERROR_CODE;
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/hw/netif/dp8390/dp8390_port.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_port.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hw/netif/dp8390/dp8390_port.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface types and structures ports.
+ */
+
+#ifndef __NET_NETIF_DP8390_PORT_H__
+#define __NET_NETIF_DP8390_PORT_H__
+
+#include <errno.h>
+#include <mem.h>
+#include <stdio.h>
+#include <libarch/ddi.h>
+#include <sys/types.h>
+
+/** Macro for difining functions.
+ *  @param[in] function The function type and name definition.
+ *  @param[in] params The function parameters definition.
+ */
+#define _PROTOTYPE(function, params) function params
+
+/** Success error code.
+ */
+#define OK	EOK
+
+/** Type definition of the unsigned byte.
+ */
+typedef uint8_t u8_t;
+
+/** Type definition of the unsigned short.
+ */
+typedef uint16_t u16_t;
+
+/** Compares two memory blocks.
+ *  @param[in] first The first memory block.
+ *  @param[in] second The second memory block.
+ *  @param[in] size The blocks size in bytes.
+ *  @returns 0 if equeal.
+ *  @returns -1 if the first is greater than the second.
+ *  @returns 1 if the second is greater than the first.
+ */
+#define memcmp(first, second, size)	bcmp((char *) (first), (char *) (second), (size))
+
+/** Reads 1 byte.
+ *  @param[in] port The address to be read.
+ *  @returns The read value.
+ */
+#define inb(port)	pio_read_8((ioport8_t *) (port))
+
+/** Reads 1 word (2 bytes).
+ *  @param[in] port The address to be read.
+ *  @returns The read value.
+ */
+#define inw(port)	pio_read_16((ioport16_t *) (port))
+
+/** Writes 1 byte.
+ *  @param[in] port The address to be written.
+ *  @param[in] value The value to be written.
+ */
+#define outb(port, value)	pio_write_8((ioport8_t *) (port), (value))
+
+/** Writes 1 word (2 bytes).
+ *  @param[in] port The address to be written.
+ *  @param[in] value The value to be written.
+ */
+#define outw(port, value)	pio_write_16((ioport16_t *) (port), (value))
+
+/** Prints out the driver critical error.
+ *  Does not call the system panic().
+ */
+#define panic(...)	printf("%s%s%d", __VA_ARGS__)
+
+/** Copies a memory block.
+ *  @param proc The source process. Ignored parameter.
+ *  @param src_s Ignored parameter.
+ *  @param[in] src The source address.
+ *  @param me The current proces. Ignored parameter.
+ *  @param dst_s Ignored parameter.
+ *  @param[in] dst The destination address.
+ *  @param[in] bytes The block size in bytes.
+ *  @returns EOK.
+ */
+#define sys_vircopy(proc, src_s, src, me, dst_s, dst, bytes)	({memcpy((void *)(dst), (void *)(src), (bytes)); EOK;})
+
+/** Reads a memory block byte by byte.
+ *  @param[in] port The address to be written.
+ *  @param proc The source process. Ignored parameter.
+ *  @param[in] dst The destination address.
+ *  @param[in] bytes The block size in bytes.
+ */
+#define do_vir_insb(port, proc, dst, bytes)	insb((port), (void *)(dst), (bytes))
+
+/** Reads a memory block word by word (2 bytes).
+ *  @param[in] port The address to be written.
+ *  @param proc The source process. Ignored parameter.
+ *  @param[in] dst The destination address.
+ *  @param[in] bytes The block size in bytes.
+ */
+#define do_vir_insw(port, proc, dst, bytes)	insw((port), (void *)(dst), (bytes))
+
+/** Writes a memory block byte by byte.
+ *  @param[in] port The address to be written.
+ *  @param proc The source process. Ignored parameter.
+ *  @param[in] src The source address.
+ *  @param[in] bytes The block size in bytes.
+ */
+#define do_vir_outsb(port, proc, src, bytes)	outsb((port), (void *)(src), (bytes))
+
+/** Writes a memory block word by word (2 bytes).
+ *  @param[in] port The address to be written.
+ *  @param proc The source process. Ignored parameter.
+ *  @param[in] src The source address.
+ *  @param[in] bytes The block size in bytes.
+ */
+#define do_vir_outsw(port, proc, src, bytes)	outsw((port), (void *)(src), (bytes))
+
+/* com.h */
+/* Bits in 'DL_MODE' field of DL requests. */
+#  define DL_NOMODE		0x0
+#  define DL_PROMISC_REQ	0x2
+#  define DL_MULTI_REQ		0x4
+#  define DL_BROAD_REQ		0x8
+
+/* const.h */
+/** True value.
+ */
+#define TRUE               1	/* used for turning integers into Booleans */
+
+/** False value.
+ */
+#define FALSE              0	/* used for turning integers into Booleans */
+
+/** No number value.
+ */
+#define NO_NUM        0x8000	/* used as numerical argument to panic() */
+
+/* devio.h */
+//typedef u16_t port_t;
+/** Type definition of a port.
+ */
+typedef long port_t;
+
+/* dl_eth.h */
+/** Ethernet statistics.
+ */
+typedef struct eth_stat
+{
+	/** Number of receive errors.
+	 */
+	unsigned long ets_recvErr;
+	/** Number of send error.
+	 */
+	unsigned long ets_sendErr;
+	/** Number of buffer overwrite warnings.
+	 */
+	unsigned long ets_OVW;
+	/** Number of crc errors of read.
+	 */
+	unsigned long ets_CRCerr;
+	/** Number of frames not alligned (number of bits % 8 != 0).
+	 */
+	unsigned long ets_frameAll;
+	/** Number of packets missed due to slow processing.
+	 */
+	unsigned long ets_missedP;
+	/** Number of packets received.
+	 */
+	unsigned long ets_packetR;
+	/** Number of packets transmitted.
+	 */
+	unsigned long ets_packetT;
+	/** Number of transmission defered (Tx was busy).
+	 */
+	unsigned long ets_transDef;
+	/** Number of collissions.
+	 */
+	unsigned long ets_collision;
+	/** Number of Tx aborted due to excess collisions.
+	 */
+	unsigned long ets_transAb;
+	/** Number of carrier sense lost.
+	 */
+	unsigned long ets_carrSense;
+	/** Number of FIFO underruns (processor too busy).
+	 */
+	unsigned long ets_fifoUnder;
+	/** Number of FIFO overruns (processor too busy).
+	 */
+	unsigned long ets_fifoOver;
+	/** Number of times unable to transmit collision sig.
+	 */
+	unsigned long ets_CDheartbeat;
+	/** Number of times out of window collision.
+	 */
+	unsigned long ets_OWC;
+} eth_stat_t;
+
+/* errno.h */
+/** Generic error.
+ */
+#define EGENERIC     EINVAL
+
+/* ether.h */
+/** Minimum Ethernet packet size in bytes.
+ */
+#define ETH_MIN_PACK_SIZE		  60
+
+/** Maximum Ethernet packet size in bytes.
+ */
+#define ETH_MAX_PACK_SIZE_TAGGED	1518
+
+/** Ethernet address type definition.
+ */
+typedef struct ether_addr
+{
+	/** Address data.
+	 */
+	u8_t ea_addr[6];
+} ether_addr_t;
+
+/* type.h */
+/** Type definition of the physical addresses and lengths in bytes.
+ */
+typedef unsigned long phys_bytes;
+
+/** Type definition of the virtual addresses and lengths in bytes.
+ */
+typedef unsigned long vir_bytes;
+
+/** Type definition of the input/output vector.
+ */
+typedef struct {
+	/** Address of an I/O buffer.
+	 */
+	vir_bytes iov_addr;
+	/** Sizeof an I/O buffer.
+	 */
+	vir_bytes iov_size;
+} iovec_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hw/netif/dp8390/local.h
===================================================================
--- uspace/srv/hw/netif/dp8390/local.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hw/netif/dp8390/local.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system 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.
+ * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * * Any deviations from these conditions require written permission from the copyright holder in advance
+ *
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``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 COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS 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.
+ *
+ * Changes:
+ *  2009 ported to HelenOS, Lukas Mejdrech
+ */
+
+/** @addtogroup dp8390
+ *  @{
+ */
+
+/** @file
+ *  Network interface probe functions.
+ */
+
+#ifndef __NET_NETIF_DP8390_CONFIG_H__
+#define __NET_NETIF_DP8390_CONFIG_H__
+
+#include "dp8390_port.h"
+
+/*
+local.h
+*/
+
+/** WDETH switch.
+ */
+#define ENABLE_WDETH 0
+
+/** NE2000 switch.
+ */
+#define ENABLE_NE2000 1
+
+/** 3C503 switch.
+ */
+#define ENABLE_3C503 0
+
+/** PCI support switch.
+ */
+#define ENABLE_PCI 0
+
+struct dpeth;
+
+/* 3c503.c */
+/* * Probes a 3C503 network interface.
+ *  @param[in] dep The network interface structure.
+ *  @returns 1 if the NE2000 network interface is present.
+ *  @returns 0 otherwise.
+ */
+//_PROTOTYPE(int el2_probe, (struct dpeth*dep)				);
+
+/* ne2000.c */
+/** Probes a NE2000 or NE1000 network interface.
+ *  @param[in] dep The network interface structure.
+ *  @returns 1 if the NE2000 network interface is present.
+ *  @returns 0 otherwise.
+ */
+int ne_probe(struct dpeth * dep);
+//_PROTOTYPE(int ne_probe, (struct dpeth *dep)				);
+//_PROTOTYPE(void ne_init, (struct dpeth *dep)				);
+
+/* rtl8029.c */
+/* * Probes a RTL8029 network interface.
+ *  @param[in] dep The network interface structure.
+ *  @returns 1 if the NE2000 network interface is present.
+ *  @returns 0 otherwise.
+ */
+//_PROTOTYPE(int rtl_probe, (struct dpeth *dep)				);
+
+/* wdeth.c */
+/* * Probes a WDETH network interface.
+ *  @param[in] dep The network interface structure.
+ *  @returns 1 if the NE2000 network interface is present.
+ *  @returns 0 otherwise.
+ */
+//_PROTOTYPE(int wdeth_probe, (struct dpeth*dep)				);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hw/netif/dp8390/ne2000.c
===================================================================
--- uspace/srv/hw/netif/dp8390/ne2000.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hw/netif/dp8390/ne2000.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system 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.
+ * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * * Any deviations from these conditions require written permission from the copyright holder in advance
+ *
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``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 COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS 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.
+ *
+ * Changes:
+ *  2009 ported to HelenOS, Lukas Mejdrech
+ */
+
+/** @addtogroup ne2k
+ *  @{
+ */
+
+/** @file
+ *  NE1000 and NE2000 network interface initialization and probe functions implementation.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "dp8390_port.h"
+
+/*
+ne2000.c
+
+Driver for the ne2000 ethernet cards. This file contains only the ne2000
+specific code, the rest is in dp8390.c
+
+Created:	March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+//#include "../drivers.h"
+
+//#include <net/gen/ether.h>
+//#include <net/gen/eth_io.h>
+//#if __minix_vmd
+//#include "config.h"
+//#endif
+
+#include "local.h"
+#include "dp8390.h"
+#include "ne2000.h"
+
+#if ENABLE_NE2000
+
+/** Number of bytes to transfer.
+ */
+#define N 100
+
+//#define MILLIS_TO_TICKS(m)  (((m)*HZ/1000)+1)
+
+/** Sleeps for the defined millicesonds.
+ *  @param[in] millis The number of milliseconds to sleep.
+ */
+#define milli_delay(millis)	usleep((millis) * 1000)
+
+/** Type definition of the testing function.
+ */
+_PROTOTYPE(typedef int (*testf_t), (dpeth_t *dep, int pos, u8_t *pat)	);
+
+/** First data pattern.
+ */
+u8_t	pat0[]= {0x00, 0x00, 0x00, 0x00};
+
+/** Second data pattern.
+ */
+u8_t	pat1[]= {0xFF, 0xFF, 0xFF, 0xFF};
+
+/** Third data pattern.
+ */
+u8_t	pat2[]= {0xA5, 0x5A, 0x69, 0x96};
+
+/** Fourth data pattern.
+ */
+u8_t	pat3[]= {0x96, 0x69, 0x5A, 0xA5};
+
+/** Tests 8 bit NE2000 network interface.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] pos The starting position.
+ *  @param[in] pat The data pattern to be written.
+ *  @returns True on success.
+ *  @returns FALSE otherwise.
+ */
+static int test_8(dpeth_t *dep, int pos, u8_t *pat);
+
+/** Tests 16 bit NE2000 network interface.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] pos The starting position.
+ *  @param[in] pat The data pattern to be written.
+ *  @returns True on success.
+ *  @returns FALSE otherwise.
+ */
+static int test_16(dpeth_t *dep, int pos, u8_t *pat);
+
+/** Stops the NE2000 network interface.
+ *  @param[in,out] dep The network interface structure.
+ */
+static void ne_stop(dpeth_t *dep);
+//_PROTOTYPE(static void milli_delay, (unsigned long millis)		);
+
+/** Initializes the NE2000 network interface.
+ *  @param[in,out] dep The network interface structure.
+ */
+void ne_init(struct dpeth *dep);
+
+/*===========================================================================*
+ *				ne_probe				     *
+ *===========================================================================*/
+int ne_probe(dep)
+dpeth_t *dep;
+{
+	int byte;
+	int i;
+	int loc1, loc2;
+	testf_t f;
+
+	dep->de_dp8390_port= dep->de_base_port + NE_DP8390;
+
+	/* We probe for an ne1000 or an ne2000 by testing whether the
+	 * on board is reachable through the dp8390. Note that the
+	 * ne1000 is an 8bit card and has a memory region distict from
+	 * the 16bit ne2000
+	 */
+
+	for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++)
+	{
+		/* Reset the ethernet card */
+		byte= inb_ne(dep, NE_RESET);
+		milli_delay(2);
+		outb_ne(dep, NE_RESET, byte);
+		milli_delay(2);
+
+		/* Reset the dp8390 */
+		outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+		for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RST) == 0); i++)
+			; /* Do nothing */
+
+		/* Check if the dp8390 is really there */
+		if ((inb_reg0(dep, DP_CR) &(CR_STP|CR_DM_ABORT)) !=
+			(CR_STP|CR_DM_ABORT))
+		{
+			return 0;
+		}
+
+		/* Disable the receiver and init TCR and DCR. */
+		outb_reg0(dep, DP_RCR, RCR_MON);
+		outb_reg0(dep, DP_TCR, TCR_NORMAL);
+		if (dep->de_16bit)
+		{
+			outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
+				DCR_BMS);
+		}
+		else
+		{
+			outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
+				DCR_BMS);
+		}
+
+		if (dep->de_16bit)
+		{
+			loc1= NE2000_START;
+			loc2= NE2000_START + NE2000_SIZE - 4;
+			f= test_16;
+		}
+		else
+		{
+			loc1= NE1000_START;
+			loc2= NE1000_START + NE1000_SIZE - 4;
+			f= test_8;
+		}
+		if (f(dep, loc1, pat0) && f(dep, loc1, pat1) && 
+			f(dep, loc1, pat2) && f(dep, loc1, pat3) && 
+			f(dep, loc2, pat0) && f(dep, loc2, pat1) && 
+			f(dep, loc2, pat2) && f(dep, loc2, pat3))
+		{
+			/* We don't need a memory segment */
+			dep->de_linmem= 0;
+			if (!dep->de_pci)
+				dep->de_initf= ne_init;
+			dep->de_stopf= ne_stop;
+			dep->de_prog_IO= 1;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*===========================================================================*
+ *				ne_init					     *
+ *===========================================================================*/
+void ne_init(dep)
+dpeth_t *dep;
+{
+	int i;
+	int word, sendq_nr;
+
+	/* Setup a transfer to get the ethernet address. */
+	if (dep->de_16bit)
+		outb_reg0(dep, DP_RBCR0, 6*2);
+	else
+		outb_reg0(dep, DP_RBCR0, 6);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, 0);
+	outb_reg0(dep, DP_RSAR1, 0);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<6; i++)
+	{
+		if (dep->de_16bit)
+		{
+			word= inw_ne(dep, NE_DATA);
+			dep->de_address.ea_addr[i]= word;
+		}
+		else
+		{
+			dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
+		}
+	}
+	dep->de_data_port= dep->de_base_port + NE_DATA;
+	if (dep->de_16bit)
+	{
+		dep->de_ramsize= NE2000_SIZE;
+		dep->de_offset_page= NE2000_START / DP_PAGESIZE;
+	}
+	else
+	{
+		dep->de_ramsize= NE1000_SIZE;
+		dep->de_offset_page= NE1000_START / DP_PAGESIZE;
+	}
+
+	/* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
+	sendq_nr= dep->de_ramsize / 0x2000;
+	if (sendq_nr < 1)
+		sendq_nr= 1;
+	else if (sendq_nr > SENDQ_NR)
+		sendq_nr= SENDQ_NR;
+	dep->de_sendq_nr= sendq_nr;
+	for (i= 0; i<sendq_nr; i++)
+	{
+		dep->de_sendq[i].sq_sendpage= dep->de_offset_page +
+			i*SENDQ_PAGES;	
+	}
+
+	dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES;
+	dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
+
+	/* Can't override the default IRQ. */
+	dep->de_irq &= ~DEI_DEFAULT;
+
+	if (!debug)
+	{
+		printf("%s: NE%d000 at %X:%d\n",
+			dep->de_name, dep->de_16bit ? 2 : 1,
+			dep->de_base_port, dep->de_irq);
+	}
+	else
+	{
+		printf("%s: Novell NE%d000 ethernet card at I/O address "
+			"0x%X, memory size 0x%X, irq %d\n",
+			dep->de_name, dep->de_16bit ? 2 : 1,
+			dep->de_base_port, dep->de_ramsize, dep->de_irq);
+	}
+}
+
+/*===========================================================================*
+ *				test_8					     *
+ *===========================================================================*/
+static int test_8(dep, pos, pat)
+dpeth_t *dep;
+int pos;
+u8_t *pat;
+{
+	u8_t buf[4];
+	int i;
+	int r;
+
+	outb_reg0(dep, DP_ISR, 0xFF);
+
+	/* Setup a transfer to put the pattern. */
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos &0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i++)
+		outb_ne(dep, NE_DATA, pat[i]);
+
+	for (i= 0; i<N; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) &ISR_RDC)
+			break;
+	}
+	if (i == N)
+	{
+		if (debug)
+		{
+			printf("%s: NE1000 remote DMA test failed\n",
+				dep->de_name);
+		}
+		return 0;
+	}
+
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos &0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i++)
+		buf[i]= inb_ne(dep, NE_DATA);
+
+	r= (memcmp(buf, pat, 4) == 0);
+	return r;
+}
+
+/*===========================================================================*
+ *				test_16					     *
+ *===========================================================================*/
+static int test_16(dep, pos, pat)
+dpeth_t *dep;
+int pos;
+u8_t *pat;
+{
+	u8_t buf[4];
+	int i;
+	int r;
+
+	outb_reg0(dep, DP_ISR, 0xFF);
+
+	/* Setup a transfer to put the pattern. */
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos &0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i += 2)
+	{
+		outw_ne(dep, NE_DATA, *(u16_t *)(pat+i));
+	}
+
+	for (i= 0; i<N; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) &ISR_RDC)
+			break;
+	}
+	if (i == N)
+	{
+		if (debug)
+		{
+			printf("%s: NE2000 remote DMA test failed\n",
+				dep->de_name);
+		}
+		return 0;
+	}
+
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos &0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i += 2)
+	{
+		*(u16_t *)(buf+i)= inw_ne(dep, NE_DATA);
+	}
+
+	r= (memcmp(buf, pat, 4) == 0);
+	return r;
+}
+
+/*===========================================================================*
+ *				ne_stop					     *
+ *===========================================================================*/
+static void ne_stop(dep)
+dpeth_t *dep;
+{
+	int byte;
+
+	/* Reset the ethernet card */
+	byte= inb_ne(dep, NE_RESET);
+	milli_delay(2);
+	outb_ne(dep, NE_RESET, byte);
+}
+/*
+static void milli_delay(unsigned long millis)
+{
+	tickdelay(MILLIS_TO_TICKS(millis));
+}
+*/
+#endif /* ENABLE_NE2000 */
+
+/*
+ * $PchId: ne2000.c,v 1.10 2004/08/03 12:03:00 philip Exp $
+ */
+
+/** @}
+ */
Index: uspace/srv/hw/netif/dp8390/ne2000.h
===================================================================
--- uspace/srv/hw/netif/dp8390/ne2000.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/hw/netif/dp8390/ne2000.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system 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.
+ * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * * Any deviations from these conditions require written permission from the copyright holder in advance
+ *
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``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 COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS 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.
+ *
+ * Changes:
+ *  2009 ported to HelenOS, Lukas Mejdrech
+ */
+
+/*
+ne2000.h
+
+Created:	March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+/** @addtogroup ne2k
+ *  @{
+ */
+
+/** @file
+ *  NE1000 and NE2000 network interface definitions.
+ */
+
+#ifndef __NET_NETIF_NE2000_H__
+#define __NET_NETIF_NE2000_H__
+
+#include <libarch/ddi.h>
+
+#include "dp8390_port.h"
+
+/** DP8390 register offset.
+ */
+#define NE_DP8390	0x00
+
+/** Data register.
+ */
+#define NE_DATA		0x10
+
+/** Reset register.
+ */
+#define NE_RESET	0x1F
+
+/** NE1000 data start.
+ */
+#define NE1000_START	0x2000
+
+/** NE1000 data size.
+ */
+#define NE1000_SIZE	0x2000
+
+/** NE2000 data start.
+ */
+#define NE2000_START	0x4000
+
+/** NE2000 data size.
+ */
+#define NE2000_SIZE	0x4000
+
+/** Reads 1 byte register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @returns The read value.
+ */
+#define inb_ne(dep, reg)	(inb(dep->de_base_port+reg))
+
+/** Writes 1 byte register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @param[in] data The value to be written.
+ */
+#define outb_ne(dep, reg, data)	(outb(dep->de_base_port+reg, data))
+
+/** Reads 1 word (2 bytes) register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @returns The read value.
+ */
+#define inw_ne(dep, reg)	(inw(dep->de_base_port+reg))
+
+/** Writes 1 word (2 bytes) register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @param[in] data The value to be written.
+ */
+#define outw_ne(dep, reg, data)	(outw(dep->de_base_port+reg, data))
+
+#endif /* __NET_NETIF_NE2000_H__ */
+
+/*
+ * $PchId: ne2000.h,v 1.4 2004/08/03 12:03:20 philip Exp $
+ */
+
+/** @}
+ */
Index: uspace/srv/loader/Makefile
===================================================================
--- uspace/srv/loader/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -28,14 +28,20 @@
 #
 
--include ../../../Makefile.config
+USPACE_PREFIX = ../..
+ROOT_PATH = $(USPACE_PREFIX)/..
+
+COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
+CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
+
+-include $(COMMON_MAKEFILE)
+-include $(CONFIG_MAKEFILE)
 -include arch/$(UARCH)/Makefile.inc
 
-USPACE_PREFIX = ../..
-LIBS = $(LIBC_PREFIX)/libc.a
-EXTRA_CFLAGS += -Iinclude
-LINK_SCRIPT = arch/$(UARCH)/_link.ld
+LINKER_SCRIPT = arch/$(UARCH)/_link.ld
+EXTRA_CLEAN = $(LINKER_SCRIPT)
 
-OUTPUT = loader
-EXTRA_OUTPUT = $(LINK_SCRIPT)
+EXTRA_CFLAGS = -Iinclude
+
+BINARY = loader
 
 GENERIC_SOURCES = \
@@ -44,9 +50,10 @@
 	interp.s
 
-SOURCES := $(GENERIC_SOURCES) $(ARCH_SOURCES)
-OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
+SOURCES = \
+	$(GENERIC_SOURCES) \
+	$(ARCH_SOURCES)
 
-include ../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
 
-$(LINK_SCRIPT): $(LINK_SCRIPT).in
+$(LINKER_SCRIPT): $(LINKER_SCRIPT).in
 	$(GCC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@
Index: uspace/srv/loader/arch/abs32le/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/abs32le/Makefile.inc	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/loader/arch/abs32le/Makefile.inc	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2008 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+ARCH_SOURCES = arch/$(UARCH)/abs32le.c
Index: uspace/srv/loader/arch/abs32le/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/abs32le/_link.ld.in	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/loader/arch/abs32le/_link.ld.in	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,63 @@
+/*
+ * The difference from _link.ld.in for regular statically-linked apps
+ * is the base address and the special interp section.
+ */
+STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
+ENTRY(__entry)
+
+PHDRS {
+	interp PT_INTERP;
+	text PT_LOAD FILEHDR PHDRS FLAGS(5);
+	data PT_LOAD FLAGS(6);
+}
+
+SECTIONS {
+	.interp : {
+		*(.interp);
+	} :interp
+	
+	. = 0x70001000;
+	
+	.text : {
+		*(.text);
+		*(.rodata*);
+	} :text
+	
+	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
+		*(.data);
+		*(.data.rel*);
+	} :data
+	
+	.tdata : {
+		_tdata_start = .;
+		*(.tdata);
+		*(.gnu.linkonce.tb.*);
+		_tdata_end = .;
+	} :data
+	
+	.tbss : {
+		_tbss_start = .;
+		*(.tbss);
+		_tbss_end = .;
+	} :data
+	
+	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
+	.sbss : {
+		*(.scommon);
+		*(.sbss);
+	}
+	
+	.bss : {
+		*(COMMON);
+		*(.bss);
+	} :data
+	
+	. = ALIGN(0x1000);
+	
+	_heap = .;
+	
+	/DISCARD/ : {
+		*(*);
+	}
+}
Index: uspace/srv/loader/arch/abs32le/abs32le.c
===================================================================
--- uspace/srv/loader/arch/abs32le/abs32le.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/loader/arch/abs32le/abs32le.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/** @file
+ */
+
+#include <bool.h>
+#include "arch.h"
+
+void program_run(void *entry_point, void *pcb)
+{
+	while (true);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/loader/arch/amd64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/amd64/Makefile.inc	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/arch/amd64/Makefile.inc	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,3 +27,3 @@
 #
 
-ARCH_SOURCES := arch/$(UARCH)/amd64.s
+ARCH_SOURCES = arch/$(UARCH)/amd64.s
Index: uspace/srv/loader/arch/arm32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/arm32/Makefile.inc	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/arch/arm32/Makefile.inc	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,3 +27,3 @@
 #
 
-ARCH_SOURCES := arch/$(UARCH)/arm32.s
+ARCH_SOURCES = arch/$(UARCH)/arm32.s
Index: uspace/srv/loader/arch/ia32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ia32/Makefile.inc	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/arch/ia32/Makefile.inc	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,3 +27,3 @@
 #
 
-ARCH_SOURCES := arch/$(UARCH)/ia32.s
+ARCH_SOURCES = arch/$(UARCH)/ia32.s
Index: uspace/srv/loader/arch/ia64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ia64/Makefile.inc	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/arch/ia64/Makefile.inc	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,4 +27,4 @@
 #
 
-ARCH_SOURCES := arch/$(UARCH)/ia64.s
+ARCH_SOURCES = arch/$(UARCH)/ia64.s
 AFLAGS += -xexplicit
Index: uspace/srv/loader/arch/mips32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/mips32/Makefile.inc	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/arch/mips32/Makefile.inc	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,3 +27,3 @@
 #
 
-ARCH_SOURCES := arch/$(UARCH)/mips32.s
+ARCH_SOURCES = arch/$(UARCH)/mips32.s
Index: uspace/srv/loader/arch/ppc32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ppc32/Makefile.inc	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/arch/ppc32/Makefile.inc	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,3 +27,3 @@
 #
 
-ARCH_SOURCES := arch/$(UARCH)/ppc32.s
+ARCH_SOURCES = arch/$(UARCH)/ppc32.s
Index: uspace/srv/loader/arch/sparc64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/sparc64/Makefile.inc	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/arch/sparc64/Makefile.inc	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,3 +27,3 @@
 #
 
-ARCH_SOURCES := arch/$(UARCH)/sparc64.s
+ARCH_SOURCES = arch/$(UARCH)/sparc64.s
Index: uspace/srv/loader/elf_load.c
===================================================================
--- uspace/srv/loader/elf_load.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/elf_load.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -60,5 +60,5 @@
 #define DPRINTF(...)
 
-static char *error_codes[] = {
+static const char *error_codes[] = {
 	"no error",
 	"invalid image",
@@ -95,12 +95,13 @@
  * pointed to by @a info.
  *
- * @param file_name	Path to the ELF file.
- * @param so_bias	Bias to use if the file is a shared object.
- * @param info		Pointer to a structure for storing information
- *			extracted from the binary.
+ * @param file_name Path to the ELF file.
+ * @param so_bias   Bias to use if the file is a shared object.
+ * @param info      Pointer to a structure for storing information
+ *                  extracted from the binary.
  *
  * @return EOK on success or negative error code.
- */
-int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info)
+ *
+ */
+int elf_load_file(const char *file_name, size_t so_bias, elf_info_t *info)
 {
 	elf_ld_t elf;
@@ -130,5 +131,6 @@
  * earlier with elf_load_file(). This function does not return.
  *
- * @param info	Info structure filled earlier by elf_load_file()
+ * @param info Info structure filled earlier by elf_load_file()
+ *
  */
 void elf_run(elf_info_t *info, pcb_t *pcb)
@@ -280,5 +282,5 @@
  * @return NULL terminated description of error.
  */
-char *elf_error(unsigned int rc)
+const char *elf_error(unsigned int rc)
 {
 	assert(rc < sizeof(error_codes) / sizeof(char *));
Index: uspace/srv/loader/include/arch.h
===================================================================
--- uspace/srv/loader/include/arch.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/include/arch.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -37,5 +37,5 @@
 #define LOADER_ARCH_H_
 
-void program_run(void *entry_point, void *pcb);
+extern void program_run(void *entry_point, void *pcb);
 
 #endif
Index: uspace/srv/loader/include/elf.h
===================================================================
--- uspace/srv/loader/include/elf.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/include/elf.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -337,5 +337,5 @@
 #endif
 
-extern char *elf_error(unsigned int rc);
+extern const char *elf_error(unsigned int rc);
 
 #endif
Index: uspace/srv/loader/include/elf_load.h
===================================================================
--- uspace/srv/loader/include/elf_load.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/include/elf_load.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup generic	
+/** @addtogroup generic
  * @{
  */
@@ -51,5 +51,5 @@
 
 	/** ELF interpreter name or NULL if statically-linked */
-	char *interp;
+	const char *interp;
 
 	/** Pointer to the dynamic section */
@@ -74,5 +74,5 @@
 } elf_ld_t;
 
-int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info);
+int elf_load_file(const char *file_name, size_t so_bias, elf_info_t *info);
 void elf_run(elf_info_t *info, pcb_t *pcb);
 void elf_create_pcb(elf_info_t *info, pcb_t *pcb);
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/loader/main.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -58,5 +58,5 @@
 #include <errno.h>
 #include <async.h>
-#include <string.h>
+#include <str.h>
 #include <as.h>
 
@@ -126,5 +126,5 @@
 {
 	char *buf;
-	int rc = async_string_receive(&buf, 0, NULL);
+	int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, NULL);
 	
 	if (rc == EOK) {
@@ -146,5 +146,5 @@
 {
 	char *buf;
-	int rc = async_string_receive(&buf, 0, NULL);
+	int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, NULL);
 	
 	if (rc == EOK) {
@@ -167,5 +167,5 @@
 	char *buf;
 	size_t buf_size;
-	int rc = async_string_receive(&buf, 0, &buf_size);
+	int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, &buf_size);
 	
 	if (rc == EOK) {
@@ -232,5 +232,6 @@
 	fdi_node_t *buf;
 	size_t buf_size;
-	int rc = async_data_receive(&buf, 0, 0, sizeof(fdi_node_t), &buf_size);
+	int rc = async_data_write_accept((void **) &buf, false, 0, 0,
+	    sizeof(fdi_node_t), &buf_size);
 	
 	if (rc == EOK) {
@@ -240,5 +241,5 @@
 		 * Allocate new filv
 		 */
-		fdi_node_t **_filv = (fdi_node_t *) malloc((count + 1) * sizeof(fdi_node_t *));
+		fdi_node_t **_filv = (fdi_node_t **) calloc(count + 1, sizeof(fdi_node_t *));
 		if (_filv == NULL) {
 			free(buf);
Index: uspace/srv/net/cfg/Makefile
===================================================================
--- uspace/srv/net/cfg/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/cfg/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,60 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+ROOT_PATH = $(USPACE_PREFIX)/..
+
+COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
+CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
+
+-include $(COMMON_MAKEFILE)
+-include $(CONFIG_MAKEFILE)
+
+ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
+	LO_SOURCE = lo.netif_nil_bundle
+	NE2K_SOURCE = ne2k.netif_nil_bundle
+else
+	LO_SOURCE = lo.netif_standalone
+	NE2K_SOURCE = ne2k.netif_standalone
+endif
+
+LO_TARGET = lo
+NE2K_TARGET = ne2k
+
+.PHONY: all clean
+
+all: $(LO_TARGET) $(NE2K_TARGET)
+
+clean:
+	rm -f $(LO_TARGET) $(NE2K_TARGET)
+
+$(LO_TARGET): $(LO_SOURCE)
+	cp $< $@
+
+$(NE2K_TARGET): $(NE2K_SOURCE)
+	cp $< $@
Index: uspace/srv/net/cfg/general
===================================================================
--- uspace/srv/net/cfg/general	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/cfg/general	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,12 @@
+# general configuration
+
+IPV=4
+IP_ROUTING=no
+
+MTU=1500
+
+ICMP_ERROR_REPORTING=yes
+ICMP_ECHO_REPLYING=yes
+
+UDP_CHECKSUM_COMPUTING=yes
+UDP_AUTOBINDING=yes
Index: uspace/srv/net/cfg/lo.netif_nil_bundle
===================================================================
--- uspace/srv/net/cfg/lo.netif_nil_bundle	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/cfg/lo.netif_nil_bundle	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,13 @@
+# loopback configuration
+
+NAME=lo
+
+NETIF=lo
+NIL=lo
+IL=ip
+
+IP_CONFIG=static
+IP_ADDR=127.0.0.1
+IP_NETMASK=255.0.0.0
+
+MTU=15535
Index: uspace/srv/net/cfg/lo.netif_standalone
===================================================================
--- uspace/srv/net/cfg/lo.netif_standalone	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/cfg/lo.netif_standalone	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,13 @@
+# loopback configuration
+
+NAME=lo
+
+NETIF=lo
+NIL=nildummy
+IL=ip
+
+IP_CONFIG=static
+IP_ADDR=127.0.0.1
+IP_NETMASK=255.0.0.0
+
+MTU=15535
Index: uspace/srv/net/cfg/ne2k.netif_nil_bundle
===================================================================
--- uspace/srv/net/cfg/ne2k.netif_nil_bundle	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/cfg/ne2k.netif_nil_bundle	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,24 @@
+# DP8390 (NE2k) configuration
+
+NAME=ne2k
+
+NETIF=dp8390
+NIL=dp8390
+IL=ip
+
+IRQ=9
+IO=300
+
+# 8023_2_LSAP, 8023_2_SNAP
+ETH_MODE=DIX
+ETH_DUMMY=no
+
+IP_CONFIG=static
+IP_ADDR=10.0.2.15
+IP_ROUTING=yes
+IP_NETMASK=255.255.255.240
+IP_BROADCAST=10.0.2.255
+IP_GATEWAY=10.0.2.2
+ARP=arp
+
+MTU=1492
Index: uspace/srv/net/cfg/ne2k.netif_standalone
===================================================================
--- uspace/srv/net/cfg/ne2k.netif_standalone	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/cfg/ne2k.netif_standalone	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,24 @@
+# DP8390 (NE2k) configuration
+
+NAME=ne2k
+
+NETIF=dp8390
+NIL=eth
+IL=ip
+
+IRQ=9
+IO=300
+
+# 8023_2_LSAP, 8023_2_SNAP
+ETH_MODE=DIX
+ETH_DUMMY=no
+
+IP_CONFIG=static
+IP_ADDR=10.0.2.15
+IP_ROUTING=yes
+IP_NETMASK=255.255.255.240
+IP_BROADCAST=10.0.2.255
+IP_GATEWAY=10.0.2.2
+ARP=arp
+
+MTU=1492
Index: uspace/srv/net/documentation.txt
===================================================================
--- uspace/srv/net/documentation.txt	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/documentation.txt	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,201 @@
+/**
+
+\mainpage Networking and TCP/IP Stack for HelenOS system
+
+\section introduction Introduction
+
+<p>
+For the microkernel HelenOS a completely new networking stack was designed.
+The networking stack was intended to implement current basic standards of the TCP/IP Stack.
+Only the minimalistic functionality allowing the stack to function was to be implemented.
+The networking stack is written in C.
+</p>
+<p>
+Please see
+</p>
+<ul>
+	<li>\ref build</li>
+	<li>\ref software</li>
+	<li>\ref running</li>
+	<li>\ref testing</li>
+</ul>
+
+\page build Build from sources
+
+<p>
+To compile the HelenOS from sources (the cross compilers from the <code>build/</code> directory are recommended):
+</p>
+<ol>
+	<li>change the working directory to the HelenOS source directory</li>
+	<li>run <code># make config</code></li>
+	<li>check/change the configuration</li>
+	<li>save and exit the configuration tool</li>
+	<li>run <code># make</code></li>
+</ol>
+<p>
+The <code>image.iso</code> should be created on success.
+</p>
+
+\page running Running the HelenOS with networking
+
+\section netstart Starting the networking
+
+<p>
+After starting the HelenOS boot image in <em>Qemu</em>, the command line appears.
+To run <em>Qemu</em> a script <code>contrib/conf/qemu.sh</code> for Linux or <code>contrib/conf/qemu.bat</code> for Windows in the HelenOS source directory can be used.
+The provided scripts set the needed arguments:
+<br><code>-vga std -M isapc -net nic,model=ne2k_isa -net user -redir udp:8080::8080 -redir udp:8081::8081 -boot d -cdrom image.iso</code><br>
+Additional arguments may be specified on the command line, they override these set.
+</p>
+
+<p>
+The networking stack is started and initialized by running a command
+<br><code># netstart</code><br>
+The networking stack is then started and configured network interfaces are enabled.
+The current configuration is printed out.
+Since that networking applications can be run using the command line as well.
+</p>
+
+\section network Qemu network
+
+<p>
+In the common mode <em>Qemu</em> creates a simple network with a gateway and settles the guest system in.
+The network is 10.0.2.*, the gateway's address 10.0.2.2 and the guest system has 10.0.2.15.
+%Even this simple setting was a bit hard to find in the documentation.
+Therefore a static configuration is possible and no additional DHCP nor BOOTP implementations are necessary.
+On the other hand the guest system is behind a firewall.
+<em>Qemu</em> may be configured to forward some ports to the guest system and allows all outgoing traffic except ICMP and ARP protocols, so you can ping only the gateway.
+</p>
+
+\section applications Applications
+
+<p>
+A few networking applications are located in the app/ directory.
+Common functions for parsing command line arguments and printing textual networking error messages are located in that directory as well.
+The networking applications should be built with the libsocket library located in the socket/libsocket.a file.
+They can use functions and definitions from the include/socket.h header file which contains socket API and further includes:
+</p>
+<ul>
+	<li>include/byteorder.h containing byte order manipulation,</li>
+	<li>include/in.h containing IPv4 socket address structure,</li>
+	<li>include/in6.h containing IPv6 socket address structure,</li>
+	<li>include/inet.h containing socket address structure and parsing functions,</li>
+	<li>include/socket codes.h containing address and protocol families and socket types and option levels, and</li>
+	<li>include/socket errno.h containing socket and general error codes.</li>
+</ul>
+
+\page software Software prerequisites
+
+<p>
+The networking and TCP/IP stack is implemented for the ia32 architecture on top of HelenOS 0.4.1 (Escalopino), the most current stable release of HelenOS.
+So far the only one operational network interface supported is in Qemu 0.10.2 and newer.
+To run <em>Qemu</em> a script contrib/conf/qemu.sh for Linux or contrib/conf/qemu.bat for Windows in the HelenOS source directory can be used.
+The qemu and its libraries have to be installed and in the path.
+These scripts set all the necessary parameters
+with some ports redirected from the local host to the guest system.
+For testing purposes at least a low level communication application is recommended, N.E.T., netcat etc.
+</p>
+<p>
+In order to build HelenOS and the networking stack from sources a few tools are
+required:
+<ul>
+	<li>binutils in version 2.19.1,</li>
+	<li>gcc–core in version 4.3.3 11,</li>
+	<li>gcc–objc in version 4.3.3, and</li>
+	<li>gcc–g++ in version 4.3.3.</li>
+</ul>
+<p>
+All these can be downloaded and installed as cross–compilers on Linux using a script contrib/toolchain.sh in the HelenOS source directory.
+In addition rats, a static source code analyzer, and Doxygen, a documentation generator, were used.
+All development was tracked in the HelenOS subversion repository.
+</p>
+<ul>
+	<li>HelenOS website: <a href="http://www.helenos.org/" title="HelenOS website">http://www.helenos.org/</a></li>
+	<li><em>Qemu</em> website: <a href="http://www.qemu.org/" title="Qemu website">http://www.qemu.org/</a></li>
+	<li><em>binutils</em> website: <a href="http://www.gnu.org/software/binutils/" title="binutils website">http://www.gnu.org/software/binutils/</a></li>
+	<li><em>GCC</em> website: <a href="http://gcc.gnu.org/" title="GCC website">http://gcc.gnu.org/</a></li>
+	<li><em>RATS</em> website: <a href="http://www.fortify.com/security-resources/rats.jsp" title="RATS website">http://www.fortify.com/security-resources/rats.jsp</a></li>
+	<li><em>Doxygen</em> website: <a href="http://www.stack.nl/ dimitri/doxygen/index.html" title="Doxygen website">http://www.stack.nl/ dimitri/doxygen/index.html</a></li>
+	<li><em>Subversion</em> website: <a href="http://subversion.tigris.org/" title="Subversion website">http://subversion.tigris.org/</a></li>
+</ul>
+
+\page testing Testing scenarios
+
+<p>
+The scenarios contain the following shortcuts:
+</p>
+<ul>
+	<li>g for the quest system, HelenOS in <em>Qemu</em></li>
+	<li>h for the host system</li>
+	<li>n for the <em>NET</em> application</li>
+	<li>e for echo echo application run in HelenOS</li>
+</ul>
+
+\section scenarios Testing scenarios
+<ul>
+	<li>UDP
+		<ol>
+			<li>g #netstart</li>
+			<li>h wine net.exe (->n) (or net.exe)</li>
+			<li>n set 127.0.0.1:8080 address and port, BuiltinUDP protocol</li>
+			<li>n send some data (an ARP will be generated and the original packet gets lost)</li>
+			<li>n send some data (the port is unreachable and the packet is discarded)</li>
+			<li>g #echo -p 8080 -c 3 -v (->e)</li>
+			<li>g prints Listening</li>
+			<li>n send some data</li>
+			<li>e prints received data</li>
+			<li>h prints reply</li>
+			<li>n click disconnect</li>
+			<li>n set :8081 port</li>
+			<li>n send some data</li>
+			<li>n click disconnect</li>
+			<li>n set :8080 port</li>
+			<li>count-1 times:
+				<ol>
+					<li>n send some data</li>
+					<li>e prints received data</li>
+					<li>h prints reply</li>
+				</ol>
+			</li>
+			<li>e prints Exiting</li>
+			<li>e quits</li>
+			<li>n send some data (the port is unreachable and the packet is discarded)</li>
+		</ol>
+	</li>
+	<li>ICMP echo to 10.0.2.2
+		<ol>
+			<li>g #netstart</li>
+			<li>g #ping 10.0.2.2 (->p)</li>
+			<li>g prints ARP request for 10.0.2.2</li>
+			<li>g prints ARP reply from 10.0.2.2</li>
+			<li>p prints timeouted</li>
+			<li>p prints round trip time</li>
+			<li>p prints round trip time</li>
+			<li>p quits</li>
+		</ol>
+	</li>
+	<li>ICMP echo to 127.0.0.1
+		<ol>
+			<li>g #netstart</li>
+			<li>g #ping 127.0.0.1 (->p)</li>
+			<li>p prints round trip time</li>
+			<li>p prints round trip time</li>
+			<li>p prints round trip time</li>
+			<li>p quits</li>
+		</ol>
+	</li>
+	<li>ICMP with no internet on the host system (!)
+		<ol>
+			<li>g #netstart</li>
+			<li>g #ping 123.123.123.3 (->p)</li>
+			<li>g prints ARP request for 10.0.2.2</li>
+			<li>g prints ARP reply from 10.0.2.2</li>
+			<li>p prints timeouted</li>
+			<li>p prints destination unreachable</li>
+			<li>p prints destination unreachable</li>
+			<li>p quits</li>
+		</ol>
+	</li>
+</ul>
+
+*/
Index: uspace/srv/net/il/arp/Makefile
===================================================================
--- uspace/srv/net/il/arp/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/arp/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,39 @@
+#
+# 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 = ../../../..
+LIBS = $(LIBNET_PREFIX)/libnet.a $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+BINARY = arp
+
+SOURCES = \
+	arp.c \
+	arp_module.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/arp/arp.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,686 @@
+/*
+ * 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 implementation.
+ *  @see arp.h
+ */
+
+#include <async.h>
+#include <malloc.h>
+#include <mem.h>
+#include <fibril_synch.h>
+#include <stdio.h>
+#include <str.h>
+#include <task.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_messages.h>
+#include <net_modules.h>
+#include <net_byteorder.h>
+#include <net_device.h>
+#include <arp_interface.h>
+#include <nil_interface.h>
+#include <protocol_map.h>
+#include <adt/measured_strings.h>
+#include <packet/packet.h>
+#include <packet/packet_client.h>
+#include <packet_remote.h>
+#include <il_messages.h>
+#include <il_interface.h>
+#include <il_local.h>
+#include <arp_messages.h>
+
+#include "arp.h"
+#include "arp_header.h"
+#include "arp_oc.h"
+#include "arp_module.h"
+
+
+/** ARP module name.
+ */
+#define NAME  "arp"
+
+/** ARP global data.
+ */
+arp_globals_t	arp_globals;
+
+/** Clears the device specific data.
+ *  @param[in] device The device specific data.
+ */
+void arp_clear_device(arp_device_ref device);
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address);
+
+/** @name Message processing functions
+ */
+/*@{*/
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EEXIST if another device with the same device identifier and different driver service exists.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the measured_strings_return() function.
+ */
+int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address);
+
+/** 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.
+ *  @returns ENOENT if device is not found.
+ *  @returns EOK on success.
+ */
+int arp_mtu_changed_message(device_id_t device_id, size_t mtu);
+
+/** 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.
+ *  @returns EOK on success and the packet is no longer needed.
+ *  @returns 1 on success and the packet has been reused.
+ *  @returns EINVAL if the packet is too small to carry an ARP packet.
+ *  @returns EINVAL if the received address lengths differs from the registered values.
+ *  @returns ENOENT if the device is not found in the cache.
+ *  @returns ENOENT if the protocol for the device is not found in the cache.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int arp_receive_message(device_id_t device_id, packet_t packet);
+
+/** 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.
+ *  @returns The hardware address of the target.
+ *  @returns NULL if the target parameter is NULL.
+ *  @returns NULL if the device is not found.
+ *  @returns NULL if the device packet is too small to send a&nbsp;request.
+ *  @returns NULL if the hardware address is not found in the cache.
+ */
+measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target);
+
+/*@}*/
+
+DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t)
+
+INT_MAP_IMPLEMENT(arp_protos, arp_proto_t)
+
+GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t)
+
+int arp_clean_cache_req(int arp_phone){
+	int count;
+	arp_device_ref device;
+
+	fibril_rwlock_write_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);
+		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_rwlock_write_unlock(&arp_globals.lock);
+	printf("Cache cleaned\n");
+	return EOK;
+}
+
+int arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address){
+	arp_device_ref device;
+	arp_proto_ref proto;
+
+	fibril_rwlock_write_lock(&arp_globals.lock);
+	device = arp_cache_find(&arp_globals.cache, device_id);
+	if(! device){
+		fibril_rwlock_write_unlock(&arp_globals.lock);
+		return ENOENT;
+	}
+	proto = arp_protos_find(&device->protos, protocol);
+	if(! proto){
+		fibril_rwlock_write_unlock(&arp_globals.lock);
+		return ENOENT;
+	}
+	arp_addr_exclude(&proto->addresses, address->value, address->length);
+	fibril_rwlock_write_unlock(&arp_globals.lock);
+	return EOK;
+}
+
+void arp_clear_device(arp_device_ref device){
+	int count;
+	arp_proto_ref proto;
+
+	for(count = arp_protos_count(&device->protos) - 1; count >= 0; -- count){
+		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_addr_destroy(&proto->addresses);
+		}
+	}
+	arp_protos_clear(&device->protos);
+}
+
+int arp_clear_device_req(int arp_phone, device_id_t device_id){
+	arp_device_ref device;
+
+	fibril_rwlock_write_lock(&arp_globals.lock);
+	device = arp_cache_find(&arp_globals.cache, device_id);
+	if(! device){
+		fibril_rwlock_write_unlock(&arp_globals.lock);
+		return ENOENT;
+	}
+	arp_clear_device(device);
+	printf("Device %d cleared\n", device_id);
+	fibril_rwlock_write_unlock(&arp_globals.lock);
+	return EOK;
+}
+
+int arp_connect_module(services_t service){
+	if(service != SERVICE_ARP){
+		return EINVAL;
+	}
+	return EOK;
+}
+
+int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address){
+	ERROR_DECLARE;
+
+	arp_device_ref device;
+	arp_proto_ref proto;
+	int index;
+	hw_type_t hardware;
+
+	fibril_rwlock_write_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_rwlock_write_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{
+			if(ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
+				fibril_rwlock_write_unlock(&arp_globals.lock);
+				return ERROR_CODE;
+			}
+			index = arp_protos_add(&device->protos, proto->service, proto);
+			if(index < 0){
+				fibril_rwlock_write_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_ref) malloc(sizeof(arp_device_t));
+		if(! device){
+			fibril_rwlock_write_unlock(&arp_globals.lock);
+			return ENOMEM;
+		}
+		device->hardware = hardware;
+		device->device_id = device_id;
+		if(ERROR_OCCURRED(arp_protos_initialize(&device->protos))
+			|| ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
+			fibril_rwlock_write_unlock(&arp_globals.lock);
+			free(device);
+			return ERROR_CODE;
+		}
+		index = arp_protos_add(&device->protos, proto->service, proto);
+		if(index < 0){
+			fibril_rwlock_write_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, (ipcarg_t) device->device_id, SERVICE_ARP, arp_globals.client_connection);
+		if(device->phone < 0){
+			fibril_rwlock_write_unlock(&arp_globals.lock);
+			arp_protos_destroy(&device->protos);
+			free(device);
+			return EREFUSED;
+		}
+		// get packet dimensions
+		if(ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id, &device->packet_dimension))){
+			fibril_rwlock_write_unlock(&arp_globals.lock);
+			arp_protos_destroy(&device->protos);
+			free(device);
+			return ERROR_CODE;
+		}
+		// get hardware address
+		if(ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id, &device->addr, &device->addr_data))){
+			fibril_rwlock_write_unlock(&arp_globals.lock);
+			arp_protos_destroy(&device->protos);
+			free(device);
+			return ERROR_CODE;
+		}
+		// get broadcast address
+		if(ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone, device_id, &device->broadcast_addr, &device->broadcast_data))){
+			fibril_rwlock_write_unlock(&arp_globals.lock);
+			free(device->addr);
+			free(device->addr_data);
+			arp_protos_destroy(&device->protos);
+			free(device);
+			return ERROR_CODE;
+		}
+		if(ERROR_OCCURRED(arp_cache_add(&arp_globals.cache, device->device_id, device))){
+			fibril_rwlock_write_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 ERROR_CODE;
+		}
+		printf("%s: Device registered (id: %d, type: 0x%x, service: %d, proto: %d)\n",
+		    NAME, device->device_id, device->hardware, device->service, protocol);
+	}
+	fibril_rwlock_write_unlock(&arp_globals.lock);
+	return EOK;
+}
+
+int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){
+	ERROR_DECLARE;
+
+	measured_string_ref tmp;
+
+	// copy the given address for exclusive use
+	tmp = measured_string_copy(address);
+	if(ERROR_OCCURRED(arp_device_message(device_id, netif, protocol, tmp))){
+		free(tmp->value);
+		free(tmp);
+	}
+	return ERROR_CODE;
+}
+
+int arp_initialize(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+
+	fibril_rwlock_initialize(&arp_globals.lock);
+	fibril_rwlock_write_lock(&arp_globals.lock);
+	arp_globals.client_connection = client_connection;
+	ERROR_PROPAGATE(arp_cache_initialize(&arp_globals.cache));
+	fibril_rwlock_write_unlock(&arp_globals.lock);
+	return EOK;
+}
+
+int arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, int *answer_count)
+{
+	ERROR_DECLARE;
+	
+	measured_string_ref address;
+	measured_string_ref translation;
+	char * data;
+	packet_t packet;
+	packet_t next;
+	
+	*answer_count = 0;
+	switch (IPC_GET_METHOD(*call)) {
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_ARP_DEVICE:
+			ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
+			if(ERROR_OCCURRED(arp_device_message(IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address))){
+				free(address);
+				free(data);
+			}
+			return ERROR_CODE;
+		case NET_ARP_TRANSLATE:
+			ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
+			fibril_rwlock_read_lock(&arp_globals.lock);
+			translation = arp_translate_message(IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), address);
+			free(address);
+			free(data);
+			if(! translation){
+				fibril_rwlock_read_unlock(&arp_globals.lock);
+				return ENOENT;
+			}
+			ERROR_CODE = measured_strings_reply(translation, 1);
+			fibril_rwlock_read_unlock(&arp_globals.lock);
+			return ERROR_CODE;
+		case NET_ARP_CLEAR_DEVICE:
+			return arp_clear_device_req(0, IPC_GET_DEVICE(call));
+		case NET_ARP_CLEAR_ADDRESS:
+			ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
+			arp_clear_address_req(0, IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), address);
+			free(address);
+			free(data);
+			return EOK;
+		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:
+			if(! ERROR_OCCURRED(packet_translate_remote(arp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
+				fibril_rwlock_read_lock(&arp_globals.lock);
+				do{
+					next = pq_detach(packet);
+					ERROR_CODE = arp_receive_message(IPC_GET_DEVICE(call), packet);
+					if(ERROR_CODE != 1){
+						pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
+					}
+					packet = next;
+				}while(packet);
+				fibril_rwlock_read_unlock(&arp_globals.lock);
+			}
+			return ERROR_CODE;
+		case NET_IL_MTU_CHANGED:
+			return arp_mtu_changed_message(IPC_GET_DEVICE(call), IPC_GET_MTU(call));
+	}
+	
+	return ENOTSUP;
+}
+
+int arp_mtu_changed_message(device_id_t device_id, size_t mtu){
+	arp_device_ref device;
+
+	fibril_rwlock_write_lock(&arp_globals.lock);
+	device = arp_cache_find(&arp_globals.cache, device_id);
+	if(! device){
+		fibril_rwlock_write_unlock(&arp_globals.lock);
+		return ENOENT;
+	}
+	device->packet_dimension.content = mtu;
+	printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
+	fibril_rwlock_write_unlock(&arp_globals.lock);
+	return EOK;
+}
+
+int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address){
+	ERROR_DECLARE;
+
+	*proto = (arp_proto_ref) malloc(sizeof(arp_proto_t));
+	if(!(*proto)){
+		return ENOMEM;
+	}
+	(** proto).service = service;
+	(** proto).addr = address;
+	(** proto).addr_data = address->value;
+	if(ERROR_OCCURRED(arp_addr_initialize(&(** proto).addresses))){
+		free(*proto);
+		return ERROR_CODE;
+	}
+	return EOK;
+}
+
+int arp_receive_message(device_id_t device_id, packet_t packet){
+	ERROR_DECLARE;
+
+	size_t length;
+	arp_header_ref header;
+	arp_device_ref device;
+	arp_proto_ref proto;
+	measured_string_ref hw_source;
+	uint8_t * src_hw;
+	uint8_t * src_proto;
+	uint8_t * des_hw;
+	uint8_t * des_proto;
+
+	length = packet_get_data_length(packet);
+	if(length <= sizeof(arp_header_t)){
+		return EINVAL;
+	}
+	device = arp_cache_find(&arp_globals.cache, device_id);
+	if(! device){
+		return ENOENT;
+	}
+	header = (arp_header_ref) packet_get_data(packet);
+	if((ntohs(header->hardware) != device->hardware)
+		|| (length < sizeof(arp_header_t) + header->hardware_length * 2u + header->protocol_length * 2u)){
+		return EINVAL;
+	}
+	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;
+	hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length));
+	// exists?
+	if(hw_source){
+		if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){
+			return EINVAL;
+		}
+		memcpy(hw_source->value, src_hw, hw_source->length);
+	}
+	// is my protocol address?
+	if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){
+		return EINVAL;
+	}
+	if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){
+		// not already upadted?
+		if(! hw_source){
+			hw_source = measured_string_create_bulk((char *) src_hw, CONVERT_SIZE(uint8_t, char, header->hardware_length));
+			if(! hw_source){
+				return ENOMEM;
+			}
+			ERROR_PROPAGATE(arp_addr_add(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length), hw_source));
+		}
+		if(ntohs(header->operation) == ARPOP_REQUEST){
+			header->operation = htons(ARPOP_REPLY);
+			memcpy(des_proto, src_proto, header->protocol_length);
+			memcpy(src_proto, proto->addr->value, header->protocol_length);
+			memcpy(src_hw, device->addr->value, device->packet_dimension.addr_len);
+			memcpy(des_hw, hw_source->value, header->hardware_length);
+			ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw, header->hardware_length));
+			nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
+			return 1;
+		}
+	}
+	return EOK;
+}
+
+task_id_t arp_task_get_id(void){
+	return task_get_id();
+}
+
+measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){
+	arp_device_ref device;
+	arp_proto_ref proto;
+	measured_string_ref addr;
+	size_t length;
+	packet_t packet;
+	arp_header_ref header;
+
+	if(! target){
+		return NULL;
+	}
+	device = arp_cache_find(&arp_globals.cache, device_id);
+	if(! device){
+		return NULL;
+	}
+	proto = arp_protos_find(&device->protos, protocol);
+	if((! proto) || (proto->addr->length != target->length)){
+		return NULL;
+	}
+	addr = arp_addr_find(&proto->addresses, target->value, target->length);
+	if(addr){
+		return addr;
+	}
+	// ARP packet content size = header + (address + translation) * 2
+	length = 8 + (CONVERT_SIZE(char, uint8_t, proto->addr->length) + CONVERT_SIZE(char, uint8_t, device->addr->length)) * 2;
+	if(length > device->packet_dimension.content){
+		return NULL;
+	}
+	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 NULL;
+	}
+	header = (arp_header_ref) packet_suffix(packet, length);
+	if(! header){
+		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
+		return NULL;
+	}
+	header->hardware = htons(device->hardware);
+	header->hardware_length = (uint8_t) device->addr->length;
+	header->protocol = htons(protocol_map(device->service, protocol));
+	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);
+	length += device->addr->length;
+	memcpy(((uint8_t *) header) + length, proto->addr->value, proto->addr->length);
+	length += proto->addr->length;
+	bzero(((uint8_t *) header) + length, device->addr->length);
+	length += device->addr->length;
+	memcpy(((uint8_t *) header) + length, target->value, target->length);
+	if(packet_set_addr(packet, (uint8_t *) device->addr->value, (uint8_t *) device->broadcast_addr->value, CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK){
+		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
+		return NULL;
+	}
+	nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
+	return NULL;
+}
+
+int arp_translate_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data){
+	measured_string_ref tmp;
+
+	fibril_rwlock_read_lock(&arp_globals.lock);
+	tmp = arp_translate_message(device_id, protocol, address);
+	if(tmp){
+		*translation = measured_string_copy(tmp);
+		fibril_rwlock_read_unlock(&arp_globals.lock);
+		if(*translation){
+			*data = (** translation).value;
+			return EOK;
+		}else{
+			return ENOMEM;
+		}
+	}else{
+		fibril_rwlock_read_unlock(&arp_globals.lock);
+		return ENOENT;
+	}
+}
+
+/** Default thread for new connections.
+ *
+ *  @param[in] iid The initial message identifier.
+ *  @param[in] icall The initial message call structure.
+ *
+ */
+static void il_client_connection(ipc_callid_t iid, ipc_call_t * icall)
+{
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0(iid, EOK);
+	
+	while(true) {
+		ipc_call_t answer;
+		int answer_count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &answer_count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = il_module_message_standalone(callid, &call, &answer,
+		    &answer_count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, answer_count);
+	}
+}
+
+/** Starts the module.
+ *
+ *  @param argc The count of the command line arguments. Ignored parameter.
+ *  @param argv The command line parameters. Ignored parameter.
+ *
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module start function.
+ *
+ */
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	/* Start the module */
+	if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
+		return ERROR_CODE;
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp.h
===================================================================
--- uspace/srv/net/il/arp/arp.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/arp/arp.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ */
+
+#ifndef __NET_ARP_H__
+#define __NET_ARP_H__
+
+#include <fibril_synch.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_device.h>
+#include <net_hardware.h>
+#include <adt/generic_char_map.h>
+#include <adt/int_map.h>
+#include <adt/measured_strings.h>
+
+
+/** Type definition of the ARP device specific data.
+ *  @see arp_device
+ */
+typedef struct arp_device	arp_device_t;
+
+/** Type definition of the ARP device specific data pointer.
+ *  @see arp_device
+ */
+typedef arp_device_t *		arp_device_ref;
+
+/** Type definition of the ARP global data.
+ *  @see arp_globals
+ */
+typedef struct arp_globals	arp_globals_t;
+
+/** Type definition of the ARP protocol specific data.
+ *  @see arp_proto
+ */
+typedef struct arp_proto	arp_proto_t;
+
+/** Type definition of the ARP protocol specific data pointer.
+ *  @see arp_proto
+ */
+typedef arp_proto_t *		arp_proto_ref;
+
+/** ARP address map.
+ *  Translates addresses.
+ *  @see generic_char_map.h
+ */
+GENERIC_CHAR_MAP_DECLARE(arp_addr, measured_string_t)
+
+/** ARP address cache.
+ *  Maps devices to the ARP device specific data.
+ *  @see device.h
+ */
+DEVICE_MAP_DECLARE(arp_cache, arp_device_t)
+
+/** ARP protocol map.
+ *  Maps protocol identifiers to the ARP protocol specific data.
+ *  @see int_map.h
+ */
+INT_MAP_DECLARE(arp_protos, arp_proto_t)
+
+/** ARP device specific data.
+ */
+struct arp_device{
+	/** Actual device hardware address.
+	 */
+	measured_string_ref addr;
+	/** Actual device hardware address data.
+	 */
+	char * addr_data;
+	/** Broadcast device hardware address.
+	 */
+	measured_string_ref broadcast_addr;
+	/** Broadcast device hardware address data.
+	 */
+	char * broadcast_data;
+	/** Device identifier.
+	 */
+	device_id_t device_id;
+	/** Hardware type.
+	 */
+	hw_type_t hardware;
+	/** Packet dimension.
+	 */
+	packet_dimension_t packet_dimension;
+	/** Device module phone.
+	 */
+	int phone;
+	/** Protocol map.
+	 *  Address map for each protocol.
+	 */
+	arp_protos_t protos;
+	/** Device module service.
+	 */
+	services_t service;
+};
+
+/** ARP global data.
+ */
+struct	arp_globals{
+	/** ARP address cache.
+	 */
+	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;
+	/** Safety lock.
+	 */
+	fibril_rwlock_t lock;
+};
+
+/** ARP protocol specific data.
+ */
+struct arp_proto{
+	/** Actual device protocol address.
+	 */
+	measured_string_ref addr;
+	/** Actual device protocol address data.
+	 */
+	char * addr_data;
+	/** Address map.
+	 */
+	arp_addr_t addresses;
+	/** Protocol service.
+	 */
+	services_t service;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp_header.h
===================================================================
--- uspace/srv/net/il/arp/arp_header.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/arp/arp_header.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+/** Type definition of an ARP protocol header pointer.
+ *  @see arp_header
+ */
+typedef arp_header_t *		arp_header_ref;
+
+/** 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: uspace/srv/net/il/arp/arp_module.c
===================================================================
--- uspace/srv/net/il/arp/arp_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/arp/arp_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,99 @@
+/*
+ * 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 <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_modules.h>
+#include <net_interface.h>
+#include <packet/packet.h>
+#include <il_local.h>
+
+#include "arp.h"
+#include "arp_module.h"
+
+/** ARP module global data.
+ */
+extern arp_globals_t	arp_globals;
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the arp_message() function.
+ */
+int il_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	return arp_message_standalone(callid, call, answer, answer_count);
+}
+
+/** Starts the ARP 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.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the arp_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int il_module_start_standalone(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+	
+	async_set_client_connection(client_connection);
+	arp_globals.net_phone = net_connect_module(SERVICE_NETWORKING);
+	ERROR_PROPAGATE(pm_init());
+	
+	ipcarg_t phonehash;
+	if (ERROR_OCCURRED(arp_initialize(client_connection))
+	    || ERROR_OCCURRED(REGISTER_ME(SERVICE_ARP, &phonehash))) {
+		pm_destroy();
+		return ERROR_CODE;
+	}
+	
+	async_manager();
+	
+	pm_destroy();
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp_module.h
===================================================================
--- uspace/srv/net/il/arp/arp_module.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/arp/arp_module.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,65 @@
+/*
+ * 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>
+
+/** Initializes the ARP module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int arp_initialize(async_client_conn_t client_connection);
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see arp_interface.h
+ *  @see IS_NET_ARP_MESSAGE()
+ */
+int arp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp_oc.h
===================================================================
--- uspace/srv/net/il/arp/arp_oc.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/arp/arp_oc.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,141 @@
+/*
+ * 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
+
+/** Reverse request operation code.
+ */
+#define ARPOP_RREQUEST					3
+
+/** Reverse reply operation code.
+ */
+#define ARPOP_RREPLY					4
+
+/** DRARP-Request operation code.
+ */
+#define ARPOP_DRARP_Request				5
+
+/** DRARP-Reply operation code.
+ */
+#define ARPOP_DRARP_Reply				6
+
+/** DRARP-Error operation code.
+ */
+#define ARPOP_DRARP_Error				7
+
+/** InARP-Request operation code.
+ */
+#define ARPOP_InREQUEST					8
+
+/** InARP-Reply operation code.
+ */
+#define ARPOP_InREPLY					9
+
+/** ARP-NAK operation code.
+ */
+#define ARPOP_NAK						10
+
+/** MARS-Request operation code.
+ */
+#define ARPOP_MARS_Request				11
+
+/** MARS-Multi operation code.
+ */
+#define ARPOP_MARS_Multi				12
+
+/** MARS-MServ operation code.
+ */
+#define ARPOP_MARS_MServ				13
+
+/** MARS-Join operation code.
+ */
+#define ARPOP_MARS_Join					14
+
+/** MARS-Leave operation code.
+ */
+#define ARPOP_MARS_Leave				15
+
+/** MARS-NAK operation code.
+ */
+#define ARPOP_MARS_NAK					16
+
+/** MARS-Unserv operation code.
+ */
+#define ARPOP_MARS_Unserv				17
+
+/** MARS-SJoin operation code.
+ */
+#define ARPOP_MARS_SJoin				18
+
+/** MARS-SLeave operation code.
+ */
+#define ARPOP_MARS_SLeave				19
+
+/** MARS-Grouplist-Request operation code.
+ */
+#define ARPOP_MARS_Grouplist_Request	20
+
+/** MARS-Grouplist-Reply operation code.
+ */
+#define ARPOP_MARS_Grouplist_Reply		21
+
+/** MARS-Redirect-Map operation code.
+ */
+#define ARPOP_MARS_Redirect_Map			22
+
+/** MAPOS-UNARP operation code.
+ */
+#define ARPOP_MAPOS_UNARP				23
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/Makefile
===================================================================
--- uspace/srv/net/il/ip/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/ip/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,39 @@
+#
+# 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 = ../../../..
+LIBS = $(LIBNET_PREFIX)/libnet.a $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+BINARY = ip
+
+SOURCES = \
+	ip.c \
+	ip_module.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/ip/ip.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,1727 @@
+/*
+ * 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 implementation.
+ *  @see arp.h
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <stdio.h>
+#include <str.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+#include <sys/types.h>
+
+#include <net_err.h>
+#include <net_messages.h>
+#include <net_modules.h>
+#include <arp_interface.h>
+#include <net_byteorder.h>
+#include <net_checksum.h>
+#include <net_device.h>
+#include <icmp_client.h>
+#include <icmp_codes.h>
+#include <icmp_interface.h>
+#include <il_interface.h>
+#include <in.h>
+#include <in6.h>
+#include <inet.h>
+#include <ip_client.h>
+#include <ip_interface.h>
+#include <net_interface.h>
+#include <nil_interface.h>
+#include <tl_interface.h>
+#include <socket_codes.h>
+#include <socket_errno.h>
+#include <adt/measured_strings.h>
+#include <adt/module_map.h>
+#include <packet/packet_client.h>
+#include <packet_remote.h>
+#include <nil_messages.h>
+#include <il_messages.h>
+#include <il_local.h>
+#include <ip_local.h>
+
+#include "ip.h"
+#include "ip_header.h"
+#include "ip_messages.h"
+#include "ip_module.h"
+
+/** IP module name.
+ */
+#define NAME  "ip"
+
+/** IP version 4.
+ */
+#define IPV4				4
+
+/** Default network interface IP version.
+ */
+#define NET_DEFAULT_IPV		IPV4
+
+/** Default network interface IP routing.
+ */
+#define NET_DEFAULT_IP_ROUTING	false
+
+/** Minimum IP packet content.
+ */
+#define IP_MIN_CONTENT	576
+
+/** ARP module name.
+ */
+#define ARP_NAME				"arp"
+
+/** ARP module filename.
+ */
+#define ARP_FILENAME			"/srv/arp"
+
+/** IP packet address length.
+ */
+#define IP_ADDR							sizeof(struct sockaddr_in6)
+
+/** IP packet prefix length.
+ */
+#define IP_PREFIX						sizeof(ip_header_t)
+
+/** IP packet suffix length.
+ */
+#define IP_SUFFIX						0
+
+/** IP packet maximum content length.
+ */
+#define IP_MAX_CONTENT					65535
+
+/** The IP localhost address.
+ */
+#define IPV4_LOCALHOST_ADDRESS	htonl((127 << 24) + 1)
+
+/** IP global data.
+ */
+ip_globals_t	ip_globals;
+
+DEVICE_MAP_IMPLEMENT(ip_netifs, ip_netif_t)
+
+INT_MAP_IMPLEMENT(ip_protos, ip_proto_t)
+
+GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t)
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOENT if device is not found.
+ */
+int ip_mtu_changed_message(device_id_t device_id, size_t mtu);
+
+/** Updates the device state.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] state The new state value.
+ *  @returns EOK on success.
+ *  @returns ENOENT if device is not found.
+ */
+int ip_device_state_message(device_id_t device_id, device_state_t state);
+
+/** Returns the device packet dimensions for sending.
+ *  @param[in] phone The service module phone.
+ *  @param[in] message The service specific message.
+ *  @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.
+ *  @returns EOK on success.
+ */
+int ip_packet_size_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix);
+
+/** 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] tl_received_msg The receiving function.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the protocol parameter and/or the service parameter is zero (0).
+ *  @returns EINVAL if the phone parameter is not a positive number and the tl_receive_msg is NULL.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int ip_register(int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg);
+
+/** Initializes a new network interface specific data.
+ *  Connects to the network interface layer module, reads the netif configuration, starts an ARP module if needed and sets the netif routing table.
+ *  The device identifier and the nil service has to be set.
+ *  @param[in,out] ip_netif Network interface specific data.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if DHCP is configured.
+ *  @returns ENOTSUP if IPv6 is configured.
+ *  @returns EINVAL if any of the addresses is invalid.
+ *  @returns EINVAL if the used ARP module is not known.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the net_get_device_conf_req() function.
+ *  @returns Other error codes as defined for the bind_service() function.
+ *  @returns Other error codes as defined for the specific arp_device_req() function.
+ *  @returns Other error codes as defined for the nil_packet_size_req() function.
+ */
+int ip_netif_initialize(ip_netif_ref ip_netif);
+
+/** Sends the packet or the packet queue via the specified route.
+ *  The ICMP_HOST_UNREACH error notification may be sent if route hardware destination address is found.
+ *  @param[in,out] packet The packet to be sent.
+ *  @param[in] netif The target network interface.
+ *  @param[in] route The target route.
+ *  @param[in] src The source address.
+ *  @param[in] dest The destination address.
+ *  @param[in] error The error module service.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the arp_translate_req() function.
+ *  @returns Other error codes as defined for the ip_prepare_packet() function.
+ */
+int ip_send_route(packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error);
+
+/** Prepares the outgoing packet or the packet queue.
+ *  The packet queue is a fragmented packet
+ *  Updates the first packet's IP header.
+ *  Prefixes the additional packets with fragment headers.
+ *  @param[in] source The source address.
+ *  @param[in] dest The destination address.
+ *  @param[in,out] packet The packet to be sent.
+ *  @param[in] destination The destination hardware address.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is too small to contain the IP header.
+ *  @returns EINVAL if the packet is too long than the IP allows.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the packet_set_addr() function.
+ */
+int ip_prepare_packet(in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination);
+
+/** Checks the packet queue lengths and fragments the packets if needed.
+ *  The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to be fragmented and the fragmentation is not allowed.
+ *  @param[in,out] packet The packet or the packet queue to be checked.
+ *  @param[in] prefix The minimum prefix size.
+ *  @param[in] content The maximum content size.
+ *  @param[in] suffix The minimum suffix size.
+ *  @param[in] addr_len The minimum address length.
+ *  @param[in] error The error module service.
+ *  @returns The packet or the packet queue of the allowed length.
+ *  @returns NULL if there are no packets left.
+ */
+packet_t ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error);
+
+/** Checks the packet length and fragments it if needed.
+ *  The new fragments are queued before the original packet.
+ *  @param[in,out] packet The packet to be checked.
+ *  @param[in] length The maximum packet length.
+ *  @param[in] prefix The minimum prefix size.
+ *  @param[in] suffix The minimum suffix size.
+ *  @param[in] addr_len The minimum address length.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet_get_addr() function fails.
+ *  @returns EINVAL if the packet does not contain the IP header.
+ *  @returns EPERM if the packet needs to be fragmented and the fragmentation is not allowed.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns ENOMEM if there is no packet available.
+ *  @returns ENOMEM if the packet is too small to contain the IP header.
+ *  @returns Other error codes as defined for the packet_trim() function.
+ *  @returns Other error codes as defined for the ip_create_middle_header() function.
+ *  @returns Other error codes as defined for the ip_fragment_packet_data() function.
+ */
+int ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len);
+
+/** Fragments the packet from the end.
+ *  @param[in] packet The packet to be fragmented.
+ *  @param[in,out] new_packet The new packet fragment.
+ *  @param[in,out] header The original packet header.
+ *  @param[in,out] new_header The new packet fragment header.
+ *  @param[in] length The new fragment length.
+ *  @param[in] src The source address.
+ *  @param[in] dest The destiantion address.
+ *  @param[in] addrlen The address length.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if the target packet is too small.
+ *  @returns Other error codes as defined for the packet_set_addr() function.
+ *  @returns Other error codes as defined for the pq_insert_after() function.
+ */
+int ip_fragment_packet_data(packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen);
+
+/** 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.
+ *  @returns The prefixed middle header.
+ *  @returns NULL on error.
+ */
+ip_header_ref ip_create_middle_header(packet_t packet, ip_header_ref last);
+
+/** Copies the fragment header.
+ *  Copies only the header itself and relevant IP options.
+ *  @param[out] last The created header.
+ *  @param[in] first The original header to be copied.
+ */
+void ip_create_last_header(ip_header_ref last, ip_header_ref first);
+
+/** Returns the network interface's IP address.
+ *  @param[in] netif The network interface.
+ *  @returns The IP address.
+ *  @returns NULL if no IP address was found.
+ */
+in_addr_t * ip_netif_address(ip_netif_ref netif);
+
+/** Searches all network interfaces if there is a suitable route.
+ *  @param[in] destination The destination address.
+ *  @returns The found route.
+ *  @returns NULL if no route was found.
+ */
+ip_route_ref ip_find_route(in_addr_t destination);
+
+/** 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.
+ *  @returns The found route.
+ *  @returns NULL if no route was found.
+ */
+ip_route_ref ip_netif_find_route(ip_netif_ref netif, in_addr_t destination);
+
+/** 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.
+ *  @returns EOK on success and the packet is no longer needed.
+ *  @returns EINVAL if the packet is too small to carry the IP packet.
+ *  @returns EINVAL if the received address lengths differs from the registered values.
+ *  @returns ENOENT if the device is not found in the cache.
+ *  @returns ENOENT if the protocol for the device is not found in the cache.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int ip_receive_message(device_id_t device_id, packet_t packet);
+
+/** 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 (2).
+ *  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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the TTL is less than two (2).
+ *  @returns EINVAL if the checksum is invalid.
+ *  @returns EAFNOSUPPORT if the address family is not supported.
+ *  @returns ENOENT if no route was found.
+ *  @returns ENOENT if the packet is for another host and the routing is disabled.
+ */
+int ip_process_packet(device_id_t device_id, packet_t packet);
+
+/** Returns the packet destination address from the IP header.
+ *  @param[in] header The packet IP header to be read.
+ *  @returns The packet destination address.
+ */
+in_addr_t ip_get_destination(ip_header_ref header);
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the packet is a fragment.
+ *  @returns EAFNOSUPPORT if the address family is not supported.
+ *  @returns ENOENT if the target protocol is not found.
+ *  @returns Other error codes as defined for the packet_set_addr() function.
+ *  @returns Other error codes as defined for the packet_trim() function.
+ *  @returns Other error codes as defined for the protocol specific tl_received_msg function.
+ */
+int ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, services_t error);
+
+/** Prepares the ICMP notification packet.
+ *  Releases additional packets and keeps only the first one.
+ *  All packets is released on error.
+ *  @param[in] error The packet error service.
+ *  @param[in] packet The packet or the packet queue to be reported as faulty.
+ *  @param[in] header The first packet IP header. May be NULL.
+ *  @returns The found ICMP phone.
+ *  @returns EINVAL if the error parameter is set.
+ *  @returns EINVAL if the ICMP phone is not found.
+ *  @returns EINVAL if the ip_prepare_icmp() fails.
+ */
+int ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, ip_header_ref header);
+
+/** Returns the ICMP phone.
+ *  Searches the registered protocols.
+ *  @returns The found ICMP phone.
+ *  @returns ENOENT if the ICMP is not registered.
+ */
+int ip_get_icmp_phone(void);
+
+/** Prepares the ICMP notification packet.
+ *  Releases additional packets and keeps only the first one.
+ *  @param[in] packet The packet or the packet queue to be reported as faulty.
+ *  @param[in] header The first packet IP header. May be NULL.
+ *  @returns EOK on success.
+ *  @returns EINVAL if there are no data in the packet.
+ *  @returns EINVAL if the packet is a fragment.
+ *  @returns ENOMEM if the packet is too short to contain the IP header.
+ *  @returns EAFNOSUPPORT if the address family is not supported.
+ *  @returns EPERM if the protocol is not allowed to send ICMP notifications. The ICMP protocol itself.
+ *  @returns Other error codes as defined for the packet_set_addr().
+ */
+int ip_prepare_icmp(packet_t packet, ip_header_ref header);
+
+/** Releases the packet and returns the result.
+ *  @param[in] packet The packet queue to be released.
+ *  @param[in] result The result to be returned.
+ *  @return The result parameter.
+ */
+int ip_release_and_return(packet_t packet, int result);
+
+int ip_initialize(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+
+	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.packet_counter = 0;
+	ip_globals.gateway.address.s_addr = 0;
+	ip_globals.gateway.netmask.s_addr = 0;
+	ip_globals.gateway.gateway.s_addr = 0;
+	ip_globals.gateway.netif = NULL;
+	ERROR_PROPAGATE(ip_netifs_initialize(&ip_globals.netifs));
+	ERROR_PROPAGATE(ip_protos_initialize(&ip_globals.protos));
+	ip_globals.client_connection = client_connection;
+	ERROR_PROPAGATE(modules_initialize(&ip_globals.modules));
+	ERROR_PROPAGATE(add_module(NULL, &ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module));
+	fibril_rwlock_write_unlock(&ip_globals.lock);
+	return EOK;
+}
+
+int ip_device_req_local(int il_phone, device_id_t device_id, services_t netif){
+	ERROR_DECLARE;
+
+	ip_netif_ref ip_netif;
+	ip_route_ref route;
+	int index;
+
+	ip_netif = (ip_netif_ref) malloc(sizeof(ip_netif_t));
+	if(! ip_netif){
+		return ENOMEM;
+	}
+	if(ERROR_OCCURRED(ip_routes_initialize(&ip_netif->routes))){
+		free(ip_netif);
+		return ERROR_CODE;
+	}
+	ip_netif->device_id = device_id;
+	ip_netif->service = netif;
+	ip_netif->state = NETIF_STOPPED;
+	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
+	if(ERROR_OCCURRED(ip_netif_initialize(ip_netif))){
+		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+		ip_routes_destroy(&ip_netif->routes);
+		free(ip_netif);
+		return ERROR_CODE;
+	}
+	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);
+	printf("%s: Broadcast (%s)\n", NAME, address);
+	
+	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+	return EOK;
+}
+
+int ip_netif_initialize(ip_netif_ref ip_netif){
+	ERROR_DECLARE;
+
+	measured_string_t names[] = {{str_dup("IPV"), 3}, {str_dup("IP_CONFIG"), 9}, {str_dup("IP_ADDR"), 7}, {str_dup("IP_NETMASK"), 10}, {str_dup("IP_GATEWAY"), 10}, {str_dup("IP_BROADCAST"), 12}, {str_dup("ARP"), 3}, {str_dup("IP_ROUTING"), 10}};
+	measured_string_ref configuration;
+	size_t count = sizeof(names) / sizeof(measured_string_t);
+	char * data;
+	measured_string_t address;
+	int index;
+	ip_route_ref route;
+	in_addr_t gateway;
+
+	ip_netif->arp = NULL;
+	route = NULL;
+	ip_netif->ipv = NET_DEFAULT_IPV;
+	ip_netif->dhcp = false;
+	ip_netif->routing = NET_DEFAULT_IP_ROUTING;
+	configuration = &names[0];
+	// get configuration
+	ERROR_PROPAGATE(net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id, &configuration, count, &data));
+	if(configuration){
+		if(configuration[0].value){
+			ip_netif->ipv = strtol(configuration[0].value, NULL, 0);
+		}
+		ip_netif->dhcp = ! str_lcmp(configuration[1].value, "dhcp", configuration[1].length);
+		if(ip_netif->dhcp){
+			// TODO dhcp
+			net_free_settings(configuration, data);
+			return ENOTSUP;
+		}else if(ip_netif->ipv == IPV4){
+			route = (ip_route_ref) malloc(sizeof(ip_route_t));
+			if(! route){
+				net_free_settings(configuration, data);
+				return ENOMEM;
+			}
+			route->address.s_addr = 0;
+			route->netmask.s_addr = 0;
+			route->gateway.s_addr = 0;
+			route->netif = ip_netif;
+			index = ip_routes_add(&ip_netif->routes, route);
+			if(index < 0){
+				net_free_settings(configuration, data);
+				free(route);
+				return index;
+			}
+			if(ERROR_OCCURRED(inet_pton(AF_INET, configuration[2].value, (uint8_t *) &route->address.s_addr))
+				|| ERROR_OCCURRED(inet_pton(AF_INET, configuration[3].value, (uint8_t *) &route->netmask.s_addr))
+				|| (inet_pton(AF_INET, configuration[4].value, (uint8_t *) &gateway.s_addr) == EINVAL)
+				|| (inet_pton(AF_INET, configuration[5].value, (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL)){
+				net_free_settings(configuration, data);
+				return EINVAL;
+			}
+		}else{
+			// TODO ipv6 in separate module
+			net_free_settings(configuration, data);
+			return ENOTSUP;
+		}
+		if(configuration[6].value){
+			ip_netif->arp = get_running_module(&ip_globals.modules, configuration[6].value);
+			if(! ip_netif->arp){
+				printf("Failed to start the arp %s\n", configuration[6].value);
+				net_free_settings(configuration, data);
+				return EINVAL;
+			}
+		}
+		if(configuration[7].value){
+			ip_netif->routing = (configuration[7].value[0] == 'y');
+		}
+		net_free_settings(configuration, data);
+	}
+	// binds the netif service which also initializes the device
+	ip_netif->phone = nil_bind_service(ip_netif->service, (ipcarg_t) ip_netif->device_id, SERVICE_IP, ip_globals.client_connection);
+	if(ip_netif->phone < 0){
+		printf("Failed to contact the nil service %d\n", ip_netif->service);
+		return ip_netif->phone;
+	}
+	// has to be after the device netif module initialization
+	if(ip_netif->arp){
+		if(route){
+			address.value = (char *) &route->address.s_addr;
+			address.length = CONVERT_SIZE(in_addr_t, char, 1);
+			ERROR_PROPAGATE(arp_device_req(ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, &address));
+		}else{
+			ip_netif->arp = 0;
+		}
+	}
+	// get packet dimensions
+	ERROR_PROPAGATE(nil_packet_size_req(ip_netif->phone, ip_netif->device_id, &ip_netif->packet_dimension));
+	if(ip_netif->packet_dimension.content < IP_MIN_CONTENT){
+		printf("Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->packet_dimension.content, IP_MIN_CONTENT);
+		ip_netif->packet_dimension.content = IP_MIN_CONTENT;
+	}
+	index = ip_netifs_add(&ip_globals.netifs, ip_netif->device_id, ip_netif);
+	if(index < 0){
+		return index;
+	}
+	if(gateway.s_addr){
+		// the default gateway
+		ip_globals.gateway.address.s_addr = 0;
+		ip_globals.gateway.netmask.s_addr = 0;
+		ip_globals.gateway.gateway.s_addr = gateway.s_addr;
+		ip_globals.gateway.netif = ip_netif;
+	}
+	return EOK;
+}
+
+int ip_mtu_changed_message(device_id_t device_id, size_t mtu){
+	ip_netif_ref 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;
+	printf("%s: Device %d changed MTU to %d\n", NAME, device_id, mtu);
+	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+	return EOK;
+}
+
+int ip_device_state_message(device_id_t device_id, device_state_t state){
+	ip_netif_ref 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;
+	printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
+	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+	return EOK;
+}
+
+int ip_connect_module(services_t service){
+	return EOK;
+}
+
+int ip_bind_service(services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg){
+	return ip_register(protocol, me, 0, received_msg);
+}
+
+int ip_register(int protocol, services_t service, int phone, tl_received_msg_t received_msg){
+	ip_proto_ref proto;
+	int index;
+
+	if(!(protocol && service && ((phone > 0) || (received_msg)))){
+		return EINVAL;
+	}
+	proto = (ip_proto_ref) 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;
+	}
+	
+	printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
+	    NAME, proto->protocol, proto->phone);
+	
+	fibril_rwlock_write_unlock(&ip_globals.protos_lock);
+	return EOK;
+}
+
+int ip_send_msg_local(int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error){
+	ERROR_DECLARE;
+
+	int addrlen;
+	ip_netif_ref netif;
+	ip_route_ref route;
+	struct sockaddr * addr;
+	struct sockaddr_in * address_in;
+//	struct sockaddr_in6 *	address_in6;
+	in_addr_t * dest;
+	in_addr_t * src;
+	int phone;
+
+	// addresses in the host byte order
+	// should be the next hop address or the target destination address
+	addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
+	if(addrlen < 0){
+		return ip_release_and_return(packet, addrlen);
+	}
+	if((size_t) addrlen < sizeof(struct sockaddr)){
+		return ip_release_and_return(packet, EINVAL);
+	}
+	switch(addr->sa_family){
+		case AF_INET:
+			if(addrlen != sizeof(struct sockaddr_in)){
+				return ip_release_and_return(packet, EINVAL);
+			}
+			address_in = (struct sockaddr_in *) addr;
+			dest = &address_in->sin_addr;
+			if(! dest->s_addr){
+				dest->s_addr = IPV4_LOCALHOST_ADDRESS;
+			}
+			break;
+		// TODO IPv6
+/*		case AF_INET6:
+			if(addrlen != sizeof(struct sockaddr_in6)){
+				return EINVAL;
+			}
+			address_in6 = (struct sockaddr_in6 *) dest;
+			address_in6.sin6_addr.s6_addr;
+			IPV6_LOCALHOST_ADDRESS;
+*/		default:
+			return ip_release_and_return(packet, EAFNOSUPPORT);
+	}
+	netif = NULL;
+	route = NULL;
+	fibril_rwlock_read_lock(&ip_globals.netifs_lock);
+	// device specified?
+	if(device_id > 0){
+		netif = ip_netifs_find(&ip_globals.netifs, device_id);
+		route = ip_netif_find_route(netif, * dest);
+		if(netif && (! route) && (ip_globals.gateway.netif == netif)){
+			route = &ip_globals.gateway;
+		}
+	}
+	if(! route){
+		route = ip_find_route(*dest);
+		netif = route ? route->netif : NULL;
+	}
+	if(!(netif && route)){
+		fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
+		phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
+		if(phone >= 0){
+			// unreachable ICMP if no routing
+			icmp_destination_unreachable_msg(phone, ICMP_NET_UNREACH, 0, packet);
+		}
+		return ENOENT;
+	}
+	if(error){
+		// do not send for broadcast, anycast packets or network broadcast
+		if((! dest->s_addr)
+			|| (!(~ dest->s_addr))
+			|| (!(~((dest->s_addr &(~ route->netmask.s_addr)) | route->netmask.s_addr)))
+			|| (!(dest->s_addr &(~ route->netmask.s_addr)))){
+			return ip_release_and_return(packet, EINVAL);
+		}
+	}
+	// if the local host is the destination
+	if((route->address.s_addr == dest->s_addr)
+		&& (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
+		// find the loopback device to deliver
+		dest->s_addr = IPV4_LOCALHOST_ADDRESS;
+		route = ip_find_route(*dest);
+		netif = route ? route->netif : NULL;
+		if(!(netif && route)){
+			fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
+			phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
+			if(phone >= 0){
+				// unreachable ICMP if no routing
+				icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
+			}
+			return ENOENT;
+		}
+	}
+	src = ip_netif_address(netif);
+	if(! src){
+		fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
+		return ip_release_and_return(packet, ENOENT);
+	}
+	ERROR_CODE = ip_send_route(packet, netif, route, src, * dest, error);
+	fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
+	return ERROR_CODE;
+}
+
+in_addr_t * ip_netif_address(ip_netif_ref netif){
+	ip_route_ref route;
+
+	route = ip_routes_get_index(&netif->routes, 0);
+	return route ? &route->address : NULL;
+}
+
+int ip_send_route(packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error){
+	ERROR_DECLARE;
+
+	measured_string_t destination;
+	measured_string_ref translation;
+	char * data;
+	int phone;
+
+	// get destination hardware address
+	if(netif->arp && (route->address.s_addr != dest.s_addr)){
+		destination.value = route->gateway.s_addr ? (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
+		destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
+		if(ERROR_OCCURRED(arp_translate_req(netif->arp->phone, netif->device_id, SERVICE_IP, &destination, &translation, &data))){
+//			sleep(1);
+//			ERROR_PROPAGATE(arp_translate_req(netif->arp->phone, netif->device_id, SERVICE_IP, &destination, &translation, &data));
+			pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
+			return ERROR_CODE;
+		}
+		if(!(translation && translation->value)){
+			if(translation){
+				free(translation);
+				free(data);
+			}
+			phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
+			if(phone >= 0){
+				// unreachable ICMP if no routing
+				icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
+			}
+			return EINVAL;
+		}
+	}else translation = NULL;
+	if(ERROR_OCCURRED(ip_prepare_packet(src, dest, packet, translation))){
+		pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
+	}else{
+		packet = ip_split_packet(packet, netif->packet_dimension.prefix, netif->packet_dimension.content, netif->packet_dimension.suffix, netif->packet_dimension.addr_len, error);
+		if(packet){
+			nil_send_msg(netif->phone, netif->device_id, packet, SERVICE_IP);
+		}
+	}
+	if(translation){
+		free(translation);
+		free(data);
+	}
+	return ERROR_CODE;
+}
+
+int ip_prepare_packet(in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination){
+	ERROR_DECLARE;
+
+	size_t length;
+	ip_header_ref header;
+	ip_header_ref last_header;
+	ip_header_ref middle_header;
+	packet_t next;
+
+	length = packet_get_data_length(packet);
+	if((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT)){
+		return EINVAL;
+	}
+	header = (ip_header_ref) packet_get_data(packet);
+	if(destination){
+		ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
+	}else{
+		ERROR_PROPAGATE(packet_set_addr(packet, NULL, NULL, 0));
+	}
+	header->version = IPV4;
+	header->fragment_offset_high = 0;
+	header->fragment_offset_low = 0;
+	header->header_checksum = 0;
+	if(source){
+		header->source_address = source->s_addr;
+	}
+	header->destination_address = dest.s_addr;
+	fibril_rwlock_write_lock(&ip_globals.lock);
+	++ ip_globals.packet_counter;
+	header->identification = htons(ip_globals.packet_counter);
+	fibril_rwlock_write_unlock(&ip_globals.lock);
+//	length = packet_get_data_length(packet);
+	if(pq_next(packet)){
+		last_header = (ip_header_ref) malloc(IP_HEADER_LENGTH(header));
+		if(! last_header){
+			return ENOMEM;
+		}
+		ip_create_last_header(last_header, header);
+		next = pq_next(packet);
+		while(pq_next(next)){
+			middle_header = (ip_header_ref) packet_prefix(next, IP_HEADER_LENGTH(last_header));
+			if(! middle_header){
+				return ENOMEM;
+			}
+			memcpy(middle_header, last_header, IP_HEADER_LENGTH(last_header));
+			header->flags |= IPFLAG_MORE_FRAGMENTS;
+			middle_header->total_length = htons(packet_get_data_length(next));
+			middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
+			middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
+			middle_header->header_checksum = IP_HEADER_CHECKSUM(middle_header);
+			if(destination){
+				ERROR_PROPAGATE(packet_set_addr(next, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
+			}
+			length += packet_get_data_length(next);
+			next = pq_next(next);
+		}
+		middle_header = (ip_header_ref) packet_prefix(next, IP_HEADER_LENGTH(last_header));
+		if(! middle_header){
+			return ENOMEM;
+		}
+		memcpy(middle_header, last_header, IP_HEADER_LENGTH(last_header));
+		middle_header->total_length = htons(packet_get_data_length(next));
+		middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
+		middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
+		middle_header->header_checksum = IP_HEADER_CHECKSUM(middle_header);
+		if(destination){
+			ERROR_PROPAGATE(packet_set_addr(next, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
+		}
+		length += packet_get_data_length(next);
+		free(last_header);
+		header->flags |= IPFLAG_MORE_FRAGMENTS;
+	}
+	header->total_length = htons(length);
+	// unnecessary for all protocols
+	header->header_checksum = IP_HEADER_CHECKSUM(header);
+	return EOK;
+}
+
+int ip_message_standalone(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, int * answer_count)
+{
+	ERROR_DECLARE;
+	
+	packet_t packet;
+	struct sockaddr *addr;
+	size_t addrlen;
+	size_t prefix;
+	size_t suffix;
+	size_t content;
+	void *header;
+	size_t headerlen;
+	device_id_t device_id;
+	
+	*answer_count = 0;
+	switch (IPC_GET_METHOD(*call)) {
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_IL_DEVICE:
+			return ip_device_req_local(0, IPC_GET_DEVICE(call),
+			    IPC_GET_SERVICE(call));
+		case IPC_M_CONNECT_TO_ME:
+			return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
+			    IPC_GET_PHONE(call), NULL);
+		case NET_IL_SEND:
+			ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
+			    IPC_GET_PACKET(call)));
+			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:
+			ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
+			    IPC_GET_PACKET(call)));
+			return ip_receive_message(IPC_GET_DEVICE(call), packet);
+		case NET_IP_RECEIVED_ERROR:
+			ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
+			    IPC_GET_PACKET(call)));
+			return ip_received_error_msg_local(0, IPC_GET_DEVICE(call), packet,
+			    IPC_GET_TARGET(call), IPC_GET_ERROR(call));
+		case NET_IP_ADD_ROUTE:
+			return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
+			    IP_GET_ADDRESS(call), IP_GET_NETMASK(call), IP_GET_GATEWAY(call));
+		case NET_IP_SET_GATEWAY:
+			return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
+			    IP_GET_GATEWAY(call));
+		case NET_IP_GET_ROUTE:
+			ERROR_PROPAGATE(data_receive((void **) &addr, &addrlen));
+			ERROR_PROPAGATE(ip_get_route_req_local(0, IP_GET_PROTOCOL(call),
+			    addr, (socklen_t) addrlen, &device_id, &header, &headerlen));
+			IPC_SET_DEVICE(answer, device_id);
+			IP_SET_HEADERLEN(answer, headerlen);
+			
+			*answer_count = 2;
+			
+			if (!ERROR_OCCURRED(data_reply(&headerlen, sizeof(headerlen))))
+				ERROR_CODE = data_reply(header, headerlen);
+			
+			free(header);
+			return ERROR_CODE;
+		case NET_IL_PACKET_SPACE:
+			ERROR_PROPAGATE(ip_packet_size_message(IPC_GET_DEVICE(call),
+			    &addrlen, &prefix, &content, &suffix));
+			IPC_SET_ADDR(answer, addrlen);
+			IPC_SET_PREFIX(answer, prefix);
+			IPC_SET_CONTENT(answer, content);
+			IPC_SET_SUFFIX(answer, suffix);
+			*answer_count = 4;
+			return EOK;
+		case NET_IL_MTU_CHANGED:
+			return ip_mtu_changed_message(IPC_GET_DEVICE(call),
+			    IPC_GET_MTU(call));
+	}
+	
+	return ENOTSUP;
+}
+
+int ip_packet_size_req_local(int ip_phone, device_id_t device_id,
+    packet_dimension_ref packet_dimension)
+{
+	if (!packet_dimension)
+		return EBADMEM;
+	
+	return ip_packet_size_message(device_id, &packet_dimension->addr_len,
+	    &packet_dimension->prefix, &packet_dimension->content,
+	    &packet_dimension->suffix);
+}
+
+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_ref netif;
+	int index;
+
+	if(!(addr_len && prefix && content && suffix)){
+		return EBADMEM;
+	}
+	*content = IP_MAX_CONTENT - IP_PREFIX;
+	fibril_rwlock_read_lock(&ip_globals.netifs_lock);
+	if(device_id < 0){
+		*addr_len = IP_ADDR;
+		*prefix = 0;
+		*suffix = 0;
+		for(index = ip_netifs_count(&ip_globals.netifs) - 1; index >= 0; -- index){
+			netif = ip_netifs_get_index(&ip_globals.netifs, index);
+			if(netif){
+				if(netif->packet_dimension.addr_len > * addr_len){
+					*addr_len = netif->packet_dimension.addr_len;
+				}
+				if(netif->packet_dimension.prefix > * prefix){
+					*prefix = netif->packet_dimension.prefix;
+				}
+				if(netif->packet_dimension.suffix > * suffix){
+					*suffix = netif->packet_dimension.suffix;
+				}
+			}
+		}
+		*prefix = * prefix + IP_PREFIX;
+		*suffix = * suffix + IP_SUFFIX;
+	}else{
+		netif = ip_netifs_find(&ip_globals.netifs, device_id);
+		if(! netif){
+			fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
+			return ENOENT;
+		}
+		*addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ? netif->packet_dimension.addr_len : IP_ADDR;
+		*prefix = netif->packet_dimension.prefix + IP_PREFIX;
+		*suffix = netif->packet_dimension.suffix + IP_SUFFIX;
+	}
+	fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
+	return EOK;
+}
+
+int ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway){
+	ip_route_ref route;
+	ip_netif_ref netif;
+	int index;
+
+	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;
+	}
+	route = (ip_route_ref) malloc(sizeof(ip_route_t));
+	if(! route){
+		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+		return ENOMEM;
+	}
+	route->address.s_addr = address.s_addr;
+	route->netmask.s_addr = netmask.s_addr;
+	route->gateway.s_addr = gateway.s_addr;
+	route->netif = netif;
+	index = ip_routes_add(&netif->routes, route);
+	if(index < 0){
+		free(route);
+	}
+	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+	return index;
+}
+
+ip_route_ref ip_find_route(in_addr_t destination){
+	int index;
+	ip_route_ref route;
+	ip_netif_ref 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;
+}
+
+ip_route_ref ip_netif_find_route(ip_netif_ref netif, in_addr_t destination){
+	int index;
+	ip_route_ref route;
+
+	if(netif){
+		// 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;
+}
+
+int ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
+{
+	ip_netif_ref 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;
+	}
+	ip_globals.gateway.address.s_addr = 0;
+	ip_globals.gateway.netmask.s_addr = 0;
+	ip_globals.gateway.gateway.s_addr = gateway.s_addr;
+	ip_globals.gateway.netif = netif;
+	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
+	return EOK;
+}
+
+packet_t ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error){
+	size_t length;
+	packet_t next;
+	packet_t new_packet;
+	int result;
+	int phone;
+
+	next = packet;
+	// check all packets
+	while(next){
+		length = packet_get_data_length(next);
+		// too long?
+		if(length > content){
+			result = ip_fragment_packet(next, content, prefix, suffix, addr_len);
+			if(result != EOK){
+				new_packet = pq_detach(next);
+				if(next == packet){
+					// the new first packet of the queue
+					packet = new_packet;
+				}
+				// fragmentation needed?
+				if(result == EPERM){
+					phone = ip_prepare_icmp_and_get_phone(error, next, NULL);
+					if(phone >= 0){
+						// fragmentation necessary ICMP
+						icmp_destination_unreachable_msg(phone, ICMP_FRAG_NEEDED, content, next);
+					}
+				}else{
+					pq_release_remote(ip_globals.net_phone, packet_get_id(next));
+				}
+				next = new_packet;
+				continue;
+			}
+		}
+		next = pq_next(next);
+	}
+	return packet;
+}
+
+int ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len){
+	ERROR_DECLARE;
+
+	packet_t new_packet;
+	ip_header_ref header;
+	ip_header_ref middle_header;
+	ip_header_ref last_header;
+	struct sockaddr * src;
+	struct sockaddr * dest;
+	socklen_t addrlen;
+	int result;
+
+	result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
+	if(result <= 0){
+		return EINVAL;
+	}
+	addrlen = (socklen_t) result;
+	if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
+		return ENOMEM;
+	}
+	// get header
+	header = (ip_header_ref) packet_get_data(packet);
+	if(! header){
+		return EINVAL;
+	}
+	// fragmentation forbidden?
+	if(header->flags &IPFLAG_DONT_FRAGMENT){
+		return EPERM;
+	}
+	// create the last fragment
+	new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, suffix, ((addrlen > addr_len) ? addrlen : addr_len));
+	if(! new_packet){
+		return ENOMEM;
+	}
+	// allocate as much as originally
+	last_header = (ip_header_ref) packet_suffix(new_packet, IP_HEADER_LENGTH(header));
+	if(! last_header){
+		return ip_release_and_return(packet, ENOMEM);
+	}
+	ip_create_last_header(last_header, header);
+	// trim the unused space
+	if(ERROR_OCCURRED(packet_trim(new_packet, 0, IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header)))){
+		return ip_release_and_return(packet, ERROR_CODE);
+	}
+	// biggest multiple of 8 lower than content
+	// TODO even fragmentation?
+	length = length &(~ 0x7);// (content / 8) * 8
+	if(ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header, last_header, ((IP_HEADER_DATA_LENGTH(header) - ((length - IP_HEADER_LENGTH(header)) &(~ 0x7))) % ((length - IP_HEADER_LENGTH(last_header)) &(~ 0x7))), src, dest, addrlen))){
+		return ip_release_and_return(packet, ERROR_CODE);
+	}
+	// mark the first as fragmented
+	header->flags |= IPFLAG_MORE_FRAGMENTS;
+	// create middle framgents
+	while(IP_TOTAL_LENGTH(header) > length){
+		new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, suffix, ((addrlen >= addr_len) ? addrlen : addr_len));
+		if(! new_packet){
+			return ENOMEM;
+		}
+		middle_header = ip_create_middle_header(new_packet, last_header);
+		if(! middle_header){
+			return ip_release_and_return(packet, ENOMEM);
+		}
+		if(ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header, middle_header, (length - IP_HEADER_LENGTH(middle_header)) &(~ 0x7), src, dest, addrlen))){
+			return ip_release_and_return(packet, ERROR_CODE);
+		}
+	}
+	// finish the first fragment
+	header->header_checksum = IP_HEADER_CHECKSUM(header);
+	return EOK;
+}
+
+int ip_fragment_packet_data(packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen){
+	ERROR_DECLARE;
+
+	void * data;
+	size_t offset;
+
+	data = packet_suffix(new_packet, length);
+	if(! data){
+		return ENOMEM;
+	}
+	memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length, length);
+	ERROR_PROPAGATE(packet_trim(packet, 0, length));
+	header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
+	new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
+	offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
+	new_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
+	new_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
+	new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
+	ERROR_PROPAGATE(packet_set_addr(new_packet, (const uint8_t *) src, (const uint8_t *) dest, addrlen));
+	return pq_insert_after(packet, new_packet);
+}
+
+ip_header_ref ip_create_middle_header(packet_t packet, ip_header_ref last){
+	ip_header_ref middle;
+
+	middle = (ip_header_ref) 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;
+}
+
+void ip_create_last_header(ip_header_ref last, ip_header_ref first){
+	ip_option_ref option;
+	size_t next;
+	size_t length;
+
+	// copy first itself
+	memcpy(last, first, sizeof(ip_header_t));
+	length = sizeof(ip_header_t);
+	next = sizeof(ip_header_t);
+	// process all ip options
+	while(next < first->header_length){
+		option = (ip_option_ref) (((uint8_t *) first) + next);
+		// skip end or noop
+		if((option->type == IPOPT_END) || (option->type == IPOPT_NOOP)){
+			++ next;
+		}else{
+			// copy if said so or skip
+			if(IPOPT_COPIED(option->type)){
+				memcpy(((uint8_t *) last) + length, ((uint8_t *) first) + next, option->length);
+				length += option->length;
+			}
+			// next option
+			next += option->length;
+		}
+	}
+	// align 4 byte boundary
+	if(length % 4){
+		bzero(((uint8_t *) last) + length, 4 - (length % 4));
+		last->header_length = length / 4 + 1;
+	}else{
+		last->header_length = length / 4;
+	}
+	last->header_checksum = 0;
+}
+
+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;
+}
+
+int ip_process_packet(device_id_t device_id, packet_t packet){
+	ERROR_DECLARE;
+
+	ip_header_ref header;
+	in_addr_t dest;
+	ip_route_ref route;
+	int phone;
+	struct sockaddr * addr;
+	struct sockaddr_in addr_in;
+//	struct sockaddr_in	addr_in6;
+	socklen_t addrlen;
+
+	header = (ip_header_ref) 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 oxceeded 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;
+/*		case IPv6VERSION:
+			addrlen = sizeof(dest_in6);
+			bzero(&dest_in6, addrlen);
+			dest_in6.sin6_family = AF_INET6;
+			memcpy(&dest_in6.sin6_addr.s6_addr,);
+			dest = (struct sockaddr *) &dest_in;
+			break;
+*/		default:
+			return ip_release_and_return(packet, EAFNOSUPPORT);
+	}
+	ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen));
+	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);
+	}else{
+		// only if routing enabled
+		if(route->netif->routing){
+			-- header->ttl;
+			return ip_send_route(packet, route->netif, route, NULL, dest, 0);
+		}else{
+			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;
+		}
+	}
+}
+
+/** Notify the IP module about the received error notification packet.
+ *
+ * @param[in] ip_phone  The IP 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.
+ * @param[in] error     The packet error reporting service. Prefixes the
+ *                      received packet.
+ *
+ * @return EOK on success.
+ *
+ */
+int ip_received_error_msg_local(int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error){
+	uint8_t * data;
+	int offset;
+	icmp_type_t type;
+	icmp_code_t code;
+	ip_netif_ref netif;
+	measured_string_t address;
+	ip_route_ref route;
+	ip_header_ref header;
+
+	switch(error){
+		case SERVICE_ICMP:
+			offset = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
+			if(offset < 0){
+				return ip_release_and_return(packet, ENOMEM);
+			}
+			data = packet_get_data(packet);
+			header = (ip_header_ref)(data + offset);
+			// destination host unreachable?
+			if((type == ICMP_DEST_UNREACH) && (code == ICMP_HOST_UNREACH)){
+				fibril_rwlock_read_lock(&ip_globals.netifs_lock);
+				netif = ip_netifs_find(&ip_globals.netifs, device_id);
+				if(netif && netif->arp){
+					route = ip_routes_get_index(&netif->routes, 0);
+					// from the same network?
+					if(route && ((route->address.s_addr &route->netmask.s_addr) == (header->destination_address &route->netmask.s_addr))){
+						// clear the ARP mapping if any
+						address.value = (char *) &header->destination_address;
+						address.length = CONVERT_SIZE(uint8_t, char, sizeof(header->destination_address));
+						arp_clear_address_req(netif->arp->phone, netif->device_id, SERVICE_IP, &address);
+					}
+				}
+				fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
+			}
+			break;
+		default:
+			return ip_release_and_return(packet, ENOTSUP);
+	}
+	return ip_deliver_local(device_id, packet, header, error);
+}
+
+int ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, services_t error){
+	ERROR_DECLARE;
+
+	ip_proto_ref 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;
+//	struct sockaddr_in	src_in6;
+//	struct sockaddr_in	dest_in6;
+	socklen_t addrlen;
+
+	if((header->flags &IPFLAG_MORE_FRAGMENTS) || IP_FRAGMENT_OFFSET(header)){
+		// TODO fragmented
+		return ENOTSUP;
+	}else{
+		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;
+/*			case IPv6VERSION:
+				addrlen = sizeof(src_in6);
+				bzero(&src_in6, addrlen);
+				src_in6.sin6_family = AF_INET6;
+				memcpy(&dest_in6, &src_in6, addrlen);
+				memcpy(&src_in6.sin6_addr.s6_addr,);
+				memcpy(&dest_in6.sin6_addr.s6_addr,);
+				src = (struct sockaddr *) &src_in;
+				dest = (struct sockaddr *) &dest_in;
+				break;
+*/			default:
+				return ip_release_and_return(packet, EAFNOSUPPORT);
+		}
+		if(ERROR_OCCURRED(packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest, addrlen))){
+			return ip_release_and_return(packet, ERROR_CODE);
+		}
+		// trim padding if present
+		if((! error) && (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))){
+			if(ERROR_OCCURRED(packet_trim(packet, 0, packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)))){
+				return ip_release_and_return(packet, ERROR_CODE);
+			}
+		}
+		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);
+			ERROR_CODE = received_msg(device_id, packet, service, error);
+		}else{
+			ERROR_CODE = tl_received_msg(proto->phone, device_id, packet, proto->service, error);
+			fibril_rwlock_read_unlock(&ip_globals.protos_lock);
+		}
+		return ERROR_CODE;
+	}
+}
+
+in_addr_t ip_get_destination(ip_header_ref header){
+	in_addr_t destination;
+
+	// TODO search set ipopt route?
+	destination.s_addr = header->destination_address;
+	return destination;
+}
+
+int ip_prepare_icmp(packet_t packet, ip_header_ref header){
+	packet_t next;
+	struct sockaddr * dest;
+	struct sockaddr_in dest_in;
+//	struct sockaddr_in	dest_in6;
+	socklen_t addrlen;
+
+	// detach the first packet and release the others
+	next = pq_detach(packet);
+	if(next){
+		pq_release_remote(ip_globals.net_phone, packet_get_id(next));
+	}
+	if(! header){
+		if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
+			return ENOMEM;
+		}
+		// get header
+		header = (ip_header_ref) packet_get_data(packet);
+		if(! header){
+			return EINVAL;
+		}
+	}
+	// only for the first fragment
+	if(IP_FRAGMENT_OFFSET(header)){
+		return EINVAL;
+	}
+	// not for the ICMP protocol
+	if(header->protocol == IPPROTO_ICMP){
+		return EPERM;
+	}
+	// set the destination address
+	switch(header->version){
+		case IPVERSION:
+			addrlen = sizeof(dest_in);
+			bzero(&dest_in, addrlen);
+			dest_in.sin_family = AF_INET;
+			memcpy(&dest_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
+			dest = (struct sockaddr *) &dest_in;
+			break;
+/*		case IPv6VERSION:
+			addrlen = sizeof(dest_in6);
+			bzero(&dest_in6, addrlen);
+			dest_in6.sin6_family = AF_INET6;
+			memcpy(&dest_in6.sin6_addr.s6_addr,);
+			dest = (struct sockaddr *) &dest_in;
+			break;
+*/		default:
+			return EAFNOSUPPORT;
+	}
+	return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
+}
+
+int ip_get_icmp_phone(void){
+	ip_proto_ref proto;
+	int phone;
+
+	fibril_rwlock_read_lock(&ip_globals.protos_lock);
+	proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
+	phone = proto ? proto->phone : ENOENT;
+	fibril_rwlock_read_unlock(&ip_globals.protos_lock);
+	return phone;
+}
+
+int ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, ip_header_ref header){
+	int phone;
+
+	phone = ip_get_icmp_phone();
+	if(error || (phone < 0) || ip_prepare_icmp(packet, header)){
+		return ip_release_and_return(packet, EINVAL);
+	}
+	return phone;
+}
+
+int ip_release_and_return(packet_t packet, int result){
+	pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
+	return result;
+}
+
+int ip_get_route_req_local(int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, void **header, size_t * headerlen){
+	struct sockaddr_in * address_in;
+//	struct sockaddr_in6 *	address_in6;
+	in_addr_t * dest;
+	in_addr_t * src;
+	ip_route_ref route;
+	ipv4_pseudo_header_ref header_in;
+
+	if(!(destination && (addrlen > 0))){
+		return EINVAL;
+	}
+	if(!(device_id && header && headerlen)){
+		return EBADMEM;
+	}
+	if((size_t) addrlen < sizeof(struct sockaddr)){
+		return EINVAL;
+	}
+	switch(destination->sa_family){
+		case AF_INET:
+			if(addrlen != sizeof(struct sockaddr_in)){
+				return EINVAL;
+			}
+			address_in = (struct sockaddr_in *) destination;
+			dest = &address_in->sin_addr;
+			if(! dest->s_addr){
+				dest->s_addr = IPV4_LOCALHOST_ADDRESS;
+			}
+			break;
+		// TODO IPv6
+/*		case AF_INET6:
+			if(addrlen != sizeof(struct sockaddr_in6)){
+				return EINVAL;
+			}
+			address_in6 = (struct sockaddr_in6 *) dest;
+			address_in6.sin6_addr.s6_addr;
+*/		default:
+			return EAFNOSUPPORT;
+	}
+	fibril_rwlock_read_lock(&ip_globals.lock);
+	route = ip_find_route(*dest);
+	// if the local host is the destination
+	if(route && (route->address.s_addr == dest->s_addr)
+		&& (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
+		// find the loopback device to deliver
+		dest->s_addr = IPV4_LOCALHOST_ADDRESS;
+		route = ip_find_route(*dest);
+	}
+	if(!(route && route->netif)){
+		fibril_rwlock_read_unlock(&ip_globals.lock);
+		return ENOENT;
+	}
+	*device_id = route->netif->device_id;
+	src = ip_netif_address(route->netif);
+	fibril_rwlock_read_unlock(&ip_globals.lock);
+	*headerlen = sizeof(*header_in);
+	header_in = (ipv4_pseudo_header_ref) malloc(*headerlen);
+	if(! header_in){
+		return ENOMEM;
+	}
+	bzero(header_in, * headerlen);
+	header_in->destination_address = dest->s_addr;
+	header_in->source_address = src->s_addr;
+	header_in->protocol = protocol;
+	header_in->data_length = 0;
+	*header = header_in;
+	return EOK;
+}
+
+/** Default thread for new connections.
+ *
+ *  @param[in] iid The initial message identifier.
+ *  @param[in] icall The initial message call structure.
+ *
+ */
+static void il_client_connection(ipc_callid_t iid, ipc_call_t * icall)
+{
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0(iid, EOK);
+	
+	while(true) {
+		ipc_call_t answer;
+		int answer_count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &answer_count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = il_module_message_standalone(callid, &call, &answer,
+		    &answer_count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, answer_count);
+	}
+}
+
+/** Starts the module.
+ *
+ *  @param argc The count of the command line arguments. Ignored parameter.
+ *  @param argv The command line parameters. Ignored parameter.
+ *
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module start function.
+ *
+ */
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	/* Start the module */
+	if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
+		return ERROR_CODE;
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/ip.h
===================================================================
--- uspace/srv/net/il/ip/ip.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/ip/ip.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ip
+ *  @{
+ */
+
+/** @file
+ *  IP module.
+ */
+
+#ifndef __NET_IP_H__
+#define __NET_IP_H__
+
+#include <fibril_synch.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_device.h>
+#include <inet.h>
+#include <ip_interface.h>
+#include <adt/int_map.h>
+#include <adt/generic_field.h>
+#include <adt/module_map.h>
+
+/** Type definition of the IP global data.
+ *  @see ip_globals
+ */
+typedef struct ip_globals	ip_globals_t;
+
+/** Type definition of the IP network interface specific data.
+ *  @see ip_netif
+ */
+typedef struct ip_netif	ip_netif_t;
+
+/** Type definition of the IP network interface specific data pointer.
+ *  @see ip_netif
+ */
+typedef ip_netif_t *	ip_netif_ref;
+
+/** Type definition of the IP protocol specific data.
+ *  @see ip_proto
+ */
+typedef struct ip_proto	ip_proto_t;
+
+/** Type definition of the IP protocol specific data pointer.
+ *  @see ip_proto
+ */
+typedef ip_proto_t *	ip_proto_ref;
+
+/** Type definition of the IP route specific data.
+ *  @see ip_route
+ */
+typedef struct ip_route	ip_route_t;
+
+/** Type definition of the IP route specific data pointer.
+ *  @see ip_route
+ */
+typedef ip_route_t *	ip_route_ref;
+
+/** IP network interfaces.
+ *  Maps devices to the IP network interface specific data.
+ *  @see device.h
+ */
+DEVICE_MAP_DECLARE(ip_netifs, ip_netif_t)
+
+/** IP registered protocols.
+ *  Maps protocols to the IP protocol specific data.
+ *  @see int_map.h
+ */
+INT_MAP_DECLARE(ip_protos, ip_proto_t)
+
+/** IP routing table.
+ *  @see generic_field.h
+ */
+GENERIC_FIELD_DECLARE(ip_routes, ip_route_t)
+
+/** IP network interface specific data.
+ */
+struct	ip_netif{
+	/** ARP module.
+	 *  Assigned if using ARP.
+	 */
+	module_ref arp;
+	/** Broadcast address.
+	 */
+	in_addr_t broadcast;
+	/** Device identifier.
+	 */
+	device_id_t device_id;
+	/** Indicates whether using DHCP.
+	 */
+	int dhcp;
+	/** IP version.
+	 */
+	int ipv;
+	/** Packet dimension.
+	 */
+	packet_dimension_t packet_dimension;
+	/** Netif module phone.
+	 */
+	int phone;
+	/** Routing table.
+	 */
+	ip_routes_t routes;
+	/** Indicates whether IP routing is enabled.
+	 */
+	int routing;
+	/** Netif module service.
+	 */
+	services_t service;
+	/** Device state.
+	 */
+	device_state_t state;
+};
+
+/** IP protocol specific data.
+ */
+struct ip_proto{
+	/** Protocol module phone.
+	 */
+	int phone;
+	/** Protocol number.
+	 */
+	int protocol;
+	/** Protocol packet receiving function.
+	 */
+	tl_received_msg_t received_msg;
+	/** Protocol module service.
+	 */
+	services_t service;
+};
+
+/** IP route specific data.
+ */
+struct ip_route{
+	/** Target address.
+	 */
+	in_addr_t address;
+	/** Gateway.
+	 */
+	in_addr_t gateway;
+	/** Parent netif.
+	 */
+	ip_netif_ref netif;
+	/** Target network mask.
+	 */
+	in_addr_t netmask;
+};
+
+/** 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;
+	/** Safety lock.
+	 */
+	fibril_rwlock_t lock;
+	/** Known support modules.
+	 */
+	modules_t modules;
+	/** Networking module phone.
+	 */
+	int net_phone;
+	/** Registered network interfaces.
+	 */
+	ip_netifs_t netifs;
+	/** Netifs safeyt lock.
+	 */
+	fibril_rwlock_t netifs_lock;
+	/** Packet counter.
+	 */
+	uint16_t packet_counter;
+	/** Registered protocols.
+	 */
+	ip_protos_t protos;
+	/** Protocols safety lock.
+	 */
+	fibril_rwlock_t protos_lock;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/ip_module.c
===================================================================
--- uspace/srv/net/il/ip/ip_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/ip/ip_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,98 @@
+/*
+ * 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 <net_err.h>
+#include <net_modules.h>
+#include <net_interface.h>
+#include <packet/packet.h>
+#include <il_local.h>
+
+#include "ip.h"
+#include "ip_module.h"
+
+/** IP module global data.
+ */
+extern ip_globals_t ip_globals;
+
+/** Processes the IP 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the ip_message() function.
+ */
+int il_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	return ip_message_standalone(callid, call, answer, answer_count);
+}
+
+/** Starts the IP 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.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the ip_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int il_module_start_standalone(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+	
+	async_set_client_connection(client_connection);
+	ip_globals.net_phone = net_connect_module(SERVICE_NETWORKING);
+	ERROR_PROPAGATE(pm_init());
+	
+	ipcarg_t phonehash;
+	if (ERROR_OCCURRED(ip_initialize(client_connection))
+	    || ERROR_OCCURRED(REGISTER_ME(SERVICE_IP, &phonehash))) {
+		pm_destroy();
+		return ERROR_CODE;
+	}
+	
+	async_manager();
+	
+	pm_destroy();
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/ip_module.h
===================================================================
--- uspace/srv/net/il/ip/ip_module.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/il/ip/ip_module.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,66 @@
+/*
+ * 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>
+
+/** Initializes the IP module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int ip_initialize(async_client_conn_t client_connection);
+
+/** Processes the IP 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see ip_interface.h
+ *  @see il_interface.h
+ *  @see IS_NET_IP_MESSAGE()
+ */
+int ip_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/net/Makefile
===================================================================
--- uspace/srv/net/net/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/net/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -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 $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+
+COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
+CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
+
+-include $(COMMON_MAKEFILE)
+-include $(CONFIG_MAKEFILE)
+
+BINARY = net
+
+SOURCES = \
+	net.c \
+	net_standalone.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/net/net.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,685 @@
+/*
+ * 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 net
+ * @{
+ */
+
+/** @file
+ * Networking subsystem central module implementation.
+ *
+ */
+
+#include <async.h>
+#include <ctype.h>
+#include <ddi.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <str.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_messages.h>
+#include <net_modules.h>
+#include <adt/char_map.h>
+#include <adt/generic_char_map.h>
+#include <adt/measured_strings.h>
+#include <adt/module_map.h>
+#include <packet/packet.h>
+#include <il_messages.h>
+#include <netif_remote.h>
+#include <net_device.h>
+#include <nil_interface.h>
+#include <net_interface.h>
+#include <ip_interface.h>
+#include <net_net_messages.h>
+
+#include "net.h"
+
+/** Networking module name.
+ *
+ */
+#define NAME  "net"
+
+/** File read buffer size.
+ *
+ */
+#define BUFFER_SIZE  256
+
+/** Networking module global data.
+ *
+ */
+net_globals_t net_globals;
+
+GENERIC_CHAR_MAP_IMPLEMENT(measured_strings, measured_string_t);
+DEVICE_MAP_IMPLEMENT(netifs, netif_t);
+
+/** Add the configured setting to the configuration map.
+ *
+ * @param[in] configuration The configuration map.
+ * @param[in] name          The setting name.
+ * @param[in] value         The setting value.
+ *
+ * @returns EOK on success.
+ * @returns ENOMEM if there is not enough memory left.
+ *
+ */
+int add_configuration(measured_strings_ref configuration, const char *name,
+    const char *value)
+{
+	ERROR_DECLARE;
+	
+	measured_string_ref setting =
+	    measured_string_create_bulk(value, 0);
+	
+	if (!setting)
+		return ENOMEM;
+	
+	/* Add the configuration setting */
+	if (ERROR_OCCURRED(measured_strings_add(configuration, name, 0, setting))) {
+		free(setting);
+		return ERROR_CODE;
+	}
+	
+	return EOK;
+}
+
+/** Generate new system-unique device identifier.
+ *
+ * @returns The system-unique devic identifier.
+ *
+ */
+static device_id_t generate_new_device_id(void)
+{
+	return device_assign_devno();
+}
+
+static int parse_line(measured_strings_ref configuration, char *line)
+{
+	ERROR_DECLARE;
+	
+	/* From the beginning */
+	char *name = line;
+	
+	/* Skip comments and blank lines */
+	if ((*name == '#') || (*name == '\0'))
+		return EOK;
+	
+	/* Skip spaces */
+	while (isspace(*name))
+		name++;
+	
+	/* Remember the name start */
+	char *value = name;
+	
+	/* Skip the name */
+	while (isalnum(*value) || (*value == '_'))
+		value++;
+	
+	if (*value == '=') {
+		/* Terminate the name */
+		*value = '\0';
+	} else {
+		/* Terminate the name */
+		*value = '\0';
+		
+		/* Skip until '=' */
+		value++;
+		while ((*value) && (*value != '='))
+			value++;
+		
+		/* Not found? */
+		if (*value != '=')
+			return EINVAL;
+	}
+	
+	value++;
+	
+	/* Skip spaces */
+	while (isspace(*value))
+		value++;
+	
+	/* Create a bulk measured string till the end */
+	measured_string_ref setting =
+	    measured_string_create_bulk(value, 0);
+	if (!setting)
+		return ENOMEM;
+	
+	/* Add the configuration setting */
+	if (ERROR_OCCURRED(measured_strings_add(configuration, name, 0, setting))) {
+		free(setting);
+		return ERROR_CODE;
+	}
+	
+	return EOK;
+}
+
+static int read_configuration_file(const char *directory, const char *filename,
+    measured_strings_ref configuration)
+{
+	ERROR_DECLARE;
+	
+	printf("%s: Reading configuration file %s/%s\n", NAME, directory, filename);
+	
+	/* Construct the full filename */
+	char line[BUFFER_SIZE];
+	if (snprintf(line, BUFFER_SIZE, "%s/%s", directory, filename) > BUFFER_SIZE)
+		return EOVERFLOW;
+	
+	/* Open the file */
+	FILE *cfg = fopen(line, "r");
+	if (!cfg)
+		return ENOENT;
+	
+	/*
+	 * Read the configuration line by line
+	 * until an error or the end of file
+	 */
+	unsigned int line_number = 0;
+	size_t index = 0;
+	while ((!ferror(cfg)) && (!feof(cfg))) {
+		int read = fgetc(cfg);
+		if ((read > 0) && (read != '\n') && (read != '\r')) {
+			if (index >= BUFFER_SIZE) {
+				line[BUFFER_SIZE - 1] = '\0';
+				fprintf(stderr, "%s: Configuration line %u too long: %s\n",
+				    NAME, line_number, line);
+				
+				/* No space left in the line buffer */
+				return EOVERFLOW;
+			} else {
+				/* Append the character */
+				line[index] = (char) read;
+				index++;
+			}
+		} else {
+			/* On error or new line */
+			line[index] = '\0';
+			line_number++;
+			if (ERROR_OCCURRED(parse_line(configuration, line)))
+				fprintf(stderr, "%s: Configuration error on line %u: %s\n",
+				    NAME, line_number, line);
+			
+			index = 0;
+		}
+	}
+	
+	fclose(cfg);
+	return EOK;
+}
+
+/** Read the network interface specific configuration.
+ *
+ * @param[in]     name  The network interface name.
+ * @param[in,out] netif The network interface structure.
+ *
+ * @returns EOK on success.
+ * @returns Other error codes as defined for the add_configuration() function.
+ *
+ */
+static int read_netif_configuration(const char *name, netif_t *netif)
+{
+	return read_configuration_file(CONF_DIR, name, &netif->configuration);
+}
+
+/** Read the networking subsystem global configuration.
+ *
+ * @returns EOK on success.
+ * @returns Other error codes as defined for the add_configuration() function.
+ *
+ */
+static int read_configuration(void)
+{
+	return read_configuration_file(CONF_DIR, CONF_GENERAL_FILE,
+	    &net_globals.configuration);
+}
+
+/** Initialize the networking module.
+ *
+ * @param[in] client_connection The client connection processing
+ *                              function. The module skeleton propagates
+ *                              its own one.
+ *
+ * @returns EOK on success.
+ * @returns ENOMEM if there is not enough memory left.
+ *
+ */
+static int net_initialize(async_client_conn_t client_connection)
+{
+	ERROR_DECLARE;
+	
+	netifs_initialize(&net_globals.netifs);
+	char_map_initialize(&net_globals.netif_names);
+	modules_initialize(&net_globals.modules);
+	measured_strings_initialize(&net_globals.configuration);
+	
+	// TODO: dynamic configuration
+	ERROR_PROPAGATE(read_configuration());
+	
+	ERROR_PROPAGATE(add_module(NULL, &net_globals.modules,
+	    LO_NAME, LO_FILENAME, SERVICE_LO, 0, connect_to_service));
+	ERROR_PROPAGATE(add_module(NULL, &net_globals.modules,
+	    DP8390_NAME, DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service));
+	ERROR_PROPAGATE(add_module(NULL, &net_globals.modules,
+	    ETHERNET_NAME, ETHERNET_FILENAME, SERVICE_ETHERNET, 0,
+	    connect_to_service));
+	ERROR_PROPAGATE(add_module(NULL, &net_globals.modules,
+	    NILDUMMY_NAME, NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0,
+	    connect_to_service));
+	
+	/* Build specific initialization */
+	return net_initialize_build(client_connection);
+}
+
+/** Start the networking 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.
+ *
+ * @returns EOK on successful module termination.
+ * @returns Other error codes as defined for the net_initialize() function.
+ * @returns Other error codes as defined for the REGISTER_ME() macro function.
+ *
+ */
+static int net_module_start(async_client_conn_t client_connection)
+{
+	ERROR_DECLARE;
+	
+	async_set_client_connection(client_connection);
+	ERROR_PROPAGATE(pm_init());
+	
+	ipcarg_t phonehash;
+	
+	if (ERROR_OCCURRED(net_initialize(client_connection))
+	    || ERROR_OCCURRED(REGISTER_ME(SERVICE_NETWORKING, &phonehash))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+	
+	async_manager();
+	
+	pm_destroy();
+	return EOK;
+}
+
+/** Return the configured values.
+ *
+ * The network interface configuration is searched first.
+ &
+ * @param[in]  netif_conf    The network interface configuration setting.
+ * @param[out] configuration The found configured values.
+ * @param[in]  count         The desired settings count.
+ * @param[out] data          The found configuration settings data.
+ *
+ * @returns EOK.
+ *
+ */
+static int net_get_conf(measured_strings_ref netif_conf,
+    measured_string_ref configuration, size_t count, char **data)
+{
+	if (data)
+		*data = NULL;
+	
+	size_t index;
+	for (index = 0; index < count; index++) {
+		measured_string_ref setting =
+		    measured_strings_find(netif_conf, configuration[index].value, 0);
+		if (!setting)
+			setting = measured_strings_find(&net_globals.configuration,
+			    configuration[index].value, 0);
+		
+		if (setting) {
+			configuration[index].length = setting->length;
+			configuration[index].value = setting->value;
+		} else {
+			configuration[index].length = 0;
+			configuration[index].value = NULL;
+		}
+	}
+	
+	return EOK;
+}
+
+int net_get_conf_req(int net_phone, measured_string_ref *configuration,
+    size_t count, char **data)
+{
+	if (!(configuration && (count > 0)))
+		return EINVAL;
+	
+	return net_get_conf(NULL, *configuration, count, data);
+}
+
+int net_get_device_conf_req(int net_phone, device_id_t device_id,
+    measured_string_ref *configuration, size_t count, char **data)
+{
+	if ((!configuration) || (count == 0))
+		return EINVAL;
+
+	netif_t *netif = netifs_find(&net_globals.netifs, device_id);
+	if (netif)
+		return net_get_conf(&netif->configuration, *configuration, count, data);
+	else
+		return net_get_conf(NULL, *configuration, count, data);
+}
+
+void net_free_settings(measured_string_ref settings, char *data)
+{
+}
+
+/** Start the network interface according to its configuration.
+ *
+ * Register the network interface with the subsystem modules.
+ * Start the needed subsystem modules.
+ *
+ * @param[in] netif The network interface specific data.
+ *
+ * @returns EOK on success.
+ * @returns EINVAL if there are some settings missing.
+ * @returns ENOENT if the internet protocol module is not known.
+ * @returns Other error codes as defined for the netif_probe_req() function.
+ * @returns Other error codes as defined for the nil_device_req() function.
+ * @returns Other error codes as defined for the needed internet layer
+ *          registering function.
+ *
+ */
+static int start_device(netif_t *netif)
+{
+	ERROR_DECLARE;
+	
+	/* Mandatory netif */
+	measured_string_ref setting =
+	    measured_strings_find(&netif->configuration, CONF_NETIF, 0);
+	
+	netif->driver = get_running_module(&net_globals.modules, setting->value);
+	if (!netif->driver) {
+		fprintf(stderr, "%s: Failed to start network interface driver '%s'\n",
+		    NAME, setting->value);
+		return EINVAL;
+	}
+	
+	/* Optional network interface layer */
+	setting = measured_strings_find(&netif->configuration, CONF_NIL, 0);
+	if (setting) {
+		netif->nil = get_running_module(&net_globals.modules, setting->value);
+		if (!netif->nil) {
+			fprintf(stderr, "%s: Failed to start network interface layer '%s'\n",
+			    NAME, setting->value);
+			return EINVAL;
+		}
+	} else
+		netif->nil = NULL;
+	
+	/* Mandatory internet layer */
+	setting = measured_strings_find(&netif->configuration, CONF_IL, 0);
+	netif->il = get_running_module(&net_globals.modules, setting->value);
+	if (!netif->il) {
+		fprintf(stderr, "%s: Failed to start internet layer '%s'\n",
+		    NAME, setting->value);
+		return EINVAL;
+	}
+	
+	/* Hardware configuration */
+	setting = measured_strings_find(&netif->configuration, CONF_IRQ, 0);
+	int irq = setting ? strtol(setting->value, NULL, 10) : 0;
+	
+	setting = measured_strings_find(&netif->configuration, CONF_IO, 0);
+	int io = setting ? strtol(setting->value, NULL, 16) : 0;
+	
+	ERROR_PROPAGATE(netif_probe_req_remote(netif->driver->phone, netif->id, irq, io));
+	
+	/* Network interface layer startup */
+	services_t internet_service;
+	if (netif->nil) {
+		setting = measured_strings_find(&netif->configuration, CONF_MTU, 0);
+		if (!setting)
+			setting = measured_strings_find(&net_globals.configuration,
+			    CONF_MTU, 0);
+		
+		int mtu = setting ? strtol(setting->value, NULL, 10) : 0;
+		
+		ERROR_PROPAGATE(nil_device_req(netif->nil->phone, netif->id, mtu,
+		    netif->driver->service));
+		
+		internet_service = netif->nil->service;
+	} else
+		internet_service = netif->driver->service;
+	
+	/* Inter-network layer startup */
+	switch (netif->il->service) {
+		case SERVICE_IP:
+			ERROR_PROPAGATE(ip_device_req(netif->il->phone, netif->id,
+			    internet_service));
+			break;
+		default:
+			return ENOENT;
+	}
+	
+	ERROR_PROPAGATE(netif_start_req_remote(netif->driver->phone, netif->id));
+	return EOK;
+}
+
+/** Read the configuration and start all network interfaces.
+ *
+ * @returns EOK on success.
+ * @returns EXDEV if there is no available system-unique device identifier.
+ * @returns EINVAL if any of the network interface names are not configured.
+ * @returns ENOMEM if there is not enough memory left.
+ * @returns Other error codes as defined for the read_configuration()
+ *          function.
+ * @returns Other error codes as defined for the read_netif_configuration()
+ *          function.
+ * @returns Other error codes as defined for the start_device() function.
+ *
+ */
+static int startup(void)
+{
+	ERROR_DECLARE;
+	
+	const char *conf_files[] = {"lo", "ne2k"};
+	size_t count = sizeof(conf_files) / sizeof(char *);
+	
+	size_t i;
+	for (i = 0; i < count; i++) {
+		netif_t *netif = (netif_t *) malloc(sizeof(netif_t));
+		if (!netif)
+			return ENOMEM;
+		
+		netif->id = generate_new_device_id();
+		if (!netif->id)
+			return EXDEV;
+		
+		ERROR_PROPAGATE(measured_strings_initialize(&netif->configuration));
+		
+		/* Read configuration files */
+		if (ERROR_OCCURRED(read_netif_configuration(conf_files[i], netif))) {
+			measured_strings_destroy(&netif->configuration);
+			free(netif);
+			return ERROR_CODE;
+		}
+		
+		/* Mandatory name */
+		measured_string_ref setting =
+		    measured_strings_find(&netif->configuration, CONF_NAME, 0);
+		if (!setting) {
+			fprintf(stderr, "%s: Network interface name is missing\n", NAME);
+			measured_strings_destroy(&netif->configuration);
+			free(netif);
+			return EINVAL;
+		}
+		netif->name = setting->value;
+		
+		/* Add to the netifs map */
+		int index = netifs_add(&net_globals.netifs, netif->id, netif);
+		if (index < 0) {
+			measured_strings_destroy(&netif->configuration);
+			free(netif);
+			return index;
+		}
+		
+		/*
+		 * Add to the netif names map and start network interfaces
+		 * and needed modules.
+		 */
+		if ((ERROR_OCCURRED(char_map_add(&net_globals.netif_names,
+		    netif->name, 0, index))) || (ERROR_OCCURRED(start_device(netif)))) {
+			measured_strings_destroy(&netif->configuration);
+			netifs_exclude_index(&net_globals.netifs, index);
+			return ERROR_CODE;
+		}
+		
+		/* Increment modules' usage */
+		netif->driver->usage++;
+		if (netif->nil)
+			netif->nil->usage++;
+		netif->il->usage++;
+		
+		printf("%s: Network interface started (name: %s, id: %d, driver: %s, "
+		    "nil: %s, il: %s)\n", NAME, netif->name, netif->id,
+		    netif->driver->name,  netif->nil ? netif->nil->name : "[none]",
+		    netif->il->name);
+	}
+	
+	return EOK;
+}
+
+/** Process the networking 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.
+ *
+ * @returns EOK on success.
+ * @returns ENOTSUP if the message is not known.
+ *
+ * @see net_interface.h
+ * @see IS_NET_NET_MESSAGE()
+ *
+ */
+int net_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
+    int *answer_count)
+{
+	ERROR_DECLARE;
+	
+	measured_string_ref strings;
+	char *data;
+	
+	*answer_count = 0;
+	switch (IPC_GET_METHOD(*call)) {
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_NET_GET_DEVICE_CONF:
+			ERROR_PROPAGATE(measured_strings_receive(&strings, &data,
+			    IPC_GET_COUNT(call)));
+			net_get_device_conf_req(0, IPC_GET_DEVICE(call), &strings,
+			    IPC_GET_COUNT(call), NULL);
+			
+			/* Strings should not contain received data anymore */
+			free(data);
+			
+			ERROR_CODE = measured_strings_reply(strings, IPC_GET_COUNT(call));
+			free(strings);
+			return ERROR_CODE;
+		case NET_NET_GET_CONF:
+			ERROR_PROPAGATE(measured_strings_receive(&strings, &data,
+			    IPC_GET_COUNT(call)));
+			net_get_conf_req(0, &strings, IPC_GET_COUNT(call), NULL);
+			
+			/* Strings should not contain received data anymore */
+			free(data);
+			
+			ERROR_CODE = measured_strings_reply(strings, IPC_GET_COUNT(call));
+			free(strings);
+			return ERROR_CODE;
+		case NET_NET_STARTUP:
+			return startup();
+	}
+	return ENOTSUP;
+}
+
+/** Default thread for new connections.
+ *
+ * @param[in] iid The initial message identifier.
+ * @param[in] icall The initial message call structure.
+ *
+ */
+static void net_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) {
+		/* Clear the answer structure */
+		ipc_call_t answer;
+		int answer_count;
+		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 = net_module_message(callid, &call, &answer, &answer_count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, answer_count);
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	if (ERROR_OCCURRED(net_module_start(net_client_connection))) {
+		fprintf(stderr, "%s: net_module_start error %i\n", NAME, ERROR_CODE);
+		return ERROR_CODE;
+	}
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/net/net.h
===================================================================
--- uspace/srv/net/net/net.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/net/net.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,143 @@
+/*
+ * 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 net
+ * @{
+ */
+
+/** @file
+ * Networking subsystem central module.
+ *
+ */
+
+#ifndef __NET_NET_H__
+#define __NET_NET_H__
+
+#include <ipc/ipc.h>
+
+#include <net_device.h>
+#include <adt/char_map.h>
+#include <adt/generic_char_map.h>
+#include <adt/measured_strings.h>
+#include <adt/module_map.h>
+#include <packet/packet.h>
+
+/** @name Modules definitions
+ * @{
+ */
+
+#define DP8390_FILENAME  "/srv/dp8390"
+#define DP8390_NAME      "dp8390"
+
+#define ETHERNET_FILENAME  "/srv/eth"
+#define ETHERNET_NAME      "eth"
+
+#define IP_FILENAME  "/srv/ip"
+#define IP_NAME      "ip"
+
+#define LO_FILENAME  "/srv/lo"
+#define LO_NAME      "lo"
+
+#define NILDUMMY_FILENAME  "/srv/nildummy"
+#define NILDUMMY_NAME      "nildummy"
+
+/** @}
+ */
+
+/** @name Configuration setting names definitions
+ * @{
+ */
+
+#define CONF_IL     "IL"     /**< Internet protocol module name configuration label. */
+#define CONF_IO     "IO"     /**< Device input/output address configuration label. */
+#define CONF_IRQ    "IRQ"    /**< Interrupt number configuration label. */
+#define CONF_MTU    "MTU"    /**< Maximum transmission unit configuration label. */
+#define CONF_NAME   "NAME"   /**< Network interface name configuration label. */
+#define CONF_NETIF  "NETIF"  /**< Network interface module name configuration label. */
+#define CONF_NIL    "NIL"    /**< Network interface layer module name configuration label. */
+
+/** @}
+ */
+
+#define CONF_DIR           "/cfg/net"  /**< Configuration directory. */
+#define CONF_GENERAL_FILE  "general"   /**< General configuration file. */
+
+/** Configuration settings.
+ *
+ * Maps setting names to the values.
+ * @see generic_char_map.h
+ *
+ */
+GENERIC_CHAR_MAP_DECLARE(measured_strings, measured_string_t);
+
+/** Present network interface device.
+ *
+ */
+typedef struct {
+	measured_strings_t configuration;  /**< Configuration. */
+	
+	/** Serving network interface driver module index. */
+	module_ref driver;
+	
+	device_id_t id;  /**< System-unique network interface identifier. */
+	module_ref il;   /**< Serving internet layer module index. */
+	char *name;      /**< System-unique network interface name. */
+	module_ref nil;  /**< Serving link layer module index. */
+} netif_t;
+
+/** Present network interfaces.
+ *
+ * Maps devices to the networking device specific data.
+ * @see device.h
+ *
+ */
+DEVICE_MAP_DECLARE(netifs, netif_t);
+
+/** Networking module global data.
+ *
+ */
+typedef struct {
+	measured_strings_t configuration;  /**< Global configuration. */
+	modules_t modules;                 /**< Available modules. */
+	
+	/** Network interface structure indices by names. */
+	char_map_t netif_names;
+	
+	/** Present network interfaces. */
+	netifs_t netifs;
+} net_globals_t;
+
+extern int add_configuration(measured_strings_ref, const char *, const char *);
+extern int net_module_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, int *);
+extern int net_initialize_build(async_client_conn_t);
+extern int net_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, int *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/net/net_bundle.c
===================================================================
--- uspace/srv/net/net/net_bundle.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/net/net_bundle.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,135 @@
+/*
+ * 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 net
+ *  @{
+ */
+
+/** @file
+ *  Wrapper for the bundled networking and TCP/IP stact modules.
+ *  Distributes messages and initializes all module parts.
+ */
+
+#include <str.h>
+
+#include <ipc/ipc.h>
+
+#include "../messages.h"
+
+#include "../include/ip_interface.h"
+
+#include "../structures/measured_strings.h"
+#include "../structures/module_map.h"
+#include "../structures/packet/packet_server.h"
+
+#include "../il/arp/arp_module.h"
+#include "../il/ip/ip_module.h"
+#include "../tl/icmp/icmp_module.h"
+#include "../tl/udp/udp_module.h"
+#include "../tl/tcp/tcp_module.h"
+
+#include "net.h"
+
+/** Networking module global data.
+ */
+extern net_globals_t	net_globals;
+
+/** Initializes the networking module for the chosen subsystem build type.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int net_initialize_build(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+
+	ipcarg_t phonehash;
+
+	ERROR_PROPAGATE(REGISTER_ME(SERVICE_IP, &phonehash));
+	ERROR_PROPAGATE(add_module(NULL, &net_globals.modules, IP_NAME, IP_FILENAME, SERVICE_IP, task_get_id(), ip_connect_module));
+	ERROR_PROPAGATE(ip_initialize(client_connection));
+	ERROR_PROPAGATE(REGISTER_ME(SERVICE_ARP, &phonehash));
+	ERROR_PROPAGATE(arp_initialize(client_connection));
+	ERROR_PROPAGATE(REGISTER_ME(SERVICE_ICMP, &phonehash));
+	ERROR_PROPAGATE(icmp_initialize(client_connection));
+	ERROR_PROPAGATE(REGISTER_ME(SERVICE_UDP, &phonehash));
+	ERROR_PROPAGATE(udp_initialize(client_connection));
+	ERROR_PROPAGATE(REGISTER_ME(SERVICE_TCP, &phonehash));
+	ERROR_PROPAGATE(tcp_initialize(client_connection));
+	return EOK;
+}
+
+/** Processes the module message.
+ *  Distributes the message to the right bundled module.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for each bundled module message function.
+ */
+int net_module_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	if((IPC_GET_METHOD(*call) == IPC_M_CONNECT_TO_ME)
+		|| IS_NET_IL_MESSAGE(call)
+		|| IS_NET_TL_MESSAGE(call)
+		|| IS_NET_SOCKET_MESSAGE(call)){
+		switch(IPC_GET_TARGET(call)){
+			case SERVICE_IP:
+				return ip_message(callid, call, answer, answer_count);
+			case SERVICE_ARP:
+				return arp_message(callid, call, answer, answer_count);
+			case SERVICE_ICMP:
+				return icmp_message(callid, call, answer, answer_count);
+			case SERVICE_UDP:
+				return udp_message(callid, call, answer, answer_count);
+			case SERVICE_TCP:
+				return tcp_message(callid, call, answer, answer_count);
+			default:
+				return EINVAL;
+		}
+	}else if(IS_NET_IP_MESSAGE(call)){
+		return ip_message(callid, call, answer, answer_count);
+	}else if(IS_NET_ARP_MESSAGE(call)){
+		return arp_message(callid, call, answer, answer_count);
+	}else if(IS_NET_ICMP_MESSAGE(call)){
+		return icmp_message(callid, call, answer, answer_count);
+	}else if(IS_NET_UDP_MESSAGE(call)){
+		return udp_message(callid, call, answer, answer_count);
+	}else if(IS_NET_TCP_MESSAGE(call)){
+		return tcp_message(callid, call, answer, answer_count);
+	}else{
+		if(IS_NET_PACKET_MESSAGE(call)){
+			return packet_server_message(callid, call, answer, answer_count);
+		}else{
+			return net_message(callid, call, answer, answer_count);
+		}
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/net/net/net_standalone.c
===================================================================
--- uspace/srv/net/net/net_standalone.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/net/net_standalone.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,110 @@
+/*
+ * 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 net
+ *  @{
+ */
+
+/** @file
+ *  Wrapper for the standalone networking module.
+ */
+
+#include <str.h>
+
+#include <ipc/ipc.h>
+
+#include <net_messages.h>
+#include <ip_interface.h>
+#include <adt/measured_strings.h>
+#include <adt/module_map.h>
+#include <packet/packet_server.h>
+
+#include "net.h"
+
+/** Networking module global data.
+ */
+extern net_globals_t net_globals;
+
+/** Initialize the networking module for the chosen subsystem build type.
+ *
+ *  @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 net_initialize_build(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+	
+	task_id_t task_id = spawn("/srv/ip");
+	if (!task_id)
+		return EINVAL;
+	
+	ERROR_PROPAGATE(add_module(NULL, &net_globals.modules, IP_NAME,
+	    IP_FILENAME, SERVICE_IP, task_id, ip_connect_module));
+	
+	if (!spawn("/srv/icmp"))
+		return EINVAL;
+	
+	if (!spawn("/srv/udp"))
+		return EINVAL;
+	
+	if (!spawn("/srv/tcp"))
+		return EINVAL;
+	
+	return EOK;
+}
+
+/** Process the module message.
+ *
+ * Distribute the message to the right module.
+ *
+ * @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 bundled module
+ *         message function.
+ *
+ */
+int net_module_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, int *answer_count)
+{
+	if (IS_NET_PACKET_MESSAGE(call))
+		return packet_server_message(callid, call, answer, answer_count);
+	
+	return net_message(callid, call, answer, answer_count);
+}
+
+/** @}
+ */
Index: uspace/srv/net/netif/lo/Makefile
===================================================================
--- uspace/srv/net/netif/lo/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/netif/lo/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,50 @@
+#
+# 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 $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+
+COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
+CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
+
+-include $(COMMON_MAKEFILE)
+-include $(CONFIG_MAKEFILE)
+
+ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
+	LIBS += $(USPACE_PREFIX)/srv/net/nil/nildummy/libnildummy.a
+endif
+
+BINARY = lo
+
+SOURCES = \
+	lo.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/netif/lo/lo.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,264 @@
+/*
+ * 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 lo
+ *  @{
+ */
+
+/** @file
+ *  Loopback network interface implementation.
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <stdio.h>
+#include <str.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_messages.h>
+#include <net_modules.h>
+#include <adt/measured_strings.h>
+#include <packet/packet_client.h>
+#include <net_device.h>
+#include <nil_interface.h>
+#include <nil_messages.h>
+#include <netif_interface.h>
+#include <netif_local.h>
+
+/** Default hardware address.
+ */
+#define DEFAULT_ADDR		"\0\0\0\0\0\0"
+
+/** Default address length.
+ */
+#define DEFAULT_ADDR_LEN	(sizeof(DEFAULT_ADDR) / sizeof(char))
+
+/** Loopback module name.
+ */
+#define NAME  "lo"
+
+/** Network interface global data.
+ */
+netif_globals_t	netif_globals;
+
+/** Changes the loopback state.
+ *  @param[in] device The device structure.
+ *  @param[in] state The new device state.
+ *  @returns The new state if changed.
+ *  @returns EOK otherwise.
+ */
+int change_state_message(netif_device_t * device, device_state_t state);
+
+/** Creates and returns the loopback network interface structure.
+ *  @param[in] device_id The new devce identifier.
+ *  @param[out] device The device structure.
+ *  @returns EOK on success.
+ *  @returns EXDEV if one loopback network interface already exists.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int create(device_id_t device_id, netif_device_t * * device);
+
+int netif_specific_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	return ENOTSUP;
+}
+
+int netif_get_addr_message(device_id_t device_id, measured_string_ref address){
+	if(! address){
+		return EBADMEM;
+	}
+	address->value = str_dup(DEFAULT_ADDR);
+	address->length = DEFAULT_ADDR_LEN;
+	return EOK;
+}
+
+int netif_get_device_stats(device_id_t device_id, device_stats_ref stats){
+	ERROR_DECLARE;
+
+	netif_device_t * device;
+
+	if(! stats){
+		return EBADMEM;
+	}
+	ERROR_PROPAGATE(find_device(device_id, &device));
+	memcpy(stats, (device_stats_ref) device->specific, sizeof(device_stats_t));
+	return EOK;
+}
+
+int 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");
+		
+		return state;
+	}
+	
+	return EOK;
+}
+
+int create(device_id_t device_id, netif_device_t * * device){
+	int index;
+
+	if(netif_device_map_count(&netif_globals.device_map) > 0){
+		return EXDEV;
+	}else{
+		*device = (netif_device_t *) malloc(sizeof(netif_device_t));
+		if(!(*device)){
+			return ENOMEM;
+		}
+		(** device).specific = malloc(sizeof(device_stats_t));
+		if(! (** device).specific){
+			free(*device);
+			return ENOMEM;
+		}
+		null_device_stats((device_stats_ref)(** device).specific);
+		(** device).device_id = device_id;
+		(** device).nil_phone = -1;
+		(** device).state = NETIF_STOPPED;
+		index = netif_device_map_add(&netif_globals.device_map, (** device).device_id, * device);
+		if(index < 0){
+			free(*device);
+			free((** device).specific);
+			*device = NULL;
+			return index;
+		}
+	}
+	return EOK;
+}
+
+int netif_initialize(void){
+	ipcarg_t phonehash;
+
+	return REGISTER_ME(SERVICE_LO, &phonehash);
+}
+
+int netif_probe_message(device_id_t device_id, int irq, uintptr_t io){
+	ERROR_DECLARE;
+
+	netif_device_t * device;
+
+	// create a new device
+	ERROR_PROPAGATE(create(device_id, &device));
+	// print the settings
+	printf("%s: Device created (id: %d)\n", NAME, device->device_id);
+	return EOK;
+}
+
+int netif_send_message(device_id_t device_id, packet_t packet, services_t sender){
+	ERROR_DECLARE;
+
+	netif_device_t * device;
+	size_t length;
+	packet_t next;
+	int phone;
+
+	ERROR_PROPAGATE(find_device(device_id, &device));
+	if(device->state != NETIF_ACTIVE){
+		netif_pq_release(packet_get_id(packet));
+		return EFORWARD;
+	}
+	next = packet;
+	do{
+		++ ((device_stats_ref) device->specific)->send_packets;
+		++ ((device_stats_ref) device->specific)->receive_packets;
+		length = packet_get_data_length(next);
+		((device_stats_ref) device->specific)->send_bytes += length;
+		((device_stats_ref) device->specific)->receive_bytes += length;
+		next = pq_next(next);
+	}while(next);
+	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;
+}
+
+int netif_start_message(netif_device_t * device){
+	return change_state_message(device, NETIF_ACTIVE);
+}
+
+int netif_stop_message(netif_device_t * device){
+	return change_state_message(device, NETIF_STOPPED);
+}
+
+/** Default thread for new connections.
+ *
+ * @param[in] iid The initial message identifier.
+ * @param[in] icall The initial message call structure.
+ *
+ */
+static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0(iid, EOK);
+	
+	while(true) {
+		ipc_call_t answer;
+		int answer_count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &answer_count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = netif_module_message(NAME, callid, &call, &answer,
+		    &answer_count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, answer_count);
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	/* Start the module */
+	if (ERROR_OCCURRED(netif_module_start(netif_client_connection)))
+		return ERROR_CODE;
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/netstart/Makefile
===================================================================
--- uspace/srv/net/netstart/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/netstart/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,40 @@
+#
+# 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 = ../../..
+LIBS = $(LIBNET_PREFIX)/libnet.a $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+
+BINARY = netstart
+
+SOURCES = \
+	netstart.c \
+	self_test.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/netstart/netstart.c
===================================================================
--- uspace/srv/net/netstart/netstart.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/netstart/netstart.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,107 @@
+/*
+ * 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 net
+ * @{
+ */
+
+/** @file
+ *
+ * Start the networking subsystem.
+ * Perform networking self-test if executed
+ * with the -s argument.
+ *
+ */
+
+#define NAME  "netstart"
+
+#include <async.h>
+#include <stdio.h>
+#include <task.h>
+#include <str_error.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_modules.h>
+#include <net_net_messages.h>
+
+#include "self_test.h"
+
+/** Start a module.
+ *
+ * @param[in] desc The module description
+ * @param[in] path The module absolute path.
+ *
+ * @returns true on succesful spanwning
+ * @returns false on failure
+ *
+ */
+static bool spawn(const char *desc, const char *path)
+{
+	printf("%s: Spawning %s (%s)\n", NAME, desc, path);
+	
+	const char *argv[2];
+	
+	argv[0] = path;
+	argv[1] = NULL;
+	
+	int err;
+	if (task_spawn(path, argv, &err) == 0) {
+		fprintf(stderr, "%s: Error spawning %s (%s)\n", NAME, path,
+		    str_error(err));
+		return false;
+	}
+	
+	return true;
+}
+
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	/* Run self-tests */
+	if ((argc > 1) && (str_cmp(argv[1], "-s") == 0))
+		ERROR_PROPAGATE(self_test());
+	
+	if (!spawn("networking service", "/srv/net"))
+		return EINVAL;
+	
+	printf("%s: Initializing networking\n", NAME);
+	
+	int net_phone = connect_to_service(SERVICE_NETWORKING);
+	if (ERROR_OCCURRED(ipc_call_sync_0_0(net_phone, NET_NET_STARTUP))) {
+		fprintf(stderr, "%s: Startup error %d\n", NAME, ERROR_CODE);
+		return ERROR_CODE;
+	}
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/netstart/self_test.c
===================================================================
--- uspace/srv/net/netstart/self_test.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/netstart/self_test.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,334 @@
+/*
+ * 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 net
+ * @{
+ */
+
+/** @file
+ * Networking self-tests implementation.
+ *
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+
+#include <net_checksum.h>
+#include <adt/int_map.h>
+#include <adt/char_map.h>
+#include <adt/generic_char_map.h>
+#include <adt/measured_strings.h>
+#include <adt/dynamic_fifo.h>
+
+#include "self_test.h"
+
+/** Test the statement, compare the result and evaluate.
+ *
+ * @param[in] statement The statement to test.
+ * @param[in] result    The expected result.
+ *
+ */
+#define TEST(statement, result) \
+	do { \
+		printf("\n\t%s == %s", #statement, #result); \
+		if ((statement) != (result)) { \
+			printf("\tfailed\n"); \
+			fprintf(stderr, "\nNetwork self-test failed\n"); \
+			return EINVAL; \
+		} else \
+			printf("\tOK"); \
+	} while (0)
+
+#define XMALLOC(var, type) \
+	do { \
+		(var) = (type *) malloc(sizeof(type)); \
+		if ((var) == NULL) { \
+			fprintf(stderr, "\nMemory allocation error\n"); \
+			return ENOMEM; \
+		} \
+	} while (0)
+
+GENERIC_CHAR_MAP_DECLARE(int_char_map, int);
+GENERIC_CHAR_MAP_IMPLEMENT(int_char_map, int);
+
+GENERIC_FIELD_DECLARE(int_field, int);
+GENERIC_FIELD_IMPLEMENT(int_field, int);
+
+INT_MAP_DECLARE(int_map, int);
+INT_MAP_IMPLEMENT(int_map, int);
+
+/** Self-test start function.
+ *
+ * Run all self-tests.
+ *
+ * @returns EOK on success.
+ * @returns The first error occurred.
+ *
+ */
+int self_test(void)
+{
+	printf("Running networking self-tests\n");
+	
+	printf("\nChar map test");
+	char_map_t cm;
+	
+	TEST(char_map_update(&cm, "ucho", 0, 3), EINVAL);
+	TEST(char_map_initialize(&cm), EOK);
+	TEST(char_map_exclude(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_add(&cm, "bla", 0, 1), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 1);
+	TEST(char_map_add(&cm, "bla", 0, 10), EEXISTS);
+	TEST(char_map_update(&cm, "bla", 0, 2), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 2);
+	TEST(char_map_update(&cm, "ucho", 0, 2), EOK);
+	TEST(char_map_exclude(&cm, "bla", 0), 2);
+	TEST(char_map_exclude(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "ucho", 0), 2);
+	TEST(char_map_update(&cm, "ucho", 0, 3), EOK);
+	TEST(char_map_find(&cm, "ucho", 0), 3);
+	TEST(char_map_add(&cm, "blabla", 0, 5), EOK);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "bla", 0, 6), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 6);
+	TEST(char_map_exclude(&cm, "bla", 0), 6);
+	TEST(char_map_find(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "auto", 0, 7), EOK);
+	TEST(char_map_find(&cm, "auto", 0), 7);
+	TEST(char_map_add(&cm, "kara", 0, 8), EOK);
+	TEST(char_map_find(&cm, "kara", 0), 8);
+	TEST(char_map_add(&cm, "nic", 0, 9), EOK);
+	TEST(char_map_find(&cm, "nic", 0), 9);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "micnicnic", 5, 9), EOK);
+	TEST(char_map_find(&cm, "micni", 0), 9);
+	TEST(char_map_find(&cm, "micnicn", 5), 9);
+	TEST(char_map_add(&cm, "\x10\x0\x2\x2", 4, 15), EOK);
+	TEST(char_map_find(&cm, "\x10\x0\x2\x2", 4), 15);
+	
+	TEST((char_map_destroy(&cm), EOK), EOK);
+	TEST(char_map_update(&cm, "ucho", 0, 3), EINVAL);
+	
+	printf("\nCRC computation test");
+	uint32_t value;
+	
+	TEST(value = ~compute_crc32(~0, "123456789", 8 * 9), 0xcbf43926);
+	TEST(value = ~compute_crc32(~0, "1", 8), 0x83dcefb7);
+	TEST(value = ~compute_crc32(~0, "12", 8 * 2), 0x4f5344cd);
+	TEST(value = ~compute_crc32(~0, "123", 8 * 3), 0x884863d2);
+	TEST(value = ~compute_crc32(~0, "1234", 8 * 4), 0x9be3e0a3);
+	TEST(value = ~compute_crc32(~0, "12345678", 8 * 8), 0x9ae0daaf);
+	TEST(value = ~compute_crc32(~0, "ahoj pane", 8 * 9), 0x5fc3d706);
+	
+	printf("\nDynamic fifo test");
+	dyn_fifo_t fifo;
+	
+	TEST(dyn_fifo_push(&fifo, 1, 0), EINVAL);
+	TEST(dyn_fifo_initialize(&fifo, 1), EOK);
+	TEST(dyn_fifo_push(&fifo, 1, 0), EOK);
+	TEST(dyn_fifo_pop(&fifo), 1);
+	TEST(dyn_fifo_pop(&fifo), ENOENT);
+	TEST(dyn_fifo_push(&fifo, 2, 1), EOK);
+	TEST(dyn_fifo_push(&fifo, 3, 1), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 3, 0), EOK);
+	TEST(dyn_fifo_pop(&fifo), 2);
+	TEST(dyn_fifo_pop(&fifo), 3);
+	TEST(dyn_fifo_push(&fifo, 4, 2), EOK);
+	TEST(dyn_fifo_push(&fifo, 5, 2), EOK);
+	TEST(dyn_fifo_push(&fifo, 6, 2), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 6, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 7, 5), EOK);
+	TEST(dyn_fifo_pop(&fifo), 4);
+	TEST(dyn_fifo_pop(&fifo), 5);
+	TEST(dyn_fifo_push(&fifo, 8, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 9, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 10, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 11, 6), EOK);
+	TEST(dyn_fifo_pop(&fifo), 6);
+	TEST(dyn_fifo_pop(&fifo), 7);
+	TEST(dyn_fifo_push(&fifo, 12, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 13, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 14, 6), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 14, 8), EOK);
+	TEST(dyn_fifo_pop(&fifo), 8);
+	TEST(dyn_fifo_pop(&fifo), 9);
+	TEST(dyn_fifo_pop(&fifo), 10);
+	TEST(dyn_fifo_pop(&fifo), 11);
+	TEST(dyn_fifo_pop(&fifo), 12);
+	TEST(dyn_fifo_pop(&fifo), 13);
+	TEST(dyn_fifo_pop(&fifo), 14);
+	TEST(dyn_fifo_destroy(&fifo), EOK);
+	TEST(dyn_fifo_push(&fifo, 1, 0), EINVAL);
+	
+	printf("\nGeneric char map test");
+	
+	int *x;
+	int *y;
+	int *z;
+	int *u;
+	int *v;
+	int *w;
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_char_map_t icm;
+	icm.magic = 0;
+	
+	TEST(int_char_map_add(&icm, "ucho", 0, z), EINVAL);
+	TEST(int_char_map_initialize(&icm), EOK);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), NULL);
+	TEST(int_char_map_add(&icm, "bla", 0, x), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), x);
+	TEST(int_char_map_add(&icm, "bla", 0, y), EEXISTS);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_add(&icm, "blabla", 0, v), EOK);
+	TEST(int_char_map_find(&icm, "blabla", 0), v);
+	TEST(int_char_map_add(&icm, "bla", 0, w), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), w);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), NULL);
+	TEST(int_char_map_find(&icm, "blabla", 0), v);
+	TEST(int_char_map_add(&icm, "auto", 0, u), EOK);
+	TEST(int_char_map_find(&icm, "auto", 0), u);
+	TEST((int_char_map_destroy(&icm), EOK), EOK);
+	TEST(int_char_map_add(&icm, "ucho", 0, z), EINVAL);
+	
+	printf("\nGeneric field test");
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_field_t gf;
+	gf.magic = 0;
+	
+	TEST(int_field_add(&gf, x), EINVAL);
+	TEST(int_field_count(&gf), -1);
+	TEST(int_field_initialize(&gf), EOK);
+	TEST(int_field_count(&gf), 0);
+	TEST(int_field_get_index(&gf, 1), NULL);
+	TEST(int_field_add(&gf, x), 0);
+	TEST(int_field_get_index(&gf, 0), x);
+	TEST((int_field_exclude_index(&gf, 0), EOK), EOK);
+	TEST(int_field_get_index(&gf, 0), NULL);
+	TEST(int_field_add(&gf, y), 1);
+	TEST(int_field_get_index(&gf, 1), y);
+	TEST(int_field_add(&gf, z), 2);
+	TEST(int_field_get_index(&gf, 2), z);
+	TEST(int_field_get_index(&gf, 1), y);
+	TEST(int_field_count(&gf), 3);
+	TEST(int_field_add(&gf, u), 3);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST(int_field_add(&gf, v), 4);
+	TEST(int_field_get_index(&gf, 4), v);
+	TEST(int_field_add(&gf, w), 5);
+	TEST(int_field_get_index(&gf, 5), w);
+	TEST(int_field_count(&gf), 6);
+	TEST((int_field_exclude_index(&gf, 1), EOK), EOK);
+	TEST(int_field_get_index(&gf, 1), NULL);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST((int_field_exclude_index(&gf, 7), EOK), EOK);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST(int_field_get_index(&gf, 5), w);
+	TEST((int_field_exclude_index(&gf, 4), EOK), EOK);
+	TEST(int_field_get_index(&gf, 4), NULL);
+	TEST((int_field_destroy(&gf), EOK), EOK);
+	TEST(int_field_count(&gf), -1);
+	
+	printf("\nInt map test");
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_map_t im;
+	im.magic = 0;
+	
+	TEST(int_map_add(&im, 1, x), EINVAL);
+	TEST(int_map_count(&im), -1);
+	TEST(int_map_initialize(&im), EOK);
+	TEST(int_map_count(&im), 0);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_add(&im, 1, x), 0);
+	TEST(int_map_find(&im, 1), x);
+	TEST((int_map_exclude(&im, 1), EOK), EOK);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_add(&im, 1, y), 1);
+	TEST(int_map_find(&im, 1), y);
+	TEST(int_map_add(&im, 4, z), 2);
+	TEST(int_map_get_index(&im, 2), z);
+	TEST(int_map_find(&im, 4), z);
+	TEST(int_map_find(&im, 1), y);
+	TEST(int_map_count(&im), 3);
+	TEST(int_map_add(&im, 2, u), 3);
+	TEST(int_map_find(&im, 2), u);
+	TEST(int_map_add(&im, 3, v), 4);
+	TEST(int_map_find(&im, 3), v);
+	TEST(int_map_get_index(&im, 4), v);
+	TEST(int_map_add(&im, 6, w), 5);
+	TEST(int_map_find(&im, 6), w);
+	TEST(int_map_count(&im), 6);
+	TEST((int_map_exclude(&im, 1), EOK), EOK);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_find(&im, 2), u);
+	TEST((int_map_exclude(&im, 7), EOK), EOK);
+	TEST(int_map_find(&im, 2), u);
+	TEST(int_map_find(&im, 6), w);
+	TEST((int_map_exclude_index(&im, 4), EOK), EOK);
+	TEST(int_map_get_index(&im, 4), NULL);
+	TEST(int_map_find(&im, 3), NULL);
+	TEST((int_map_destroy(&im), EOK), EOK);
+	TEST(int_map_count(&im), -1);
+	
+	printf("\nMeasured strings test");
+	
+	measured_string_ref string =
+	    measured_string_create_bulk("I am a measured string!", 0);
+	printf("\n%x, %s at %x of %d\n", string, string->value, string->value,
+	    string->length);
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/netstart/self_test.h
===================================================================
--- uspace/srv/net/netstart/self_test.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/netstart/self_test.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,41 @@
+/*
+ * 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 net
+ * @{
+ */
+
+#ifndef __SELF_TEST_H__
+#define __SELF_TEST_H__
+
+extern int self_test(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/nil/eth/Makefile
===================================================================
--- uspace/srv/net/nil/eth/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/nil/eth/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,51 @@
+#
+# 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 $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+
+COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
+CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
+
+-include $(COMMON_MAKEFILE)
+-include $(CONFIG_MAKEFILE)
+
+ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
+	LIBRARY = libeth
+else
+	BINARY = eth
+endif
+
+SOURCES = \
+	eth.c \
+	eth_module.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/nil/eth/eth.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,844 @@
+/*
+ * 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 implementation.
+ *  @see eth.h
+ */
+
+#include <async.h>
+#include <malloc.h>
+#include <mem.h>
+#include <stdio.h>
+#include <str.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_messages.h>
+#include <net_modules.h>
+#include <net_byteorder.h>
+#include <net_checksum.h>
+#include <ethernet_lsap.h>
+#include <ethernet_protocols.h>
+#include <protocol_map.h>
+#include <net_device.h>
+#include <netif_interface.h>
+#include <net_interface.h>
+#include <nil_interface.h>
+#include <il_interface.h>
+#include <adt/measured_strings.h>
+#include <packet/packet_client.h>
+#include <packet_remote.h>
+#include <nil_local.h>
+
+#include "eth.h"
+#include "eth_header.h"
+
+/** The module name.
+ */
+#define NAME  "eth"
+
+/** Reserved packet prefix length.
+ */
+#define ETH_PREFIX		(sizeof(eth_header_t) + sizeof(eth_header_lsap_t) + sizeof(eth_header_snap_t))
+
+/** Reserved packet suffix length.
+ */
+#define ETH_SUFFIX		sizeof(eth_fcs_t)
+
+/** Maximum packet content length.
+ */
+#define ETH_MAX_CONTENT 1500u
+
+/** Minimum packet content length.
+ */
+#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))
+
+/** 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))
+
+/** Dummy flag shift value.
+ */
+#define ETH_DUMMY_SHIFT	0
+
+/** Mode flag shift value.
+ */
+#define ETH_MODE_SHIFT	1
+
+/** Dummy device flag.
+ *  Preamble and FCS are mandatory part of the packets.
+ */
+#define ETH_DUMMY				(1 << ETH_DUMMY_SHIFT)
+
+/** Returns the dummy flag.
+ *  @see ETH_DUMMY
+ */
+#define IS_DUMMY(flags)		((flags) &ETH_DUMMY)
+
+/** Device mode flags.
+ *  @see ETH_DIX
+ *  @see ETH_8023_2_LSAP
+ *  @see ETH_8023_2_SNAP
+ */
+#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.
+ *  @see 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.
+ *  @see 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.
+ *  @see 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.
+ *  @see eth_addr_type
+ */
+typedef enum eth_addr_type	eth_addr_type_t;
+
+/** Type definition of the ethernet address type pointer.
+ *  @see eth_addr_type
+ */
+typedef eth_addr_type_t *	eth_addr_type_ref;
+
+/** Ethernet address type.
+ */
+enum eth_addr_type{
+	/** Local address.
+	 */
+	ETH_LOCAL_ADDR,
+	/** Broadcast address.
+	 */
+	ETH_BROADCAST_ADDR
+};
+
+/** Ethernet module global data.
+ */
+eth_globals_t	eth_globals;
+
+/** @name Message processing functions
+ */
+/*@{*/
+
+/** Processes 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.
+ */
+void eth_receiver(ipc_callid_t iid, ipc_call_t * icall);
+
+/** Registers new device or updates the MTU of an existing one.
+ *  Determines 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.
+ *  @returns EOK on success.
+ *  @returns EEXIST if the device with the different service exists.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the net_get_device_conf_req() function.
+ *  @returns Other error codes as defined for the netif_bind_service() function.
+ *  @returns Other error codes as defined for the netif_get_addr_req() function.
+ */
+int eth_device_message(device_id_t device_id, services_t service, size_t mtu);
+
+/** Registers receiving module service.
+ *  Passes received packets for this service.
+ *  @param[in] service The module service.
+ *  @param[in] phone The service phone.
+ *  @returns EOK on success.
+ *  @returns ENOENT if the service is not known.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int eth_register_message(services_t service, int phone);
+
+/** Returns 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.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if either one of the parameters is NULL.
+ *  @returns ENOENT if there is no such device.
+ */
+int eth_packet_space_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix);
+
+/** Returns the device hardware address.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] type Type of the desired address.
+ *  @param[out] address The device hardware address.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the address parameter is NULL.
+ *  @returns ENOENT if there no such device.
+ */
+int eth_addr_message(device_id_t device_id, eth_addr_type_t type, measured_string_ref * address);
+
+/** Sends the packet queue.
+ *  Sends only packet successfully processed by the eth_prepare_packet() function.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet The packet queue.
+ *  @param[in] sender The sending module service.
+ *  @returns EOK on success.
+ *  @returns ENOENT if there no such device.
+ *  @returns EINVAL if the service parameter is not known.
+ */
+int eth_send_message(device_id_t device_id, packet_t packet, services_t sender);
+
+/*@}*/
+
+/** Processes the received packet and chooses the target registered module.
+ *  @param[in] flags The device flags.
+ *  @param[in] packet The packet.
+ *  @returns The target registered module.
+ *  @returns NULL if the packet is not long enough.
+ *  @returns NULL if the packet is too long.
+ *  @returns NULL if the raw ethernet protocol is used.
+ *  @returns NULL if the dummy device FCS checksum is invalid.
+ *  @returns NULL if the packet address length is not big enough.
+ */
+eth_proto_ref eth_process_packet(int flags, packet_t packet);
+
+/** Prepares the packet for sending.
+ *  @param[in] flags The device flags.
+ *  @param[in] packet The packet.
+ *  @param[in] src_addr The source hardware address.
+ *  @param[in] ethertype The ethernet protocol type.
+ *  @param[in] mtu The device maximum transmission unit.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet addresses length is not long enough.
+ *  @returns EINVAL if the packet is bigger than the device MTU.
+ *  @returns ENOMEM if there is not enough memory in the packet.
+ */
+int eth_prepare_packet(int flags, packet_t packet, uint8_t * src_addr, int ethertype, size_t mtu);
+
+DEVICE_MAP_IMPLEMENT(eth_devices, eth_device_t)
+
+INT_MAP_IMPLEMENT(eth_protos, eth_proto_t)
+
+int nil_device_state_msg_local(int nil_phone, device_id_t device_id, int state){
+	int index;
+	eth_proto_ref proto;
+
+	fibril_rwlock_read_lock(&eth_globals.protos_lock);
+	for(index = eth_protos_count(&eth_globals.protos) - 1; index >= 0; -- index){
+		proto = eth_protos_get_index(&eth_globals.protos, index);
+		if(proto && proto->phone){
+			il_device_state_msg(proto->phone, device_id, state, proto->service);
+		}
+	}
+	fibril_rwlock_read_unlock(&eth_globals.protos_lock);
+	return EOK;
+}
+
+int nil_initialize(int net_phone){
+	ERROR_DECLARE;
+
+	fibril_rwlock_initialize(&eth_globals.devices_lock);
+	fibril_rwlock_initialize(&eth_globals.protos_lock);
+	fibril_rwlock_write_lock(&eth_globals.devices_lock);
+	fibril_rwlock_write_lock(&eth_globals.protos_lock);
+	eth_globals.net_phone = net_phone;
+	eth_globals.broadcast_addr = measured_string_create_bulk("\xFF\xFF\xFF\xFF\xFF\xFF", CONVERT_SIZE(uint8_t, char, ETH_ADDR));
+	if(! eth_globals.broadcast_addr){
+		return ENOMEM;
+	}
+	ERROR_PROPAGATE(eth_devices_initialize(&eth_globals.devices));
+	if(ERROR_OCCURRED(eth_protos_initialize(&eth_globals.protos))){
+		eth_devices_destroy(&eth_globals.devices);
+		return ERROR_CODE;
+	}
+	fibril_rwlock_write_unlock(&eth_globals.protos_lock);
+	fibril_rwlock_write_unlock(&eth_globals.devices_lock);
+	return EOK;
+}
+
+int eth_device_message(device_id_t device_id, services_t service, size_t mtu){
+	ERROR_DECLARE;
+
+	eth_device_ref device;
+	int index;
+	measured_string_t names[2] = {{str_dup("ETH_MODE"), 8}, {str_dup("ETH_DUMMY"), 9}};
+	measured_string_ref configuration;
+	size_t count = sizeof(names) / sizeof(measured_string_t);
+	char * data;
+	eth_proto_ref proto;
+
+	fibril_rwlock_write_lock(&eth_globals.devices_lock);
+	// an existing device?
+	device = eth_devices_find(&eth_globals.devices, device_id);
+	if(device){
+		if(device->service != service){
+			printf("Device %d already exists\n", device->device_id);
+			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
+			return EEXIST;
+		}else{
+			// update mtu
+			if((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags))){
+				device->mtu = mtu;
+			}else{
+				 device->mtu = ETH_MAX_TAGGED_CONTENT(device->flags);
+			}
+			printf("Device %d already exists:\tMTU\t= %d\n", device->device_id, device->mtu);
+			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
+			// notify all upper layer modules
+			fibril_rwlock_read_lock(&eth_globals.protos_lock);
+			for(index = 0; index < eth_protos_count(&eth_globals.protos); ++ index){
+				proto = eth_protos_get_index(&eth_globals.protos, index);
+				if (proto->phone){
+					il_mtu_changed_msg(proto->phone, device->device_id, device->mtu, proto->service);
+				}
+			}
+			fibril_rwlock_read_unlock(&eth_globals.protos_lock);
+			return EOK;
+		}
+	}else{
+		// create a new device
+		device = (eth_device_ref) malloc(sizeof(eth_device_t));
+		if(! device){
+			return ENOMEM;
+		}
+		device->device_id = device_id;
+		device->service = service;
+		device->flags = 0;
+		if((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags))){
+			device->mtu = mtu;
+		}else{
+			 device->mtu = ETH_MAX_TAGGED_CONTENT(device->flags);
+		}
+		configuration = &names[0];
+		if(ERROR_OCCURRED(net_get_device_conf_req(eth_globals.net_phone, device->device_id, &configuration, count, &data))){
+			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
+			free(device);
+			return ERROR_CODE;
+		}
+		if(configuration){
+			if(! str_lcmp(configuration[0].value, "DIX", configuration[0].length)){
+				device->flags |= ETH_DIX;
+			}else if(! str_lcmp(configuration[0].value, "8023_2_LSAP", configuration[0].length)){
+				device->flags |= ETH_8023_2_LSAP;
+			}else device->flags |= ETH_8023_2_SNAP;
+			if((configuration[1].value) && (configuration[1].value[0] == 'y')){
+				device->flags |= ETH_DUMMY;
+			}
+			net_free_settings(configuration, data);
+		}else{
+			device->flags |= ETH_8023_2_SNAP;
+		}
+		// bind the device driver
+		device->phone = netif_bind_service(device->service, device->device_id, SERVICE_ETHERNET, eth_receiver);
+		if(device->phone < 0){
+			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
+			free(device);
+			return device->phone;
+		}
+		// get hardware address
+		if(ERROR_OCCURRED(netif_get_addr_req(device->phone, device->device_id, &device->addr, &device->addr_data))){
+			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
+			free(device);
+			return ERROR_CODE;
+		}
+		// add to the cache
+		index = eth_devices_add(&eth_globals.devices, device->device_id, device);
+		if(index < 0){
+			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
+			free(device->addr);
+			free(device->addr_data);
+			free(device);
+			return index;
+		}
+		printf("%s: Device registered (id: %d, service: %d: mtu: %d, "
+		    "mac: %x:%x:%x:%x:%x:%x, flags: 0x%x)\n",
+		    NAME, device->device_id, device->service, device->mtu,
+		    device->addr_data[0], device->addr_data[1],
+		    device->addr_data[2], device->addr_data[3],
+		    device->addr_data[4], device->addr_data[5], device->flags);
+	}
+	fibril_rwlock_write_unlock(&eth_globals.devices_lock);
+	return EOK;
+}
+
+eth_proto_ref eth_process_packet(int flags, packet_t packet){
+	ERROR_DECLARE;
+
+	eth_header_snap_ref header;
+	size_t length;
+	eth_type_t type;
+	size_t prefix;
+	size_t suffix;
+	eth_fcs_ref fcs;
+	uint8_t * data;
+
+	length = packet_get_data_length(packet);
+	if(IS_DUMMY(flags)){
+		packet_trim(packet, sizeof(eth_preamble_t), 0);
+	}
+	if(length < sizeof(eth_header_t) + ETH_MIN_CONTENT + (IS_DUMMY(flags) ? ETH_SUFFIX : 0)) return NULL;
+	data = packet_get_data(packet);
+	header = (eth_header_snap_ref) data;
+	type = ntohs(header->header.ethertype);
+	if(type >= ETH_MIN_PROTO){
+		// DIX Ethernet
+		prefix = sizeof(eth_header_t);
+		suffix = 0;
+		fcs = (eth_fcs_ref) data + length - sizeof(eth_fcs_t);
+		length -= sizeof(eth_fcs_t);
+	}else if(type <= ETH_MAX_CONTENT){
+		// translate "LSAP" values
+		if((header->lsap.dsap == ETH_LSAP_GLSAP) && (header->lsap.ssap == ETH_LSAP_GLSAP)){
+			// raw packet
+			// discard
+			return NULL;
+		}else if((header->lsap.dsap == ETH_LSAP_SNAP) && (header->lsap.ssap == ETH_LSAP_SNAP)){
+			// IEEE 802.3 + 802.2 + LSAP + SNAP
+			// organization code not supported
+			type = ntohs(header->snap.ethertype);
+			prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) + sizeof(eth_header_snap_t);
+		}else{
+			// IEEE 802.3 + 802.2 LSAP
+			type = lsap_map(header->lsap.dsap);
+			prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
+		}
+		suffix = (type < ETH_MIN_CONTENT) ? ETH_MIN_CONTENT - type : 0u;
+		fcs = (eth_fcs_ref) data + prefix + type + suffix;
+		suffix += length - prefix - type;
+		length = prefix + type + suffix;
+	}else{
+		// invalid length/type, should not occurr
+		return NULL;
+	}
+	if(IS_DUMMY(flags)){
+		if((~ compute_crc32(~ 0u, data, length * 8)) != ntohl(*fcs)){
+			return NULL;
+		}
+		suffix += sizeof(eth_fcs_t);
+	}
+	if(ERROR_OCCURRED(packet_set_addr(packet, header->header.source_address, header->header.destination_address, ETH_ADDR))
+		|| ERROR_OCCURRED(packet_trim(packet, prefix, suffix))){
+		return NULL;
+	}
+	return eth_protos_find(&eth_globals.protos, type);
+}
+
+int nil_received_msg_local(int nil_phone, device_id_t device_id, packet_t packet, services_t target){
+	eth_proto_ref proto;
+	packet_t next;
+	eth_device_ref device;
+	int flags;
+
+	fibril_rwlock_read_lock(&eth_globals.devices_lock);
+	device = eth_devices_find(&eth_globals.devices, device_id);
+	if(! device){
+		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
+		return ENOENT;
+	}
+	flags = device->flags;
+	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
+	fibril_rwlock_read_lock(&eth_globals.protos_lock);
+	do{
+		next = pq_detach(packet);
+		proto = eth_process_packet(flags, packet);
+		if(proto){
+			il_received_msg(proto->phone, device_id, packet, proto->service);
+		}else{
+			// drop invalid/unknown
+			pq_release_remote(eth_globals.net_phone, packet_get_id(packet));
+		}
+		packet = next;
+	}while(packet);
+	fibril_rwlock_read_unlock(&eth_globals.protos_lock);
+	return EOK;
+}
+
+int eth_packet_space_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix){
+	eth_device_ref device;
+
+	if(!(addr_len && prefix && content && suffix)){
+		return EBADMEM;
+	}
+	fibril_rwlock_read_lock(&eth_globals.devices_lock);
+	device = eth_devices_find(&eth_globals.devices, device_id);
+	if(! device){
+		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
+		return ENOENT;
+	}
+	*content = device->mtu;
+	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
+	*addr_len = ETH_ADDR;
+	*prefix = ETH_PREFIX;
+	*suffix = ETH_MIN_CONTENT + ETH_SUFFIX;
+	return EOK;
+}
+
+int eth_addr_message(device_id_t device_id, eth_addr_type_t type, measured_string_ref * address){
+	eth_device_ref device;
+
+	if(! address){
+		return EBADMEM;
+	}
+	if(type == ETH_BROADCAST_ADDR){
+		*address = eth_globals.broadcast_addr;
+	}else{
+		fibril_rwlock_read_lock(&eth_globals.devices_lock);
+		device = eth_devices_find(&eth_globals.devices, device_id);
+		if(! device){
+			fibril_rwlock_read_unlock(&eth_globals.devices_lock);
+			return ENOENT;
+		}
+		*address = device->addr;
+		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
+	}
+	return (*address) ? EOK : ENOENT;
+}
+
+int eth_register_message(services_t service, int phone){
+	eth_proto_ref proto;
+	int protocol;
+	int index;
+
+	protocol = protocol_map(SERVICE_ETHERNET, service);
+	if(! protocol){
+		return ENOENT;
+	}
+	fibril_rwlock_write_lock(&eth_globals.protos_lock);
+	proto = eth_protos_find(&eth_globals.protos, protocol);
+	if(proto){
+		proto->phone = phone;
+		fibril_rwlock_write_unlock(&eth_globals.protos_lock);
+		return EOK;
+	}else{
+		proto = (eth_proto_ref) malloc(sizeof(eth_proto_t));
+		if(! proto){
+			fibril_rwlock_write_unlock(&eth_globals.protos_lock);
+			return ENOMEM;
+		}
+		proto->service = service;
+		proto->protocol = protocol;
+		proto->phone = phone;
+		index = eth_protos_add(&eth_globals.protos, protocol, proto);
+		if(index < 0){
+			fibril_rwlock_write_unlock(&eth_globals.protos_lock);
+			free(proto);
+			return index;
+		}
+	}
+	
+	printf("%s: Protocol registered (protocol: %d, service: %d, phone: %d)\n",
+	    NAME, proto->protocol, proto->service, proto->phone);
+	
+	fibril_rwlock_write_unlock(&eth_globals.protos_lock);
+	return EOK;
+}
+
+int eth_prepare_packet(int flags, packet_t packet, uint8_t * src_addr, int ethertype, size_t mtu){
+	eth_header_snap_ref header;
+	eth_header_lsap_ref header_lsap;
+	eth_header_ref header_dix;
+	eth_fcs_ref fcs;
+	uint8_t * src;
+	uint8_t * dest;
+	size_t length;
+	int i;
+	void * padding;
+	eth_preamble_ref preamble;
+
+	i = packet_get_addr(packet, &src, &dest);
+	if(i < 0){
+		return i;
+	}
+	if(i != ETH_ADDR){
+		return EINVAL;
+	}
+	length = packet_get_data_length(packet);
+	if(length > mtu){
+		return EINVAL;
+	}
+	if(length < ETH_MIN_TAGGED_CONTENT(flags)){
+		padding = packet_suffix(packet, ETH_MIN_TAGGED_CONTENT(flags) - length);
+		if(! padding){
+			return ENOMEM;
+		}
+		bzero(padding, ETH_MIN_TAGGED_CONTENT(flags) - length);
+	}
+	if(IS_DIX(flags)){
+		header_dix = PACKET_PREFIX(packet, eth_header_t);
+		if(! header_dix){
+			return ENOMEM;
+		}
+		header_dix->ethertype = (uint16_t) ethertype;
+		memcpy(header_dix->source_address, src_addr, ETH_ADDR);
+		memcpy(header_dix->destination_address, dest, ETH_ADDR);
+		src = &header_dix->destination_address[0];
+	}else if(IS_8023_2_LSAP(flags)){
+		header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
+		if(! header_lsap){
+			return ENOMEM;
+		}
+		header_lsap->header.ethertype = htons(length + sizeof(eth_header_lsap_t));
+		header_lsap->lsap.dsap = lsap_unmap(ntohs(ethertype));
+		header_lsap->lsap.ssap = header_lsap->lsap.dsap;
+		header_lsap->lsap.ctrl = IEEE_8023_2_UI;
+		memcpy(header_lsap->header.source_address, src_addr, ETH_ADDR);
+		memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
+		src = &header_lsap->header.destination_address[0];
+	}else if(IS_8023_2_SNAP(flags)){
+		header = PACKET_PREFIX(packet, eth_header_snap_t);
+		if(! header){
+			return ENOMEM;
+		}
+		header->header.ethertype = htons(length + sizeof(eth_header_lsap_t) + sizeof(eth_header_snap_t));
+		header->lsap.dsap = (uint16_t) ETH_LSAP_SNAP;
+		header->lsap.ssap = header->lsap.dsap;
+		header->lsap.ctrl = IEEE_8023_2_UI;
+		for(i = 0; i < 3; ++ i){
+			header->snap.protocol[i] = 0;
+		}
+		header->snap.ethertype = (uint16_t) ethertype;
+		memcpy(header->header.source_address, src_addr, ETH_ADDR);
+		memcpy(header->header.destination_address, dest, ETH_ADDR);
+		src = &header->header.destination_address[0];
+	}
+	if(IS_DUMMY(flags)){
+		preamble = PACKET_PREFIX(packet, eth_preamble_t);
+		if(! preamble){
+			return ENOMEM;
+		}
+		for(i = 0; i < 7; ++ i){
+			preamble->preamble[i] = ETH_PREAMBLE;
+		}
+		preamble->sfd = ETH_SFD;
+		fcs = PACKET_SUFFIX(packet, eth_fcs_t);
+		if(! fcs){
+			return ENOMEM;
+		}
+		*fcs = htonl(~ compute_crc32(~ 0u, src, length * 8));
+	}
+	return EOK;
+}
+
+int eth_send_message(device_id_t device_id, packet_t packet, services_t sender){
+	ERROR_DECLARE;
+
+	eth_device_ref device;
+	packet_t next;
+	packet_t tmp;
+	int ethertype;
+
+	ethertype = htons(protocol_map(SERVICE_ETHERNET, sender));
+	if(! ethertype){
+		pq_release_remote(eth_globals.net_phone, packet_get_id(packet));
+		return EINVAL;
+	}
+	fibril_rwlock_read_lock(&eth_globals.devices_lock);
+	device = eth_devices_find(&eth_globals.devices, device_id);
+	if(! device){
+		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
+		return ENOENT;
+	}
+	// process packet queue
+	next = packet;
+	do{
+		if(ERROR_OCCURRED(eth_prepare_packet(device->flags, next, (uint8_t *) device->addr->value, ethertype, device->mtu))){
+			// release invalid packet
+			tmp = pq_detach(next);
+			if(next == packet){
+				packet = tmp;
+			}
+			pq_release_remote(eth_globals.net_phone, packet_get_id(next));
+			next = tmp;
+		}else{
+			next = pq_next(next);
+		}
+	}while(next);
+	// send packet queue
+	if(packet){
+		netif_send_msg(device->phone, device_id, packet, SERVICE_ETHERNET);
+	}
+	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
+	return EOK;
+}
+
+int nil_message_standalone(const char *name, ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, int *answer_count)
+{
+	ERROR_DECLARE;
+	
+	measured_string_ref address;
+	packet_t packet;
+	size_t addrlen;
+	size_t prefix;
+	size_t suffix;
+	size_t content;
+	
+	*answer_count = 0;
+	switch (IPC_GET_METHOD(*call)) {
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_NIL_DEVICE:
+			return eth_device_message(IPC_GET_DEVICE(call),
+			    IPC_GET_SERVICE(call), IPC_GET_MTU(call));
+		case NET_NIL_SEND:
+			ERROR_PROPAGATE(packet_translate_remote(eth_globals.net_phone, &packet,
+			    IPC_GET_PACKET(call)));
+			return eth_send_message(IPC_GET_DEVICE(call), packet,
+			    IPC_GET_SERVICE(call));
+		case NET_NIL_PACKET_SPACE:
+			ERROR_PROPAGATE(eth_packet_space_message(IPC_GET_DEVICE(call),
+			    &addrlen, &prefix, &content, &suffix));
+			IPC_SET_ADDR(answer, addrlen);
+			IPC_SET_PREFIX(answer, prefix);
+			IPC_SET_CONTENT(answer, content);
+			IPC_SET_SUFFIX(answer, suffix);
+			*answer_count = 4;
+			return EOK;
+		case NET_NIL_ADDR:
+			ERROR_PROPAGATE(eth_addr_message(IPC_GET_DEVICE(call),
+			    ETH_LOCAL_ADDR, &address));
+			return measured_strings_reply(address, 1);
+		case NET_NIL_BROADCAST_ADDR:
+			ERROR_PROPAGATE(eth_addr_message(IPC_GET_DEVICE(call),
+			    ETH_BROADCAST_ADDR, &address));
+			return measured_strings_reply(address, 1);
+		case IPC_M_CONNECT_TO_ME:
+			return eth_register_message(NIL_GET_PROTO(call),
+			    IPC_GET_PHONE(call));
+	}
+	
+	return ENOTSUP;
+}
+
+void eth_receiver(ipc_callid_t iid, ipc_call_t * icall){
+	ERROR_DECLARE;
+
+	packet_t packet;
+
+	while(true){
+//		printf("message %d - %d\n", IPC_GET_METHOD(*icall), NET_NIL_FIRST);
+		switch(IPC_GET_METHOD(*icall)){
+			case NET_NIL_DEVICE_STATE:
+				nil_device_state_msg_local(0, IPC_GET_DEVICE(icall), IPC_GET_STATE(icall));
+				ipc_answer_0(iid, EOK);
+				break;
+			case NET_NIL_RECEIVED:
+				if(! ERROR_OCCURRED(packet_translate_remote(eth_globals.net_phone, &packet, IPC_GET_PACKET(icall)))){
+					ERROR_CODE = nil_received_msg_local(0, IPC_GET_DEVICE(icall), packet, 0);
+				}
+				ipc_answer_0(iid, (ipcarg_t) ERROR_CODE);
+				break;
+			default:
+				ipc_answer_0(iid, (ipcarg_t) ENOTSUP);
+		}
+		iid = async_get_call(icall);
+	}
+}
+
+#ifndef CONFIG_NETIF_NIL_BUNDLE
+
+/** Default thread for new connections.
+ *
+ * @param[in] iid The initial message identifier.
+ * @param[in] icall The initial message call structure.
+ *
+ */
+static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0(iid, EOK);
+	
+	while(true) {
+		ipc_call_t answer;
+		int answer_count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &answer_count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = nil_module_message_standalone(NAME, callid, &call, &answer,
+		    &answer_count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, answer_count);
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	/* Start the module */
+	if (ERROR_OCCURRED(nil_module_start_standalone(nil_client_connection)))
+		return ERROR_CODE;
+	
+	return EOK;
+}
+
+#endif /* CONFIG_NETIF_NIL_BUNDLE */
+
+/** @}
+ */
Index: uspace/srv/net/nil/eth/eth.h
===================================================================
--- uspace/srv/net/nil/eth/eth.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/nil/eth/eth.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+#ifndef __NET_ETH_H__
+#define __NET_ETH_H__
+
+#include <fibril_synch.h>
+#include <ipc/services.h>
+
+#include <net_device.h>
+#include <adt/measured_strings.h>
+
+/** Type definition of the Ethernet global data.
+ *  @see eth_globals
+ */
+typedef struct eth_globals	eth_globals_t;
+
+/** Type definition of the Ethernet device specific data.
+ *  @see eth_device
+ */
+typedef struct eth_device	eth_device_t;
+
+/** Type definition of the Ethernet device specific data pointer.
+ *  @see eth_device
+ */
+typedef eth_device_t *		eth_device_ref;
+
+/** Type definition of the Ethernet protocol specific data.
+ *  @see eth_proto
+ */
+typedef struct eth_proto	eth_proto_t;
+
+/** Type definition of the Ethernet protocol specific data pointer.
+ *  @see eth_proto
+ */
+typedef eth_proto_t *		eth_proto_ref;
+
+/** Ethernet device map.
+ *  Maps devices to the Ethernet device specific data.
+ *  @see device.h
+ */
+DEVICE_MAP_DECLARE(eth_devices, eth_device_t)
+
+/** Ethernet protocol map.
+ *  Maps protocol identifiers to the Ethernet protocol specific data.
+ *  @see int_map.h
+ */
+INT_MAP_DECLARE(eth_protos, eth_proto_t)
+
+/** Ethernet device specific data.
+ */
+struct	eth_device{
+	/** Device identifier.
+	 */
+	device_id_t device_id;
+	/** Device driver service.
+	 */
+	services_t service;
+	/** Driver phone.
+	 */
+	int phone;
+	/** Maximal transmission unit.
+	 */
+	size_t mtu;
+	/** Various device flags.
+	 *  @see ETH_DUMMY
+	 *  @see ETH_MODE_MASK
+	 */
+	int flags;
+	/** Actual device hardware address.
+	 */
+	measured_string_ref addr;
+	/** Actual device hardware address data.
+	 */
+	char * addr_data;
+};
+
+/** Ethernet protocol specific data.
+ */
+struct eth_proto{
+	/** Protocol service.
+	 */
+	services_t service;
+	/** Protocol identifier.
+	 */
+	int protocol;
+	/** Protocol module phone.
+	 */
+	int phone;
+};
+
+/** Ethernet global data.
+ */
+struct	eth_globals{
+	/** Networking module phone.
+	 */
+	int net_phone;
+	/** Safety lock for devices.
+	 */
+	fibril_rwlock_t devices_lock;
+	/** All known Ethernet devices.
+	 */
+	eth_devices_t devices;
+	/** Safety lock for protocols.
+	 */
+	fibril_rwlock_t protos_lock;
+	/** Protocol map.
+	 *  Service phone map for each protocol.
+	 */
+	eth_protos_t protos;
+	/** Broadcast device hardware address.
+	 */
+	measured_string_ref broadcast_addr;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/nil/eth/eth_header.h
===================================================================
--- uspace/srv/net/nil/eth/eth_header.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/nil/eth/eth_header.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,217 @@
+/*
+ * 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 pointer.
+ *  @see eth_header_snap
+ */
+typedef eth_header_snap_t *		eth_header_snap_ref;
+
+/** 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 IEEE 802.3 + 802.2 extension pointer.
+ *  @see eth_header_lsap
+ */
+typedef eth_header_lsap_t *		eth_header_lsap_ref;
+
+/** 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 LSAP extension pointer.
+ *  @see eth_ieee_lsap
+ */
+typedef eth_ieee_lsap_t *		eth_ieee_lsap_ref;
+
+/** Type definition of the Ethernet header SNAP extension.
+ *  @see eth_snap
+ */
+typedef struct eth_snap		eth_snap_t;
+
+/** Type definition of the Ethernet header SNAP extension pointer.
+ *  @see eth_snap
+ */
+typedef eth_snap_t *		eth_snap_ref;
+
+/** Type definition of the Ethernet header preamble.
+ *  @see preamble
+ */
+typedef struct eth_preamble	eth_preamble_t;
+
+/** Type definition of the Ethernet header preamble pointer.
+ *  @see eth_preamble
+ */
+typedef eth_preamble_t *	eth_preamble_ref;
+
+/** Type definition of the Ethernet header.
+ *  @see eth_header
+ */
+typedef struct eth_header	eth_header_t;
+
+/** Type definition of the Ethernet header pointer.
+ *  @see eth_header
+ */
+typedef eth_header_t *		eth_header_ref;
+
+/** 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;
+
+/** Ethernet Frame Check Sequence pointer.
+ */
+typedef eth_fcs_t *		eth_fcs_ref;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/nil/eth/eth_module.c
===================================================================
--- uspace/srv/net/nil/eth/eth_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/nil/eth/eth_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,103 @@
+/*
+ * 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 <async.h>
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_modules.h>
+#include <net_interface.h>
+#include <packet/packet.h>
+#include <nil_local.h>
+
+#include "eth.h"
+
+/** Starts the Ethernet 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the pm_init() function.
+ *  @returns Other error codes as defined for the nil_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int nil_module_start_standalone(async_client_conn_t client_connection)
+{
+	ERROR_DECLARE;
+	
+	async_set_client_connection(client_connection);
+	int net_phone = net_connect_module(SERVICE_NETWORKING);
+	ERROR_PROPAGATE(pm_init());
+	
+	ipcarg_t phonehash;
+	if (ERROR_OCCURRED(nil_initialize(net_phone))
+	    || ERROR_OCCURRED(REGISTER_ME(SERVICE_ETHERNET, &phonehash))) {
+		pm_destroy();
+		return ERROR_CODE;
+	}
+	
+	async_manager();
+	
+	pm_destroy();
+	return EOK;
+}
+
+/** 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.
+ *
+ */
+int nil_module_message_standalone(const char *name, ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, int *answer_count)
+{
+	return nil_message_standalone(name, callid, call, answer, answer_count);
+}
+
+/** @}
+ */
Index: uspace/srv/net/nil/nildummy/Makefile
===================================================================
--- uspace/srv/net/nil/nildummy/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/nil/nildummy/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,51 @@
+#
+# 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 $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+
+COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
+CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
+
+-include $(COMMON_MAKEFILE)
+-include $(CONFIG_MAKEFILE)
+
+ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
+	LIBRARY = libnildummy
+else
+	BINARY = nildummy
+endif
+
+SOURCES = \
+	nildummy.c \
+	nildummy_module.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,466 @@
+/*
+ * 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 implementation.
+ * @see nildummy.h
+ */
+
+#include <async.h>
+#include <malloc.h>
+#include <mem.h>
+#include <stdio.h>
+#include <str.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_messages.h>
+#include <net_modules.h>
+#include <net_device.h>
+#include <netif_interface.h>
+#include <nil_interface.h>
+#include <il_interface.h>
+#include <adt/measured_strings.h>
+#include <packet/packet.h>
+#include <packet_remote.h>
+#include <nil_local.h>
+
+#include "nildummy.h"
+
+/** The module name.
+ *
+ */
+#define NAME  "nildummy"
+
+/** Default maximum transmission unit.
+ *
+ */
+#define NET_DEFAULT_MTU  1500
+
+/** Network interface layer module global data.
+ *
+ */
+nildummy_globals_t nildummy_globals;
+
+DEVICE_MAP_IMPLEMENT(nildummy_devices, nildummy_device_t);
+
+int nil_device_state_msg_local(int nil_phone, device_id_t device_id, int state)
+{
+	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
+	
+	if (nildummy_globals.proto.phone)
+		il_device_state_msg(nildummy_globals.proto.phone, device_id, state,
+		    nildummy_globals.proto.service);
+	
+	fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
+	
+	return EOK;
+}
+
+int nil_initialize(int net_phone)
+{
+	ERROR_DECLARE;
+	
+	fibril_rwlock_initialize(&nildummy_globals.devices_lock);
+	fibril_rwlock_initialize(&nildummy_globals.protos_lock);
+	fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
+	fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
+	
+	nildummy_globals.net_phone = net_phone;
+	nildummy_globals.proto.phone = 0;
+	ERROR_PROPAGATE(nildummy_devices_initialize(&nildummy_globals.devices));
+	
+	fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
+	fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
+	
+	return EOK;
+}
+
+/** 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.
+ *
+ */
+static void nildummy_receiver(ipc_callid_t iid, ipc_call_t * icall){
+	ERROR_DECLARE;
+
+	packet_t packet;
+
+	while(true){
+		switch(IPC_GET_METHOD(*icall)){
+			case NET_NIL_DEVICE_STATE:
+				ERROR_CODE = nil_device_state_msg_local(0, IPC_GET_DEVICE(icall), IPC_GET_STATE(icall));
+				ipc_answer_0(iid, (ipcarg_t) ERROR_CODE);
+				break;
+			case NET_NIL_RECEIVED:
+				if(! ERROR_OCCURRED(packet_translate_remote(nildummy_globals.net_phone, &packet, IPC_GET_PACKET(icall)))){
+					ERROR_CODE = nil_received_msg_local(0, IPC_GET_DEVICE(icall), packet, 0);
+				}
+				ipc_answer_0(iid, (ipcarg_t) ERROR_CODE);
+				break;
+			default:
+				ipc_answer_0(iid, (ipcarg_t) ENOTSUP);
+		}
+		iid = async_get_call(icall);
+	}
+}
+
+/** Register new device or updates the MTU of an existing one.
+ *
+ * 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.
+ *
+ * @returns EOK on success.
+ * @returns EEXIST if the device with the different service exists.
+ * @returns ENOMEM if there is not enough memory left.
+ * @returns Other error codes as defined for the netif_bind_service() function.
+ * @returns 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)
+{
+	ERROR_DECLARE;
+
+	nildummy_device_ref device;
+	int index;
+
+	fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
+	// an existing device?
+	device = nildummy_devices_find(&nildummy_globals.devices, device_id);
+	if(device){
+		if(device->service != service){
+			printf("Device %d already exists\n", device->device_id);
+			fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
+			return EEXIST;
+		}else{
+			// update mtu
+			if(mtu > 0){
+				device->mtu = mtu;
+			}else{
+				device->mtu = NET_DEFAULT_MTU;
+			}
+			printf("Device %d already exists:\tMTU\t= %d\n", device->device_id, device->mtu);
+			fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
+			// notify the upper layer module
+			fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
+			if(nildummy_globals.proto.phone){
+				il_mtu_changed_msg(nildummy_globals.proto.phone, device->device_id, device->mtu, nildummy_globals.proto.service);
+			}
+			fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
+			return EOK;
+		}
+	}else{
+		// create a new device
+		device = (nildummy_device_ref) malloc(sizeof(nildummy_device_t));
+		if(! device){
+			return ENOMEM;
+		}
+		device->device_id = device_id;
+		device->service = service;
+		if(mtu > 0){
+			device->mtu = mtu;
+		}else{
+			device->mtu = NET_DEFAULT_MTU;
+		}
+		// bind the device driver
+		device->phone = netif_bind_service(device->service, device->device_id, SERVICE_ETHERNET, nildummy_receiver);
+		if(device->phone < 0){
+			fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
+			free(device);
+			return device->phone;
+		}
+		// get hardware address
+		if(ERROR_OCCURRED(netif_get_addr_req(device->phone, device->device_id, &device->addr, &device->addr_data))){
+			fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
+			free(device);
+			return ERROR_CODE;
+		}
+		// add to the cache
+		index = nildummy_devices_add(&nildummy_globals.devices, device->device_id, device);
+		if(index < 0){
+			fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
+			free(device->addr);
+			free(device->addr_data);
+			free(device);
+			return index;
+		}
+		printf("%s: Device registered (id: %d, service: %d, mtu: %d)\n",
+		    NAME, device->device_id, device->service, device->mtu);
+	}
+	fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
+	return EOK;
+}
+
+/** 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.
+ *
+ */
+static int nildummy_addr_message(device_id_t device_id,
+    measured_string_ref *address)
+{
+	nildummy_device_ref device;
+
+	if(! address){
+		return EBADMEM;
+	}
+	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
+	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);
+	return (*address) ? EOK : ENOENT;
+}
+
+/** 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.
+ *
+ */
+static int nildummy_packet_space_message(device_id_t device_id,
+    size_t *addr_len, size_t *prefix, size_t *content, size_t *suffix)
+{
+	nildummy_device_ref device;
+
+	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);
+	if(! device){
+		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
+		return ENOENT;
+	}
+	*content = device->mtu;
+	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
+	*addr_len = 0;
+	*prefix = 0;
+	*suffix = 0;
+	return EOK;
+}
+
+int nil_received_msg_local(int nil_phone, device_id_t device_id, 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);
+			il_received_msg(nildummy_globals.proto.phone, device_id, packet, nildummy_globals.proto.service);
+			packet = next;
+		}while(packet);
+	}
+	fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
+	return EOK;
+}
+
+/** Register receiving module service.
+ *
+ * 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.
+ *
+ */
+static int nildummy_register_message(services_t service, int phone)
+{
+	fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
+	nildummy_globals.proto.service = service;
+	nildummy_globals.proto.phone = phone;
+	
+	printf("%s: Protocol registered (service: %d, phone: %d)\n",
+	    NAME, nildummy_globals.proto.service, nildummy_globals.proto.phone);
+	
+	fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
+	return EOK;
+}
+
+/** 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.
+ *
+ */
+static int nildummy_send_message(device_id_t device_id, packet_t packet,
+    services_t sender)
+{
+	nildummy_device_ref device;
+
+	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
+	device = nildummy_devices_find(&nildummy_globals.devices, device_id);
+	if(! device){
+		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
+		return ENOENT;
+	}
+	// send packet queue
+	if(packet){
+		netif_send_msg(device->phone, device_id, packet, SERVICE_NILDUMMY);
+	}
+	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
+	return EOK;
+}
+
+int nil_message_standalone(const char *name, ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, int *answer_count)
+{
+	ERROR_DECLARE;
+	
+	measured_string_ref address;
+	packet_t packet;
+	size_t addrlen;
+	size_t prefix;
+	size_t suffix;
+	size_t content;
+	
+	*answer_count = 0;
+	switch (IPC_GET_METHOD(*call)) {
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_NIL_DEVICE:
+			return nildummy_device_message(IPC_GET_DEVICE(call),
+			    IPC_GET_SERVICE(call), IPC_GET_MTU(call));
+		case NET_NIL_SEND:
+			ERROR_PROPAGATE(packet_translate_remote(nildummy_globals.net_phone,
+			    &packet, IPC_GET_PACKET(call)));
+			return nildummy_send_message(IPC_GET_DEVICE(call), packet,
+			    IPC_GET_SERVICE(call));
+		case NET_NIL_PACKET_SPACE:
+			ERROR_PROPAGATE(nildummy_packet_space_message(IPC_GET_DEVICE(call),
+			    &addrlen, &prefix, &content, &suffix));
+			IPC_SET_ADDR(answer, addrlen);
+			IPC_SET_PREFIX(answer, prefix);
+			IPC_SET_CONTENT(answer, content);
+			IPC_SET_SUFFIX(answer, suffix);
+			*answer_count = 4;
+			return EOK;
+		case NET_NIL_ADDR:
+			ERROR_PROPAGATE(nildummy_addr_message(IPC_GET_DEVICE(call),
+			    &address));
+			return measured_strings_reply(address, 1);
+		case NET_NIL_BROADCAST_ADDR:
+			ERROR_PROPAGATE(nildummy_addr_message(IPC_GET_DEVICE(call),
+			    &address));
+			return measured_strings_reply(address, 1);
+		case IPC_M_CONNECT_TO_ME:
+			return nildummy_register_message(NIL_GET_PROTO(call),
+			    IPC_GET_PHONE(call));
+	}
+	
+	return ENOTSUP;
+}
+
+#ifndef CONFIG_NETIF_NIL_BUNDLE
+
+/** Default thread for new connections.
+ *
+ * @param[in] iid   The initial message identifier.
+ * @param[in] icall The initial message call structure.
+ *
+ */
+static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0(iid, EOK);
+	
+	while(true) {
+		ipc_call_t answer;
+		int answer_count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &answer_count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = nil_module_message_standalone(NAME, callid, &call, &answer,
+		    &answer_count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, answer_count);
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	/* Start the module */
+	if (ERROR_OCCURRED(nil_module_start_standalone(nil_client_connection)))
+		return ERROR_CODE;
+	
+	return EOK;
+}
+
+#endif /* CONFIG_NETIF_NIL_BUNDLE */
+
+/** @}
+ */
Index: uspace/srv/net/nil/nildummy/nildummy.h
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/nil/nildummy/nildummy.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+#ifndef __NET_NILDUMMY_H__
+#define __NET_NILDUMMY_H__
+
+#include <fibril_synch.h>
+#include <ipc/services.h>
+
+#include <net_device.h>
+#include <adt/measured_strings.h>
+
+/** 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 device specific data pointer.
+ *  @see nildummy_device
+ */
+typedef nildummy_device_t *		nildummy_device_ref;
+
+/** Type definition of the dummy nil protocol specific data.
+ *  @see nildummy_proto
+ */
+typedef struct nildummy_proto	nildummy_proto_t;
+
+/** Type definition of the dummy nil protocol specific data pointer.
+ *  @see nildummy_proto
+ */
+typedef nildummy_proto_t *		nildummy_proto_ref;
+
+/** Dummy nil device map.
+ *  Maps devices to the dummy nil device specific data.
+ *  @see device.h
+ */
+DEVICE_MAP_DECLARE(nildummy_devices, nildummy_device_t)
+
+/** Dummy nil device specific data.
+ */
+struct	nildummy_device{
+	/** 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_ref addr;
+	/** Actual device hardware address data.
+	 */
+	char * addr_data;
+};
+
+/** Dummy nil protocol specific data.
+ */
+struct nildummy_proto{
+	/** Protocol service.
+	 */
+	services_t service;
+	/** Protocol module phone.
+	 */
+	int phone;
+};
+
+/** Dummy nil global data.
+ */
+struct	nildummy_globals{
+	/** Networking module phone.
+	 */
+	int net_phone;
+	/** Safety 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;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/nil/nildummy/nildummy_module.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/nil/nildummy/nildummy_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,111 @@
+/*
+ * 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 <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_modules.h>
+#include <net_interface.h>
+#include <packet/packet.h>
+#include <nil_local.h>
+
+#include "nildummy.h"
+
+/** Start the dummy nil 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.
+ *
+ */
+int nil_module_start_standalone(async_client_conn_t client_connection)
+{
+	ERROR_DECLARE;
+	
+	async_set_client_connection(client_connection);
+	int net_phone = net_connect_module(SERVICE_NETWORKING);
+	ERROR_PROPAGATE(pm_init());
+	
+	ipcarg_t phonehash;
+	if (ERROR_OCCURRED(nil_initialize(net_phone))
+	    || ERROR_OCCURRED(REGISTER_ME(SERVICE_NILDUMMY, &phonehash))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+	
+	async_manager();
+	
+	pm_destroy();
+	return EOK;
+}
+
+/** 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.
+ *
+ */
+int nil_module_message_standalone(const char *name, ipc_callid_t callid,
+    ipc_call_t *call, ipc_call_t *answer, int *answer_count)
+{
+	return nil_message_standalone(name, callid, call, answer, answer_count);
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/Makefile
===================================================================
--- uspace/srv/net/tl/icmp/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/icmp/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,39 @@
+#
+# 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 = ../../../..
+LIBS = $(LIBNET_PREFIX)/libnet.a $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+BINARY = icmp
+
+SOURCES = \
+	icmp.c \
+	icmp_module.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/icmp/icmp.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,883 @@
+/*
+ * 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 implementation.
+ *  @see icmp.h
+ */
+
+#include <async.h>
+#include <atomic.h>
+#include <fibril.h>
+#include <fibril_synch.h>
+#include <stdint.h>
+#include <str.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <net_err.h>
+#include <net_messages.h>
+#include <net_modules.h>
+#include <packet/packet_client.h>
+#include <packet_remote.h>
+#include <net_byteorder.h>
+#include <net_checksum.h>
+#include <icmp_api.h>
+#include <icmp_client.h>
+#include <icmp_codes.h>
+#include <icmp_common.h>
+#include <icmp_interface.h>
+#include <il_interface.h>
+#include <inet.h>
+#include <ip_client.h>
+#include <ip_interface.h>
+#include <ip_protocols.h>
+#include <net_interface.h>
+#include <socket_codes.h>
+#include <socket_errno.h>
+#include <tl_messages.h>
+#include <tl_interface.h>
+#include <tl_local.h>
+#include <icmp_messages.h>
+#include <icmp_header.h>
+
+#include "icmp.h"
+#include "icmp_module.h"
+
+/** ICMP module name.
+ */
+#define NAME	"ICMP protocol"
+
+/** Default ICMP error reporting.
+ */
+#define NET_DEFAULT_ICMP_ERROR_REPORTING	true
+
+/** Default ICMP echo replying.
+ */
+#define NET_DEFAULT_ICMP_ECHO_REPLYING		true
+
+/** Original datagram length in bytes transfered to the error notification message.
+ */
+#define ICMP_KEEP_LENGTH	8
+
+/** Free identifier numbers pool start.
+ */
+#define ICMP_FREE_IDS_START	1
+
+/** Free identifier numbers pool end.
+ */
+#define ICMP_FREE_IDS_END	MAX_UINT16
+
+/** Computes the ICMP datagram checksum.
+ *  @param[in,out] header The ICMP datagram header.
+ *  @param[in] length The total datagram length.
+ *  @returns The computed checksum.
+ */
+#define ICMP_CHECKSUM(header, length)		htons(ip_checksum((uint8_t *) (header), (length)))
+
+/** An echo request datagrams pattern.
+ */
+#define ICMP_ECHO_TEXT					"Hello from HelenOS."
+
+/** Computes an ICMP reply data key.
+ *  @param[in] id The message identifier.
+ *  @param[in] sequence The message sequence number.
+ *  @returns The computed ICMP reply data key.
+ */
+#define ICMP_GET_REPLY_KEY(id, sequence)	(((id) << 16) | (sequence &0xFFFF))
+
+/** Processes the received ICMP packet.
+ *  Is used as an entry point from the underlying IP module.
+ *  Releases the packet on error.
+ *  @param device_id The device identifier. Ignored parameter.
+ *  @param[in,out] packet The received packet.
+ *  @param receiver The target service. Ignored parameter.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the icmp_process_packet() function.
+ */
+int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error);
+
+/** Processes the received ICMP packet.
+ *  Notifies the destination socket application.
+ *  @param[in,out] packet The received packet.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns EINVAL if the stored packet address is not the an_addr_t.
+ *  @returns EINVAL if the packet does not contain any data.
+ *  @returns NO_DATA if the packet content is shorter than the user datagram header.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EADDRNOTAVAIL if the destination socket does not exist.
+ *  @returns Other error codes as defined for the ip_client_process_packet() function.
+ */
+int icmp_process_packet(packet_t packet, services_t error);
+
+/** Processes the client messages.
+ *  Remembers the assigned identifier and sequence numbers.
+ *  Runs until the client module disconnects.
+ *  @param[in] callid The message identifier.
+ *  @param[in] call The message parameters.
+ *  @returns EOK.
+ *  @see icmp_interface.h
+ *  @see icmp_api.h
+ */
+int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
+
+/** Processes the generic client messages.
+ *  @param[in] call The message parameters.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for the packet_translate() function.
+ *  @returns Other error codes as defined for the icmp_destination_unreachable_msg() function.
+ *  @returns Other error codes as defined for the icmp_source_quench_msg() function.
+ *  @returns Other error codes as defined for the icmp_time_exceeded_msg() function.
+ *  @returns Other error codes as defined for the icmp_parameter_problem_msg() function.
+ *  @see icmp_interface.h
+ */
+int icmp_process_message(ipc_call_t * call);
+
+/** Releases the packet and returns the result.
+ *  @param[in] packet The packet queue to be released.
+ *  @param[in] result The result to be returned.
+ *  @returns The result parameter.
+ */
+int icmp_release_and_return(packet_t packet, int result);
+
+/** Requests an echo message.
+ *  Sends a packet with specified parameters to the target host and waits for the reply upto the given timeout.
+ *  Blocks the caller until the reply or the timeout occurs.
+ *  @param[in] id The message identifier.
+ *  @param[in] sequence The message sequence parameter.
+ *  @param[in] size The message data length in bytes.
+ *  @param[in] timeout The timeout in miliseconds.
+ *  @param[in] ttl The time to live.
+ *  @param[in] tos The type of service.
+ *  @param[in] dont_fragment The value indicating whether the datagram must not be fragmented. Is used as a MTU discovery.
+ *  @param[in] addr The target host address.
+ *  @param[in] addrlen The torget host address length.
+ *  @returns ICMP_ECHO on success.
+ *  @returns ETIMEOUT if the reply has not arrived before the timeout.
+ *  @returns ICMP type of the received error notification. 
+ *  @returns EINVAL if the addrlen parameter is less or equal to zero (<=0).
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EPARTY if there was an internal error.
+ */
+int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen);
+
+/** Prepares the ICMP error packet.
+ *  Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes.
+ *  Prefixes and returns the ICMP header.
+ *  @param[in,out] packet The original packet.
+ *  @returns The prefixed ICMP header.
+ *  @returns NULL on errors.
+ */
+icmp_header_ref icmp_prepare_packet(packet_t packet);
+
+/** Sends the ICMP message.
+ *  Sets the message type and code and computes the checksum.
+ *  Error messages are sent only if allowed in the configuration.
+ *  Releases the packet on errors.
+ *  @param[in] type The message type.
+ *  @param[in] code The message code.
+ *  @param[in] packet The message packet to be sent.
+ *  @param[in] header The ICMP header.
+ *  @param[in] error The error service to be announced. Should be SERVICE_ICMP or zero (0).
+ *  @param[in] ttl The time to live.
+ *  @param[in] tos The type of service.
+ *  @param[in] dont_fragment The value indicating whether the datagram must not be fragmented. Is used as a MTU discovery.
+ *  @returns EOK on success.
+ *  @returns EPERM if the error message is not allowed.
+ */
+int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment);
+
+/** Tries to set the pending reply result as the received message type.
+ *  If the reply data is not present, the reply timed out and the other fibril
+ *  is already awake.
+ *  Releases the packet.
+ *  @param[in] packet The received reply message.
+ *  @param[in] header The ICMP message header.
+ *  @param[in] type The received reply message type.
+ *  @param[in] code The received reply message code.
+ *  @returns EOK.
+ */
+int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code);
+
+/** Assigns a new identifier for the connection.
+ *  Fills the echo data parameter with the assigned values.
+ *  @param[in,out] echo_data The echo data to be bound.
+ *  @returns Index of the inserted echo data.
+ *  @returns EBADMEM if the echo_data parameter is NULL.
+ *  @returns ENOTCONN if no free identifier have been found.
+ */
+int icmp_bind_free_id(icmp_echo_ref echo_data);
+
+/** ICMP global data.
+ */
+icmp_globals_t	icmp_globals;
+
+INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
+
+INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t);
+
+int icmp_echo_msg(int icmp_phone, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen){
+	icmp_echo_ref echo_data;
+	int res;
+
+	fibril_rwlock_write_lock(&icmp_globals.lock);
+	// use the phone as the echo data index
+	echo_data = icmp_echo_data_find(&icmp_globals.echo_data, icmp_phone);
+	if(! echo_data){
+		res = ENOENT;
+	}else{
+		res = icmp_echo(echo_data->identifier, echo_data->sequence_number, size, timeout, ttl, tos, dont_fragment, addr, addrlen);
+		if(echo_data->sequence_number < MAX_UINT16){
+			++ echo_data->sequence_number;
+		}else{
+			echo_data->sequence_number = 0;
+		}
+	}
+	fibril_rwlock_write_unlock(&icmp_globals.lock);
+	return res;
+}
+
+int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen){
+	ERROR_DECLARE;
+
+	icmp_header_ref header;
+	packet_t packet;
+	size_t length;
+	uint8_t * data;
+	icmp_reply_ref reply;
+	int reply_key;
+	int result;
+	int index;
+
+	if(addrlen <= 0){
+		return EINVAL;
+	}
+	length = (size_t) addrlen;
+	// TODO do not ask all the time
+	ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension));
+	packet = packet_get_4_remote(icmp_globals.net_phone, size, icmp_globals.packet_dimension.addr_len, ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix, icmp_globals.packet_dimension.suffix);
+	if(! packet){
+		return ENOMEM;
+	}
+
+	// prepare the requesting packet
+	// set the destination address
+	if(ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr, length))){
+		return icmp_release_and_return(packet, ERROR_CODE);
+	}
+	// allocate space in the packet
+	data = (uint8_t *) packet_suffix(packet, size);
+	if(! data){
+		return icmp_release_and_return(packet, ENOMEM);
+	}
+	// fill the data
+	length = 0;
+	while(size > length + sizeof(ICMP_ECHO_TEXT)){
+		memcpy(data + length, ICMP_ECHO_TEXT, sizeof(ICMP_ECHO_TEXT));
+		length += sizeof(ICMP_ECHO_TEXT);
+	}
+	memcpy(data + length, ICMP_ECHO_TEXT, size - length);
+	// prefix the header
+	header = PACKET_PREFIX(packet, icmp_header_t);
+	if(! header){
+		return icmp_release_and_return(packet, ENOMEM);
+	}
+	bzero(header, sizeof(*header));
+	header->un.echo.identifier = id;
+	header->un.echo.sequence_number = sequence;
+
+	// prepare the reply structure
+	reply = malloc(sizeof(*reply));
+	if(! reply){
+		return icmp_release_and_return(packet, ENOMEM);
+	}
+	fibril_mutex_initialize(&reply->mutex);
+	fibril_mutex_lock(&reply->mutex);
+	fibril_condvar_initialize(&reply->condvar);
+	reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number);
+	index = icmp_replies_add(&icmp_globals.replies, reply_key, reply);
+	if(index < 0){
+		free(reply);
+		return icmp_release_and_return(packet, index);
+	}
+
+	// unlock the globals so that we can wait for the reply
+	fibril_rwlock_write_unlock(&icmp_globals.lock);
+
+	// send the request
+	icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment);
+
+	// wait for the reply
+	// timeout in microseconds
+	if(ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex, timeout * 1000))){
+		result = ERROR_CODE;
+	}else{
+		// read the result
+		result = reply->result;
+	}
+
+	// drop the reply mutex before locking the globals again
+	fibril_mutex_unlock(&reply->mutex);
+	fibril_rwlock_write_lock(&icmp_globals.lock);
+
+	// destroy the reply structure
+	icmp_replies_exclude_index(&icmp_globals.replies, index);
+	return result;
+}
+
+int icmp_destination_unreachable_msg(int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet){
+	icmp_header_ref header;
+
+	header = icmp_prepare_packet(packet);
+	if(! header){
+		return icmp_release_and_return(packet, ENOMEM);
+	}
+	if(mtu){
+		header->un.frag.mtu = mtu;
+	}
+	return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0);
+}
+
+int icmp_source_quench_msg(int icmp_phone, packet_t packet){
+	icmp_header_ref header;
+
+	header = icmp_prepare_packet(packet);
+	if(! header){
+		return icmp_release_and_return(packet, ENOMEM);
+	}
+	return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0);
+}
+
+int icmp_time_exceeded_msg(int icmp_phone, icmp_code_t code, packet_t packet){
+	icmp_header_ref header;
+
+	header = icmp_prepare_packet(packet);
+	if(! header){
+		return icmp_release_and_return(packet, ENOMEM);
+	}
+	return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0);
+}
+
+int icmp_parameter_problem_msg(int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet){
+	icmp_header_ref header;
+
+	header = icmp_prepare_packet(packet);
+	if(! header){
+		return icmp_release_and_return(packet, ENOMEM);
+	}
+	header->un.param.pointer = pointer;
+	return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0);
+}
+
+icmp_header_ref icmp_prepare_packet(packet_t packet){
+	icmp_header_ref header;
+	size_t header_length;
+	size_t total_length;
+
+	total_length = packet_get_data_length(packet);
+	if(total_length <= 0){
+		return NULL;
+	}
+	header_length = ip_client_header_length(packet);
+	if(header_length <= 0){
+		return NULL;
+	}
+	// truncate if longer than 64 bits (without the IP header)
+	if((total_length > header_length + ICMP_KEEP_LENGTH)
+		&& (packet_trim(packet, 0, total_length - header_length - ICMP_KEEP_LENGTH) != EOK)){
+		return NULL;
+	}
+	header = PACKET_PREFIX(packet, icmp_header_t);
+	if(! header){
+		return NULL;
+	}
+	bzero(header, sizeof(*header));
+	return header;
+}
+
+int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment){
+	ERROR_DECLARE;
+
+	// do not send an error if disabled
+	if(error && (! icmp_globals.error_reporting)){
+		return icmp_release_and_return(packet, EPERM);
+	}
+	header->type = type;
+	header->code = code;
+	header->checksum = 0;
+	header->checksum = ICMP_CHECKSUM(header, packet_get_data_length(packet));
+	if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0))){
+		return icmp_release_and_return(packet, ERROR_CODE);
+	}
+	return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error);
+}
+
+int icmp_connect_module(services_t service, suseconds_t timeout){
+	icmp_echo_ref echo_data;
+	icmp_param_t id;
+	int index;
+
+	echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data));
+	if(! echo_data){
+		return ENOMEM;
+	}
+	// assign a new identifier
+	fibril_rwlock_write_lock(&icmp_globals.lock);
+	index = icmp_bind_free_id(echo_data);
+	if(index < 0){
+		free(echo_data);
+		fibril_rwlock_write_unlock(&icmp_globals.lock);
+		return index;
+	}else{
+		id = echo_data->identifier;
+		fibril_rwlock_write_unlock(&icmp_globals.lock);
+		// return the echo data identifier as the ICMP phone
+		return id;
+	}
+}
+
+int icmp_initialize(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+
+	measured_string_t names[] = {{str_dup("ICMP_ERROR_REPORTING"), 20}, {str_dup("ICMP_ECHO_REPLYING"), 18}};
+	measured_string_ref configuration;
+	size_t count = sizeof(names) / sizeof(measured_string_t);
+	char * 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.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg);
+	if(icmp_globals.ip_phone < 0){
+		return icmp_globals.ip_phone;
+	}
+	ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension));
+	icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
+	icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
+	// get configuration
+	icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
+	icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
+	configuration = &names[0];
+	ERROR_PROPAGATE(net_get_conf_req(icmp_globals.net_phone, &configuration, count, &data));
+	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;
+}
+
+int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
+	ERROR_DECLARE;
+
+	if(ERROR_OCCURRED(icmp_process_packet(packet, error))){
+		return icmp_release_and_return(packet, ERROR_CODE);
+	}
+
+	return EOK;
+}
+
+int icmp_process_packet(packet_t packet, services_t error){
+	ERROR_DECLARE;
+
+	size_t length;
+	uint8_t * src;
+	int addrlen;
+	int result;
+	void * data;
+	icmp_header_ref header;
+	icmp_type_t type;
+	icmp_code_t code;
+
+	if(error){
+		switch(error){
+			case SERVICE_ICMP:
+				// process error
+				result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
+				if(result < 0){
+					return result;
+				}
+				length = (size_t) result;
+				// remove the error header
+				ERROR_PROPAGATE(packet_trim(packet, length, 0));
+				break;
+			default:
+				return ENOTSUP;
+		}
+	}
+	// get rid of the ip header
+	length = ip_client_header_length(packet);
+	ERROR_PROPAGATE(packet_trim(packet, length, 0));
+
+	length = packet_get_data_length(packet);
+	if(length <= 0){
+		return EINVAL;
+	}
+	if(length < ICMP_HEADER_SIZE){
+		return EINVAL;
+	}
+	data = packet_get_data(packet);
+	if(! data){
+		return EINVAL;
+	}
+	// get icmp header
+	header = (icmp_header_ref) data;
+	// checksum
+	if(header->checksum){
+		while(ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){
+			// set the original message type on error notification
+			// type swap observed in Qemu
+			if(error){
+				switch(header->type){
+					case ICMP_ECHOREPLY:
+						header->type = ICMP_ECHO;
+						continue;
+				}
+			}
+			return EINVAL;
+		}
+	}
+	switch(header->type){
+		case ICMP_ECHOREPLY:
+			if(error){
+				return icmp_process_echo_reply(packet, header, type, code);
+			}else{
+				return icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
+			}
+		case ICMP_ECHO:
+			if(error){
+				return icmp_process_echo_reply(packet, header, type, code);
+			// do not send a reply if disabled
+			}else if(icmp_globals.echo_replying){
+				addrlen = packet_get_addr(packet, &src, NULL);
+				if((addrlen > 0)
+				// set both addresses to the source one (avoids the source address deletion before setting the destination one)
+					&& (packet_set_addr(packet, src, src, (size_t) addrlen) == EOK)){
+					// send the reply
+					icmp_send_packet(ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0);
+					return EOK;
+				}else{
+					return EINVAL;
+				}
+			}else{
+				return EPERM;
+			}
+		case ICMP_DEST_UNREACH:
+		case ICMP_SOURCE_QUENCH:
+		case ICMP_REDIRECT:
+		case ICMP_ALTERNATE_ADDR:
+		case ICMP_ROUTER_ADV:
+		case ICMP_ROUTER_SOL:
+		case ICMP_TIME_EXCEEDED:
+		case ICMP_PARAMETERPROB:
+		case ICMP_CONVERSION_ERROR:
+		case ICMP_REDIRECT_MOBILE:
+		case ICMP_SKIP:
+		case ICMP_PHOTURIS:
+			ip_received_error_msg(icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP);
+			return EOK;
+		default:
+			return ENOTSUP;
+	}
+}
+
+int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code){
+	int reply_key;
+	icmp_reply_ref reply;
+
+	// compute the reply key
+	reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number);
+	pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
+	// lock the globals
+	fibril_rwlock_write_lock(&icmp_globals.lock);
+	// find the pending reply
+	reply = icmp_replies_find(&icmp_globals.replies, reply_key);
+	if(reply){
+		// set the result
+		reply->result = type;
+		// notify the waiting fibril
+		fibril_condvar_signal(&reply->condvar);
+	}
+	fibril_rwlock_write_unlock(&icmp_globals.lock);
+	return EOK;
+}
+
+int icmp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	ERROR_DECLARE;
+
+	packet_t packet;
+
+	*answer_count = 0;
+	switch(IPC_GET_METHOD(*call)){
+		case NET_TL_RECEIVED:
+			if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
+				ERROR_CODE = icmp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_ICMP, IPC_GET_ERROR(call));
+			}
+			return ERROR_CODE;
+		case NET_ICMP_INIT:
+			return icmp_process_client_messages(callid, * call);
+		default:
+			return icmp_process_message(call);
+	}
+	return ENOTSUP;
+}
+
+int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
+	ERROR_DECLARE;
+
+	bool keep_on_going = true;
+//	fibril_rwlock_t			lock;
+	ipc_call_t answer;
+	int answer_count;
+	size_t length;
+	struct sockaddr * addr;
+	ipc_callid_t data_callid;
+	icmp_echo_ref echo_data;
+	int res;
+
+	/*
+	 * Accept the connection
+	 *  - Answer the first NET_ICMP_INIT call.
+	 */
+	res = EOK;
+	answer_count = 0;
+
+//	fibril_rwlock_initialize(&lock);
+
+	echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data));
+	if(! echo_data){
+		return ENOMEM;
+	}
+
+	// assign a new identifier
+	fibril_rwlock_write_lock(&icmp_globals.lock);
+	res = icmp_bind_free_id(echo_data);
+	fibril_rwlock_write_unlock(&icmp_globals.lock);
+	if(res < 0){
+		free(echo_data);
+		return res;
+	}
+
+	while(keep_on_going){
+
+		// answer the call
+		answer_call(callid, res, &answer, answer_count);
+
+		// refresh data
+		refresh_answer(&answer, &answer_count);
+
+		// get the next call
+		callid = async_get_call(&call);
+
+		// process the call
+		switch(IPC_GET_METHOD(call)){
+			case IPC_M_PHONE_HUNGUP:
+				keep_on_going = false;
+				res = EHANGUP;
+				break;
+			case NET_ICMP_ECHO:
+//				fibril_rwlock_write_lock(&lock);
+				if(! async_data_write_receive(&data_callid, &length)){
+					res = EINVAL;
+				}else{
+					addr = malloc(length);
+					if(! addr){
+						res = ENOMEM;
+					}else{
+						if(! ERROR_OCCURRED(async_data_write_finalize(data_callid, addr, length))){
+							fibril_rwlock_write_lock(&icmp_globals.lock);
+							res = icmp_echo(echo_data->identifier, echo_data->sequence_number, ICMP_GET_SIZE(call), ICMP_GET_TIMEOUT(call), ICMP_GET_TTL(call), ICMP_GET_TOS(call), ICMP_GET_DONT_FRAGMENT(call), addr, (socklen_t) length);
+							fibril_rwlock_write_unlock(&icmp_globals.lock);
+							free(addr);
+							if(echo_data->sequence_number < MAX_UINT16){
+								++ echo_data->sequence_number;
+							}else{
+								echo_data->sequence_number = 0;
+							}
+						}else{
+							res = ERROR_CODE;
+						}
+					}
+				}
+//				fibril_rwlock_write_unlock(&lock);
+				break;
+			default:
+				res = icmp_process_message(&call);
+		}
+	}
+
+	// release the identifier
+	fibril_rwlock_write_lock(&icmp_globals.lock);
+	icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier);
+	fibril_rwlock_write_unlock(&icmp_globals.lock);
+	return res;
+}
+
+int icmp_process_message(ipc_call_t * call){
+	ERROR_DECLARE;
+
+	packet_t packet;
+
+	switch(IPC_GET_METHOD(*call)){
+		case NET_ICMP_DEST_UNREACH:
+			if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
+				ERROR_CODE = icmp_destination_unreachable_msg(0, ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet);
+			}
+			return ERROR_CODE;
+		case NET_ICMP_SOURCE_QUENCH:
+			if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
+				ERROR_CODE = icmp_source_quench_msg(0, packet);
+			}
+			return ERROR_CODE;
+		case NET_ICMP_TIME_EXCEEDED:
+			if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
+				ERROR_CODE = icmp_time_exceeded_msg(0, ICMP_GET_CODE(call), packet);
+			}
+			return ERROR_CODE;
+		case NET_ICMP_PARAMETERPROB:
+			if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
+				ERROR_CODE = icmp_parameter_problem_msg(0, ICMP_GET_CODE(call), ICMP_GET_POINTER(call), packet);
+			}
+			return ERROR_CODE;
+		default:
+			return ENOTSUP;
+	}
+}
+
+int icmp_release_and_return(packet_t packet, int result){
+	pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
+	return result;
+}
+
+int icmp_bind_free_id(icmp_echo_ref echo_data){
+	icmp_param_t index;
+
+	if(! echo_data){
+		return EBADMEM;
+	}
+	// from the last used one
+	index = icmp_globals.last_used_id;
+	do{
+		++ index;
+		// til the range end
+		if(index >= ICMP_FREE_IDS_END){
+			// start from the range beginning
+			index = ICMP_FREE_IDS_START - 1;
+			do{
+				++ index;
+				// til the last used one
+				if(index >= icmp_globals.last_used_id){
+					// none found
+					return ENOTCONN;
+				}
+			}while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
+			// found, break immediately
+			break;
+		}
+	}while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
+	echo_data->identifier = index;
+	echo_data->sequence_number = 0;
+	return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
+}
+
+/** Default thread for new connections.
+ *
+ *  @param[in] iid The initial message identifier.
+ *  @param[in] icall The initial message call structure.
+ *
+ */
+static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
+{
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0(iid, EOK);
+	
+	while(true) {
+		ipc_call_t answer;
+		int answer_count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &answer_count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = tl_module_message_standalone(callid, &call, &answer,
+		    &answer_count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, answer_count);
+	}
+}
+
+/** Starts the module.
+ *
+ *  @param argc The count of the command line arguments. Ignored parameter.
+ *  @param argv The command line parameters. Ignored parameter.
+ *
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module start function.
+ *
+ */
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	/* Start the module */
+	if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
+		return ERROR_CODE;
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/icmp.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/icmp/icmp.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2008 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP module.
+ */
+
+#ifndef __NET_ICMP_H__
+#define __NET_ICMP_H__
+
+#include <fibril_synch.h>
+
+#include <icmp_codes.h>
+#include <adt/int_map.h>
+#include <icmp_header.h>
+
+/** Type definition of the ICMP reply data.
+ *  @see icmp_reply
+ */
+typedef struct icmp_reply	icmp_reply_t;
+
+/** Type definition of the ICMP reply data pointer.
+ *  @see icmp_reply
+ */
+typedef icmp_reply_t *	icmp_reply_ref;
+
+/** Type definition of the ICMP global data.
+ *  @see icmp_globals
+ */
+typedef struct icmp_globals	icmp_globals_t;
+
+/** Pending replies map.
+ *  Maps message identifiers to the pending replies.
+ *  Sending fibril waits for its associated reply event.
+ *  Receiving fibril sets the associated reply with the return value and signals the event.
+ */
+INT_MAP_DECLARE(icmp_replies, icmp_reply_t);
+
+/** Echo specific data map.
+ *  The bundle module gets an identifier of the assigned echo specific data while connecting.
+ *  The identifier is used in the future semi-remote calls instead of the ICMP phone.
+ */
+INT_MAP_DECLARE(icmp_echo_data, icmp_echo_t);
+
+/** ICMP reply data.
+ */
+struct icmp_reply{
+	/** Reply result.
+	 */
+	int result;
+	/** Safety lock.
+	 */
+	fibril_mutex_t mutex;
+	/** Received or timeouted reply signaling.
+	 */
+	fibril_condvar_t condvar;
+};
+
+/** ICMP global data.
+ */
+struct	icmp_globals{
+	/** IP module phone.
+	 */
+	int ip_phone;
+	/** Packet dimension.
+	 */
+	packet_dimension_t packet_dimension;
+	/** Networking module phone.
+	 */
+	int net_phone;
+	/** Indicates whether ICMP error reporting is enabled.
+	 */
+	int error_reporting;
+	/** Indicates whether ICMP echo replying (ping) is enabled.
+	 */
+	int echo_replying;
+	/** The last used identifier number.
+	 */
+	icmp_param_t last_used_id;
+	/** The budled modules assigned echo specific data.
+	 */
+	icmp_echo_data_t echo_data;
+	/** Echo timeout locks.
+	 */
+	icmp_replies_t replies;
+	/** Safety lock.
+	 */
+	fibril_rwlock_t lock;
+};
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/tl/icmp/icmp_module.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/icmp/icmp_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,101 @@
+/*
+ * 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 <async.h>
+#include <stdio.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_modules.h>
+#include <packet/packet.h>
+#include <net_interface.h>
+#include <tl_local.h>
+
+#include "icmp.h"
+#include "icmp_module.h"
+
+/** ICMP module global data.
+ */
+extern icmp_globals_t	icmp_globals;
+
+/** Starts the ICMP 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.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the arp_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int tl_module_start_standalone(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+
+	ipcarg_t phonehash;
+
+	async_set_client_connection(client_connection);
+	icmp_globals.net_phone = net_connect_module(SERVICE_NETWORKING);
+	if(icmp_globals.net_phone < 0){
+		return icmp_globals.net_phone;
+	}
+	ERROR_PROPAGATE(pm_init());
+	if(ERROR_OCCURRED(icmp_initialize(client_connection))
+		|| ERROR_OCCURRED(REGISTER_ME(SERVICE_ICMP, &phonehash))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+/** Processes the ICMP message.
+ *  @param[in] callid The message identifier.
+ *  @param[in] call The message parameters.
+ *  @param[out] answer The message answer parameters.
+ *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the icmp_message() function.
+ */
+int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	return icmp_message_standalone(callid, call, answer, answer_count);
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/icmp_module.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp_module.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/icmp/icmp_module.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,66 @@
+/*
+ * 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>
+
+/** Initializes the ICMP module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int icmp_initialize(async_client_conn_t client_connection);
+
+/** Processes the ICMP message.
+ *  @param[in] callid The message identifier.
+ *  @param[in] call The message parameters.
+ *  @param[out] answer The message answer parameters.
+ *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see icmp_interface.h
+ *  @see IS_NET_ICMP_MESSAGE()
+ */
+int icmp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/tcp/Makefile
===================================================================
--- uspace/srv/net/tl/tcp/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/tcp/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,39 @@
+#
+# 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 = ../../../..
+LIBS = $(LIBNET_PREFIX)/libnet.a $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+BINARY = tcp
+
+SOURCES = \
+	tcp.c \
+	tcp_module.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,2061 @@
+/*
+ * 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 implementation.
+ *  @see tcp.h
+ */
+
+#include <assert.h>
+#include <async.h>
+#include <fibril_synch.h>
+#include <malloc.h>
+//TODO remove stdio
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_messages.h>
+#include <net_modules.h>
+#include <adt/dynamic_fifo.h>
+#include <packet/packet_client.h>
+#include <packet_remote.h>
+#include <net_checksum.h>
+#include <in.h>
+#include <in6.h>
+#include <inet.h>
+#include <ip_client.h>
+#include <ip_interface.h>
+#include <ip_protocols.h>
+#include <icmp_client.h>
+#include <icmp_interface.h>
+#include <net_interface.h>
+#include <socket_codes.h>
+#include <socket_errno.h>
+#include <tcp_codes.h>
+#include <socket_core.h>
+#include <socket_messages.h>
+#include <tl_common.h>
+#include <tl_messages.h>
+#include <tl_local.h>
+#include <tl_interface.h>
+
+#include "tcp.h"
+#include "tcp_header.h"
+#include "tcp_module.h"
+
+/** TCP module name.
+ */
+#define NAME	"TCP protocol"
+
+/** The TCP window default value.
+ */
+#define NET_DEFAULT_TCP_WINDOW	10240
+
+/** Initial timeout for new connections.
+ */
+#define NET_DEFAULT_TCP_INITIAL_TIMEOUT	3000000L
+
+/** Default timeout for closing.
+ */
+#define NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT	2000L
+
+/** The initial outgoing sequence number.
+ */
+#define TCP_INITIAL_SEQUENCE_NUMBER		2999
+
+/** Maximum TCP fragment size.
+ */
+#define MAX_TCP_FRAGMENT_SIZE	65535
+
+/** Free ports pool start.
+ */
+#define TCP_FREE_PORTS_START	1025
+
+/** Free ports pool end.
+ */
+#define TCP_FREE_PORTS_END		65535
+
+/** Timeout for connection initialization, SYN sent.
+ */
+#define TCP_SYN_SENT_TIMEOUT	1000000L
+
+/** The maximum number of timeouts in a row before singaling connection lost.
+ */
+#define TCP_MAX_TIMEOUTS		8
+
+/** The number of acknowledgements before retransmit.
+ */
+#define TCP_FAST_RETRANSMIT_COUNT	3
+
+/** Returns a value indicating whether the value is in the interval respecting the possible overflow.
+ *  The high end and/or the value may overflow, be lower than the low value.
+ *  @param[in] lower The last value before the interval.
+ *  @param[in] value The value to be checked.
+ *  @param[in] higher_equal The last value in the interval.
+ */
+#define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal)	((((lower) < (value)) && (((value) <= (higher_equal)) || ((higher_equal) < (lower)))) || (((value) <= (higher_equal)) && ((higher_equal) < (lower))))
+
+/** Type definition of the TCP timeout.
+ *  @see tcp_timeout
+ */
+typedef struct tcp_timeout	tcp_timeout_t;
+
+/** Type definition of the TCP timeout pointer.
+ *  @see tcp_timeout
+ */
+typedef tcp_timeout_t *	tcp_timeout_ref;
+
+/** TCP reply timeout data.
+ *  Used as a timeouting fibril argument.
+ *  @see tcp_timeout()
+ */
+struct tcp_timeout{
+	/** TCP global data are going to be read only.
+	 */
+	int globals_read_only;
+	/** Socket port.
+	 */
+	int port;
+	/** Local sockets.
+	 */
+	socket_cores_ref local_sockets;
+	/** Socket identifier.
+	 */
+	int socket_id;
+	/** Socket state.
+	 */
+	tcp_socket_state_t state;
+	/** Sent packet sequence number.
+	 */
+	int sequence_number;
+	/** Timeout in microseconds.
+	 */
+	suseconds_t timeout;
+	/** Port map key.
+	 */
+	char * key;
+	/** Port map key length.
+	 */
+	size_t key_length;
+};
+
+/** Releases the packet and returns the result.
+ *  @param[in] packet The packet queue to be released.
+ *  @param[in] result The result to be returned.
+ *  @return The result parameter.
+ */
+int tcp_release_and_return(packet_t packet, int result);
+
+void tcp_prepare_operation_header(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize);
+int tcp_prepare_timeout(int (*timeout_function)(void * tcp_timeout_t), socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, int globals_read_only);
+void tcp_free_socket_data(socket_core_ref socket);
+int tcp_timeout(void * data);
+int tcp_release_after_timeout(void * data);
+int tcp_process_packet(device_id_t device_id, packet_t packet, services_t error);
+int tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen);
+int tcp_queue_prepare_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length);
+int tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length);
+packet_t tcp_get_packets_to_send(socket_core_ref socket, tcp_socket_data_ref socket_data);
+void tcp_send_packets(device_id_t device_id, packet_t packet);
+void tcp_process_acknowledgement(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header);
+packet_t tcp_send_prepare_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number);
+packet_t tcp_prepare_copy(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number);
+void tcp_retransmit_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number);
+int tcp_create_notification_packet(packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize);
+void tcp_refresh_socket_data(tcp_socket_data_ref socket_data);
+void tcp_initialize_socket_data(tcp_socket_data_ref socket_data);
+int tcp_process_listen(socket_core_ref listening_socket, tcp_socket_data_ref listening_socket_data, tcp_header_ref header, packet_t packet, struct sockaddr * src, struct sockaddr * dest, size_t addrlen);
+int tcp_process_syn_sent(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet);
+int tcp_process_syn_received(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet);
+int tcp_process_established(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet, int fragments, size_t total_length);
+int tcp_queue_received_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length);
+
+int tcp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error);
+int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
+int tcp_listen_message(socket_cores_ref local_sockets, int socket_id, int backlog);
+int tcp_connect_message(socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen);
+int tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen);
+int tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags);
+int tcp_accept_message(socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen);
+int tcp_close_message(socket_cores_ref local_sockets, int socket_id);
+
+/** TCP global data.
+ */
+tcp_globals_t	tcp_globals;
+
+int tcp_initialize(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+
+	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, tcp_received_msg);
+	if(tcp_globals.ip_phone < 0){
+		return tcp_globals.ip_phone;
+	}
+	ERROR_PROPAGATE(socket_ports_initialize(&tcp_globals.sockets));
+	if(ERROR_OCCURRED(packet_dimensions_initialize(&tcp_globals.dimensions))){
+		socket_ports_destroy(&tcp_globals.sockets);
+		return ERROR_CODE;
+	}
+	tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
+	fibril_rwlock_write_unlock(&tcp_globals.lock);
+	return EOK;
+}
+
+int tcp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
+	ERROR_DECLARE;
+
+	if(receiver != SERVICE_TCP){
+		return EREFUSED;
+	}
+	fibril_rwlock_write_lock(&tcp_globals.lock);
+	if(ERROR_OCCURRED(tcp_process_packet(device_id, packet, error))){
+		fibril_rwlock_write_unlock(&tcp_globals.lock);
+	}
+	printf("receive %d \n", ERROR_CODE);
+
+	return ERROR_CODE;
+}
+
+int tcp_process_packet(device_id_t device_id, packet_t packet, services_t error){
+	ERROR_DECLARE;
+
+	size_t length;
+	size_t offset;
+	int result;
+	tcp_header_ref header;
+	socket_core_ref  socket;
+	tcp_socket_data_ref socket_data;
+	packet_t next_packet;
+	size_t total_length;
+	uint32_t checksum;
+	int fragments;
+	icmp_type_t type;
+	icmp_code_t code;
+	struct sockaddr * src;
+	struct sockaddr * dest;
+	size_t addrlen;
+
+	printf("p1 \n");
+	if(error){
+		switch(error){
+			case SERVICE_ICMP:
+				// process error
+				result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
+				if(result < 0){
+					return tcp_release_and_return(packet, result);
+				}
+				length = (size_t) result;
+				if(ERROR_OCCURRED(packet_trim(packet, length, 0))){
+					return tcp_release_and_return(packet, ERROR_CODE);
+				}
+				break;
+			default:
+				return tcp_release_and_return(packet, ENOTSUP);
+		}
+	}
+
+	// TODO process received ipopts?
+	result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
+//	printf("ip len %d\n", result);
+	if(result < 0){
+		return tcp_release_and_return(packet, result);
+	}
+	offset = (size_t) result;
+
+	length = packet_get_data_length(packet);
+//	printf("packet len %d\n", length);
+	if(length <= 0){
+		return tcp_release_and_return(packet, EINVAL);
+	}
+	if(length < TCP_HEADER_SIZE + offset){
+		return tcp_release_and_return(packet, NO_DATA);
+	}
+
+	// trim all but TCP header
+	if(ERROR_OCCURRED(packet_trim(packet, offset, 0))){
+		return tcp_release_and_return(packet, ERROR_CODE);
+	}
+
+	// get tcp header
+	header = (tcp_header_ref) packet_get_data(packet);
+	if(! header){
+		return tcp_release_and_return(packet, NO_DATA);
+	}
+//	printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header), ntohs(header->destination_port));
+
+	result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
+	if(result <= 0){
+		return tcp_release_and_return(packet, result);
+	}
+	addrlen = (size_t) result;
+
+	if(ERROR_OCCURRED(tl_set_address_port(src, addrlen, ntohs(header->source_port)))){
+		return tcp_release_and_return(packet, ERROR_CODE);
+	}
+
+	// find the destination socket
+	socket = socket_port_find(&tcp_globals.sockets, ntohs(header->destination_port), (const char *) src, addrlen);
+	if(! socket){
+//		printf("listening?\n");
+		// find the listening destination socket
+		socket = socket_port_find(&tcp_globals.sockets, ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
+		if(! socket){
+			if(tl_prepare_icmp_packet(tcp_globals.net_phone, tcp_globals.icmp_phone, packet, error) == EOK){
+				icmp_destination_unreachable_msg(tcp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet);
+			}
+			return EADDRNOTAVAIL;
+		}
+	}
+	printf("socket id %d\n", socket->socket_id);
+	socket_data = (tcp_socket_data_ref) socket->specific_data;
+	assert(socket_data);
+
+	// some data received, clear the timeout counter
+	socket_data->timeout_count = 0;
+
+	// count the received packet fragments
+	next_packet = packet;
+	fragments = 0;
+	checksum = 0;
+	total_length = 0;
+	do{
+		++ fragments;
+		length = packet_get_data_length(next_packet);
+		if(length <= 0){
+			return tcp_release_and_return(packet, NO_DATA);
+		}
+		total_length += length;
+		// add partial checksum if set
+		if(! error){
+			checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
+		}
+	}while((next_packet = pq_next(next_packet)));
+//	printf("fragments %d of %d bytes\n", fragments, total_length);
+
+//	printf("lock?\n");
+	fibril_rwlock_write_lock(socket_data->local_lock);
+//	printf("locked\n");
+	if(! error){
+		if(socket_data->state == TCP_SOCKET_LISTEN){
+			if(socket_data->pseudo_header){
+				free(socket_data->pseudo_header);
+				socket_data->pseudo_header = NULL;
+				socket_data->headerlen = 0;
+			}
+			if(ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_TCP, src, addrlen, dest, addrlen, total_length, &socket_data->pseudo_header, &socket_data->headerlen))){
+				fibril_rwlock_write_unlock(socket_data->local_lock);
+				return tcp_release_and_return(packet, ERROR_CODE);
+			}
+		}else if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(socket_data->pseudo_header, socket_data->headerlen, total_length))){
+			fibril_rwlock_write_unlock(socket_data->local_lock);
+			return tcp_release_and_return(packet, ERROR_CODE);
+		}
+		checksum = compute_checksum(checksum, socket_data->pseudo_header, socket_data->headerlen);
+		if(flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO){
+			printf("checksum err %x -> %x\n", header->checksum, flip_checksum(compact_checksum(checksum)));
+			fibril_rwlock_write_unlock(socket_data->local_lock);
+			if(! ERROR_OCCURRED(tl_prepare_icmp_packet(tcp_globals.net_phone, tcp_globals.icmp_phone, packet, error))){
+				// checksum error ICMP
+				icmp_parameter_problem_msg(tcp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet);
+			}
+			return EINVAL;
+		}
+	}
+
+	fibril_rwlock_read_unlock(&tcp_globals.lock);
+
+	// TODO error reporting/handling
+//	printf("st %d\n", socket_data->state);
+	switch(socket_data->state){
+		case TCP_SOCKET_LISTEN:
+			ERROR_CODE = tcp_process_listen(socket, socket_data, header, packet, src, dest, addrlen);
+			break;
+		case TCP_SOCKET_SYN_RECEIVED:
+			ERROR_CODE = tcp_process_syn_received(socket, socket_data, header, packet);
+			break;
+		case TCP_SOCKET_SYN_SENT:
+			ERROR_CODE = tcp_process_syn_sent(socket, socket_data, header, packet);
+			break;
+		case TCP_SOCKET_FIN_WAIT_1:
+			// ack changing the state to FIN_WAIT_2 gets processed later
+		case TCP_SOCKET_FIN_WAIT_2:
+			// fin changing state to LAST_ACK gets processed later
+		case TCP_SOCKET_LAST_ACK:
+			// ack releasing the socket get processed later
+		case TCP_SOCKET_CLOSING:
+			// ack releasing the socket gets processed later
+		case TCP_SOCKET_ESTABLISHED:
+			ERROR_CODE = tcp_process_established(socket, socket_data, header, packet, fragments, total_length);
+			break;
+		default:
+			pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+	}
+
+	if(ERROR_CODE != EOK){
+		printf("process %d\n", ERROR_CODE);
+		fibril_rwlock_write_unlock(socket_data->local_lock);
+	}
+	return EOK;
+}
+
+int tcp_process_established(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet, int fragments, size_t total_length){
+	ERROR_DECLARE;
+
+	packet_t next_packet;
+	packet_t tmp_packet;
+	uint32_t old_incoming;
+	size_t order;
+	uint32_t sequence_number;
+	size_t length;
+	size_t offset;
+	uint32_t new_sequence_number;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+	assert(header);
+	assert(packet);
+
+	new_sequence_number = ntohl(header->sequence_number);
+	old_incoming = socket_data->next_incoming;
+
+	if(header->finalize){
+		socket_data->fin_incoming = new_sequence_number;
+	}
+
+//	printf("pe %d < %d <= %d\n", new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length);
+	// trim begining if containing expected data
+	if(IS_IN_INTERVAL_OVERFLOW(new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length)){
+		// get the acknowledged offset
+		if(socket_data->next_incoming < new_sequence_number){
+			offset = new_sequence_number - socket_data->next_incoming;
+		}else{
+			offset = socket_data->next_incoming - new_sequence_number;
+		}
+//		printf("offset %d\n", offset);
+		new_sequence_number += offset;
+		total_length -= offset;
+		length = packet_get_data_length(packet);
+		// trim the acknowledged data
+		while(length <= offset){
+			// release the acknowledged packets
+			next_packet = pq_next(packet);
+			pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+			packet = next_packet;
+			offset -= length;
+			length = packet_get_data_length(packet);
+		}
+		if((offset > 0)
+			&& (ERROR_OCCURRED(packet_trim(packet, offset, 0)))){
+			return tcp_release_and_return(packet, ERROR_CODE);
+		}
+		assert(new_sequence_number == socket_data->next_incoming);
+	}
+
+	// release if overflowing the window
+//	if(IS_IN_INTERVAL_OVERFLOW(socket_data->next_incoming + socket_data->window, new_sequence_number, new_sequence_number + total_length)){
+//		return tcp_release_and_return(packet, EOVERFLOW);
+//	}
+
+/*
+	// trim end if overflowing the window
+	if(IS_IN_INTERVAL_OVERFLOW(new_sequence_number, socket_data->next_incoming + socket_data->window, new_sequence_number + total_length)){
+		// get the allowed data length
+		if(socket_data->next_incoming + socket_data->window < new_sequence_number){
+			offset = new_sequence_number - socket_data->next_incoming + socket_data->window;
+		}else{
+			offset = socket_data->next_incoming + socket_data->window - new_sequence_number;
+		}
+		next_packet = packet;
+		// trim the overflowing data
+		while(next_packet && (offset > 0)){
+			length = packet_get_data_length(packet);
+			if(length <= offset){
+				next_packet = pq_next(next_packet);
+			}else if(ERROR_OCCURRED(packet_trim(next_packet, 0, length - offset))){
+				return tcp_release_and_return(packet, ERROR_CODE);
+			}
+			offset -= length;
+			total_length -= length - offset;
+		}
+		// release the overflowing packets
+		next_packet = pq_next(next_packet);
+		if(next_packet){
+			tmp_packet = next_packet;
+			next_packet = pq_next(next_packet);
+			pq_insert_after(tmp_packet, next_packet);
+			pq_release_remote(tcp_globals.net_phone, packet_get_id(tmp_packet));
+		}
+		assert(new_sequence_number + total_length == socket_data->next_incoming + socket_data->window);
+	}
+*/
+	// the expected one arrived?
+	if(new_sequence_number == socket_data->next_incoming){
+		printf("expected\n");
+		// process acknowledgement
+		tcp_process_acknowledgement(socket, socket_data, header);
+
+		// remove the header
+		total_length -= TCP_HEADER_LENGTH(header);
+		if(ERROR_OCCURRED(packet_trim(packet, TCP_HEADER_LENGTH(header), 0))){
+			return tcp_release_and_return(packet, ERROR_CODE);
+		}
+
+		if(total_length){
+			ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, fragments, total_length));
+		}else{
+			total_length = 1;
+		}
+		socket_data->next_incoming = old_incoming + total_length;
+		packet = socket_data->incoming;
+		while(packet){
+			if(ERROR_OCCURRED(pq_get_order(socket_data->incoming, &order, NULL))){
+				// remove the corrupted packet
+				next_packet = pq_detach(packet);
+				if(packet == socket_data->incoming){
+					socket_data->incoming = next_packet;
+				}
+				pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+				packet = next_packet;
+				continue;
+			}
+			sequence_number = (uint32_t) order;
+			if(IS_IN_INTERVAL_OVERFLOW(sequence_number, old_incoming, socket_data->next_incoming)){
+				// move to the next
+				packet = pq_next(packet);
+			// coninual data?
+			}else if(IS_IN_INTERVAL_OVERFLOW(old_incoming, sequence_number, socket_data->next_incoming)){
+				// detach the packet
+				next_packet = pq_detach(packet);
+				if(packet == socket_data->incoming){
+					socket_data->incoming = next_packet;
+				}
+				// get data length
+				length = packet_get_data_length(packet);
+				new_sequence_number = sequence_number + length;
+				if(length <= 0){
+					// remove the empty packet
+					pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+					packet = next_packet;
+					continue;
+				}
+				// exactly following
+				if(sequence_number == socket_data->next_incoming){
+					// queue received data
+					ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, 1, packet_get_data_length(packet)));
+					socket_data->next_incoming = new_sequence_number;
+					packet = next_packet;
+					continue;
+				// at least partly following data?
+				}else if(IS_IN_INTERVAL_OVERFLOW(sequence_number, socket_data->next_incoming, new_sequence_number)){
+					if(socket_data->next_incoming < new_sequence_number){
+						length = new_sequence_number - socket_data->next_incoming;
+					}else{
+						length = socket_data->next_incoming - new_sequence_number;
+					}
+					if(! ERROR_OCCURRED(packet_trim(packet, length, 0))){
+						// queue received data
+						ERROR_PROPAGATE(tcp_queue_received_packet(socket, socket_data, packet, 1, packet_get_data_length(packet)));
+						socket_data->next_incoming = new_sequence_number;
+						packet = next_packet;
+						continue;
+					}
+				}
+				// remove the duplicit or corrupted packet
+				pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+				packet = next_packet;
+				continue;
+			}else{
+				break;
+			}
+		}
+	}else if(IS_IN_INTERVAL(socket_data->next_incoming, new_sequence_number, socket_data->next_incoming + socket_data->window)){
+		printf("in window\n");
+		// process acknowledgement
+		tcp_process_acknowledgement(socket, socket_data, header);
+
+		// remove the header
+		total_length -= TCP_HEADER_LENGTH(header);
+		if(ERROR_OCCURRED(packet_trim(packet, TCP_HEADER_LENGTH(header), 0))){
+			return tcp_release_and_return(packet, ERROR_CODE);
+		}
+
+		next_packet = pq_detach(packet);
+		length = packet_get_data_length(packet);
+		if(ERROR_OCCURRED(pq_add(&socket_data->incoming, packet, new_sequence_number, length))){
+			// remove the corrupted packets
+			pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+			pq_release_remote(tcp_globals.net_phone, packet_get_id(next_packet));
+		}else{
+			while(next_packet){
+				new_sequence_number += length;
+				tmp_packet = pq_detach(next_packet);
+				length = packet_get_data_length(next_packet);
+				if(ERROR_OCCURRED(pq_set_order(next_packet, new_sequence_number, length))
+					|| ERROR_OCCURRED(pq_insert_after(packet, next_packet))){
+					pq_release_remote(tcp_globals.net_phone, packet_get_id(next_packet));
+				}
+				next_packet = tmp_packet;
+			}
+		}
+	}else{
+		printf("unexpected\n");
+		// release duplicite or restricted
+		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+	}
+
+	// change state according to the acknowledging incoming fin
+	if(IS_IN_INTERVAL_OVERFLOW(old_incoming, socket_data->fin_incoming, socket_data->next_incoming)){
+		switch(socket_data->state){
+			case TCP_SOCKET_FIN_WAIT_1:
+			case TCP_SOCKET_FIN_WAIT_2:
+			case TCP_SOCKET_CLOSING:
+				socket_data->state = TCP_SOCKET_CLOSING;
+				break;
+			//case TCP_ESTABLISHED:
+			default:
+				socket_data->state = TCP_SOCKET_CLOSE_WAIT;
+				break;
+		}
+	}
+
+	packet = tcp_get_packets_to_send(socket, socket_data);
+	if(! packet){
+		// create the notification packet
+		ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 0, 0));
+		ERROR_PROPAGATE(tcp_queue_prepare_packet(socket, socket_data, packet, 1));
+		packet = tcp_send_prepare_packet(socket, socket_data, packet, 1, socket_data->last_outgoing + 1);
+	}
+	fibril_rwlock_write_unlock(socket_data->local_lock);
+	// send the packet
+	tcp_send_packets(socket_data->device_id, packet);
+	return EOK;
+}
+
+int tcp_queue_received_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length){
+	ERROR_DECLARE;
+
+	packet_dimension_ref packet_dimension;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+	assert(packet);
+	assert(fragments >= 1);
+	assert(socket_data->window > total_length);
+
+	// queue the received packet
+	if(ERROR_OCCURRED(dyn_fifo_push(&socket->received, packet_get_id(packet), SOCKET_MAX_RECEIVED_SIZE))
+	    || ERROR_OCCURRED(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension))){
+		return tcp_release_and_return(packet, ERROR_CODE);
+	}
+
+	// decrease the window size
+	socket_data->window -= total_length;
+
+	// notify the destination socket
+	async_msg_5(socket->phone, NET_SOCKET_RECEIVED, (ipcarg_t) socket->socket_id, ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size), 0, 0, (ipcarg_t) fragments);
+	return EOK;
+}
+
+int tcp_process_syn_sent(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet){
+	ERROR_DECLARE;
+
+	packet_t next_packet;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+	assert(header);
+	assert(packet);
+
+	if(header->synchronize){
+		// process acknowledgement
+		tcp_process_acknowledgement(socket, socket_data, header);
+
+		socket_data->next_incoming = ntohl(header->sequence_number) + 1;
+		// release additional packets
+		next_packet = pq_detach(packet);
+		if(next_packet){
+			pq_release_remote(tcp_globals.net_phone, packet_get_id(next_packet));
+		}
+		// trim if longer than the header
+		if((packet_get_data_length(packet) > sizeof(*header))
+			&& ERROR_OCCURRED(packet_trim(packet, 0, packet_get_data_length(packet) - sizeof(*header)))){
+			return tcp_release_and_return(packet, ERROR_CODE);
+		}
+		tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
+		fibril_mutex_lock(&socket_data->operation.mutex);
+		socket_data->operation.result = tcp_queue_packet(socket, socket_data, packet, 1);
+		if(socket_data->operation.result == EOK){
+			socket_data->state = TCP_SOCKET_ESTABLISHED;
+			packet = tcp_get_packets_to_send(socket, socket_data);
+			if(packet){
+				fibril_rwlock_write_unlock(socket_data->local_lock);
+				// send the packet
+				tcp_send_packets(socket_data->device_id, packet);
+				// signal the result
+				fibril_condvar_signal(&socket_data->operation.condvar);
+				fibril_mutex_unlock(&socket_data->operation.mutex);
+				return EOK;
+			}
+		}
+		fibril_mutex_unlock(&socket_data->operation.mutex);
+	}
+	return tcp_release_and_return(packet, EINVAL);
+}
+
+int tcp_process_listen(socket_core_ref listening_socket, tcp_socket_data_ref listening_socket_data, tcp_header_ref header, packet_t packet, struct sockaddr * src, struct sockaddr * dest, size_t addrlen){
+	ERROR_DECLARE;
+
+	packet_t next_packet;
+	socket_core_ref socket;
+	tcp_socket_data_ref socket_data;
+	int socket_id;
+	int listening_socket_id = listening_socket->socket_id;
+	int listening_port = listening_socket->port;
+
+	assert(listening_socket);
+	assert(listening_socket_data);
+	assert(listening_socket->specific_data == listening_socket_data);
+	assert(header);
+	assert(packet);
+
+//	printf("syn %d\n", header->synchronize);
+	if(header->synchronize){
+		socket_data = (tcp_socket_data_ref) malloc(sizeof(*socket_data));
+		if(! socket_data){
+			return tcp_release_and_return(packet, ENOMEM);
+		}else{
+			tcp_initialize_socket_data(socket_data);
+			socket_data->local_lock = listening_socket_data->local_lock;
+			socket_data->local_sockets = listening_socket_data->local_sockets;
+			socket_data->listening_socket_id = listening_socket->socket_id;
+
+			socket_data->next_incoming = ntohl(header->sequence_number);
+			socket_data->treshold = socket_data->next_incoming + ntohs(header->window);
+
+			socket_data->addrlen = addrlen;
+			socket_data->addr = malloc(socket_data->addrlen);
+			if(! socket_data->addr){
+				free(socket_data);
+				return tcp_release_and_return(packet, ENOMEM);
+			}
+			memcpy(socket_data->addr, src, socket_data->addrlen);
+
+			socket_data->dest_port = ntohs(header->source_port);
+			if(ERROR_OCCURRED(tl_set_address_port(socket_data->addr, socket_data->addrlen, socket_data->dest_port))){
+				free(socket_data->addr);
+				free(socket_data);
+				pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+				return ERROR_CODE;
+			}
+
+//			printf("addr %p\n", socket_data->addr, socket_data->addrlen);
+			// create a socket
+			socket_id = -1;
+			if(ERROR_OCCURRED(socket_create(socket_data->local_sockets, listening_socket->phone, socket_data, &socket_id))){
+				free(socket_data->addr);
+				free(socket_data);
+				return tcp_release_and_return(packet, ERROR_CODE);
+			}
+
+			printf("new_sock %d\n", socket_id);
+			socket_data->pseudo_header = listening_socket_data->pseudo_header;
+			socket_data->headerlen = listening_socket_data->headerlen;
+			listening_socket_data->pseudo_header = NULL;
+			listening_socket_data->headerlen = 0;
+
+			fibril_rwlock_write_unlock(socket_data->local_lock);
+//			printf("list lg\n");
+			fibril_rwlock_write_lock(&tcp_globals.lock);
+//			printf("list locked\n");
+			// find the destination socket
+			listening_socket = socket_port_find(&tcp_globals.sockets, listening_port, SOCKET_MAP_KEY_LISTENING, 0);
+			if((! listening_socket) || (listening_socket->socket_id != listening_socket_id)){
+				fibril_rwlock_write_unlock(&tcp_globals.lock);
+				// a shadow may remain until app hangs up
+				return tcp_release_and_return(packet, EOK/*ENOTSOCK*/);
+			}
+//			printf("port %d\n", listening_socket->port);
+			listening_socket_data = (tcp_socket_data_ref) listening_socket->specific_data;
+			assert(listening_socket_data);
+
+//			printf("list ll\n");
+			fibril_rwlock_write_lock(listening_socket_data->local_lock);
+//			printf("list locked\n");
+
+			socket = socket_cores_find(listening_socket_data->local_sockets, socket_id);
+			if(! socket){
+				// where is the socket?!?
+				fibril_rwlock_write_unlock(&tcp_globals.lock);
+				return ENOTSOCK;
+			}
+			socket_data = (tcp_socket_data_ref) socket->specific_data;
+			assert(socket_data);
+
+//			uint8_t * data = socket_data->addr;
+//			printf("addr %d of %x %x %x %x-%x %x %x %x-%x %x %x %x-%x %x %x %x\n", socket_data->addrlen, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
+
+			ERROR_CODE = socket_port_add(&tcp_globals.sockets, listening_port, socket, (const char *) socket_data->addr, socket_data->addrlen);
+			assert(socket == socket_port_find(&tcp_globals.sockets, listening_port, (const char *) socket_data->addr, socket_data->addrlen));
+			//ERROR_CODE = socket_bind_free_port(&tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port);
+			//tcp_globals.last_used_port = socket->port;
+//			printf("bound %d\n", socket->port);
+			fibril_rwlock_write_unlock(&tcp_globals.lock);
+			if(ERROR_CODE != EOK){
+				socket_destroy(tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
+				return tcp_release_and_return(packet, ERROR_CODE);
+			}
+
+			socket_data->state = TCP_SOCKET_LISTEN;
+			socket_data->next_incoming = ntohl(header->sequence_number) + 1;
+			// release additional packets
+			next_packet = pq_detach(packet);
+			if(next_packet){
+				pq_release_remote(tcp_globals.net_phone, packet_get_id(next_packet));
+			}
+			// trim if longer than the header
+			if((packet_get_data_length(packet) > sizeof(*header))
+				&& ERROR_OCCURRED(packet_trim(packet, 0, packet_get_data_length(packet) - sizeof(*header)))){
+				socket_destroy(tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
+				return tcp_release_and_return(packet, ERROR_CODE);
+			}
+			tcp_prepare_operation_header(socket, socket_data, header, 1, 0);
+			if(ERROR_OCCURRED(tcp_queue_packet(socket, socket_data, packet, 1))){
+				socket_destroy(tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
+				return ERROR_CODE;
+			}
+			packet = tcp_get_packets_to_send(socket, socket_data);
+//			printf("send %d\n", packet_get_id(packet));
+			if(! packet){
+				socket_destroy(tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
+				return EINVAL;
+			}else{
+				socket_data->state = TCP_SOCKET_SYN_RECEIVED;
+//				printf("unlock\n");
+				fibril_rwlock_write_unlock(socket_data->local_lock);
+				// send the packet
+				tcp_send_packets(socket_data->device_id, packet);
+				return EOK;
+			}
+		}
+	}
+	return tcp_release_and_return(packet, EINVAL);
+}
+
+int tcp_process_syn_received(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet){
+	ERROR_DECLARE;
+
+	socket_core_ref listening_socket;
+	tcp_socket_data_ref listening_socket_data;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+	assert(header);
+	assert(packet);
+
+	printf("syn_rec\n");
+	if(header->acknowledge){
+		// process acknowledgement
+		tcp_process_acknowledgement(socket, socket_data, header);
+
+		socket_data->next_incoming = ntohl(header->sequence_number);// + 1;
+		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		socket_data->state = TCP_SOCKET_ESTABLISHED;
+		listening_socket = socket_cores_find(socket_data->local_sockets, socket_data->listening_socket_id);
+		if(listening_socket){
+			listening_socket_data = (tcp_socket_data_ref) listening_socket->specific_data;
+			assert(listening_socket_data);
+
+			// queue the received packet
+			if(! ERROR_OCCURRED(dyn_fifo_push(&listening_socket->accepted, (-1 * socket->socket_id), listening_socket_data->backlog))){
+				// notify the destination socket
+				async_msg_5(socket->phone, NET_SOCKET_ACCEPTED, (ipcarg_t) listening_socket->socket_id, socket_data->data_fragment_size, TCP_HEADER_SIZE, 0, (ipcarg_t) socket->socket_id);
+				fibril_rwlock_write_unlock(socket_data->local_lock);
+				return EOK;
+			}
+		}
+		// send FIN
+		socket_data->state = TCP_SOCKET_FIN_WAIT_1;
+
+		// create the notification packet
+		ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 0, 1));
+
+		// send the packet
+		ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
+
+		// flush packets
+		packet = tcp_get_packets_to_send(socket, socket_data);
+		fibril_rwlock_write_unlock(socket_data->local_lock);
+		if(packet){
+			// send the packet
+			tcp_send_packets(socket_data->device_id, packet);
+		}
+		return EOK;
+	}else{
+		return tcp_release_and_return(packet, EINVAL);
+	}
+	return EINVAL;
+}
+
+void tcp_process_acknowledgement(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header){
+	size_t number;
+	size_t length;
+	packet_t packet;
+	packet_t next;
+	packet_t acknowledged = NULL;
+	uint32_t old;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+	assert(header);
+
+	if(header->acknowledge){
+		number = ntohl(header->acknowledgement_number);
+		// if more data acknowledged
+		if(number != socket_data->expected){
+			old = socket_data->expected;
+			if(IS_IN_INTERVAL_OVERFLOW(old, socket_data->fin_outgoing, number)){
+				switch(socket_data->state){
+					case TCP_SOCKET_FIN_WAIT_1:
+						socket_data->state = TCP_SOCKET_FIN_WAIT_2;
+						break;
+					case TCP_SOCKET_LAST_ACK:
+					case TCP_SOCKET_CLOSING:
+						// fin acknowledged - release the socket in another fibril
+						tcp_prepare_timeout(tcp_release_after_timeout, socket, socket_data, 0, TCP_SOCKET_TIME_WAIT, NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true);
+						break;
+					default:
+						break;
+				}
+			}
+			// update the treshold if higher than set
+			if(number + ntohs(header->window) > socket_data->expected + socket_data->treshold){
+				socket_data->treshold = number + ntohs(header->window) - socket_data->expected;
+			}
+			// set new expected sequence number
+			socket_data->expected = number;
+			socket_data->expected_count = 1;
+			packet = socket_data->outgoing;
+			while(pq_get_order(packet, &number, &length) == EOK){
+				if(IS_IN_INTERVAL_OVERFLOW((uint32_t) old, (uint32_t)(number + length), (uint32_t) socket_data->expected)){
+					next = pq_detach(packet);
+					if(packet == socket_data->outgoing){
+						socket_data->outgoing = next;
+					}
+					// add to acknowledged or release
+					if(pq_add(&acknowledged, packet, 0, 0) != EOK){
+						pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+					}
+					packet = next;
+				}else if(old < socket_data->expected){
+					break;
+				}
+			}
+			// release acknowledged
+			if(acknowledged){
+				pq_release_remote(tcp_globals.net_phone, packet_get_id(acknowledged));
+			}
+			return;
+		// if the same as the previous time
+		}else if(number == socket_data->expected){
+			// increase the counter
+			++ socket_data->expected_count;
+			if(socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT){
+				socket_data->expected_count = 1;
+				// TODO retransmit lock
+				//tcp_retransmit_packet(socket, socket_data, number);
+			}
+		}
+	}
+}
+
+int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	ERROR_DECLARE;
+
+	packet_t packet;
+
+	assert(call);
+	assert(answer);
+	assert(answer_count);
+
+	*answer_count = 0;
+	switch(IPC_GET_METHOD(*call)){
+		case NET_TL_RECEIVED:
+			//fibril_rwlock_read_lock(&tcp_globals.lock);
+			if(! ERROR_OCCURRED(packet_translate_remote(tcp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
+				ERROR_CODE = tcp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_TCP, IPC_GET_ERROR(call));
+			}
+			//fibril_rwlock_read_unlock(&tcp_globals.lock);
+			return ERROR_CODE;
+		case IPC_M_CONNECT_TO_ME:
+			return tcp_process_client_messages(callid, * call);
+	}
+	return ENOTSUP;
+}
+
+void tcp_refresh_socket_data(tcp_socket_data_ref socket_data){
+	assert(socket_data);
+
+	bzero(socket_data, sizeof(*socket_data));
+	socket_data->state = TCP_SOCKET_INITIAL;
+	socket_data->device_id = DEVICE_INVALID_ID;
+	socket_data->window = NET_DEFAULT_TCP_WINDOW;
+	socket_data->treshold = socket_data->window;
+	socket_data->last_outgoing = TCP_INITIAL_SEQUENCE_NUMBER;
+	socket_data->timeout = NET_DEFAULT_TCP_INITIAL_TIMEOUT;
+	socket_data->acknowledged = socket_data->last_outgoing;
+	socket_data->next_outgoing = socket_data->last_outgoing + 1;
+	socket_data->expected = socket_data->next_outgoing;
+}
+
+void tcp_initialize_socket_data(tcp_socket_data_ref socket_data){
+	assert(socket_data);
+
+	tcp_refresh_socket_data(socket_data);
+	fibril_mutex_initialize(&socket_data->operation.mutex);
+	fibril_condvar_initialize(&socket_data->operation.condvar);
+	socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE;
+}
+
+int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
+	int res;
+	bool keep_on_going = true;
+	socket_cores_t local_sockets;
+	int app_phone = IPC_GET_PHONE(&call);
+	struct sockaddr * addr;
+	int socket_id;
+	size_t addrlen;
+	size_t size;
+	fibril_rwlock_t lock;
+	ipc_call_t answer;
+	int answer_count;
+	tcp_socket_data_ref socket_data;
+	socket_core_ref socket;
+	packet_dimension_ref packet_dimension;
+
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	res = EOK;
+	answer_count = 0;
+
+	socket_cores_initialize(&local_sockets);
+	fibril_rwlock_initialize(&lock);
+
+	while(keep_on_going){
+
+		// answer the call
+		answer_call(callid, res, &answer, answer_count);
+
+		// refresh data
+		refresh_answer(&answer, &answer_count);
+
+		// get the next call
+		callid = async_get_call(&call);
+
+		// process the call
+		switch(IPC_GET_METHOD(call)){
+			case IPC_M_PHONE_HUNGUP:
+				keep_on_going = false;
+				res = EHANGUP;
+				break;
+			case NET_SOCKET:
+				socket_data = (tcp_socket_data_ref) malloc(sizeof(*socket_data));
+				if(! socket_data){
+					res = ENOMEM;
+				}else{
+					tcp_initialize_socket_data(socket_data);
+					socket_data->local_lock = &lock;
+					socket_data->local_sockets = &local_sockets;
+					fibril_rwlock_write_lock(&lock);
+					socket_id = SOCKET_GET_SOCKET_ID(call);
+					res = socket_create(&local_sockets, app_phone, socket_data, &socket_id);
+					SOCKET_SET_SOCKET_ID(answer, socket_id);
+					fibril_rwlock_write_unlock(&lock);
+					if(res == EOK){
+						if (tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, DEVICE_INVALID_ID, &packet_dimension) == EOK){
+							SOCKET_SET_DATA_FRAGMENT_SIZE(answer, ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size));
+						}
+//						SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_TCP_FRAGMENT_SIZE);
+						SOCKET_SET_HEADER_SIZE(answer, TCP_HEADER_SIZE);
+						answer_count = 3;
+					}else{
+						free(socket_data);
+					}
+				}
+				break;
+			case NET_SOCKET_BIND:
+				res = data_receive((void **) &addr, &addrlen);
+				if(res == EOK){
+					fibril_rwlock_write_lock(&tcp_globals.lock);
+					fibril_rwlock_write_lock(&lock);
+					res = socket_bind(&local_sockets, &tcp_globals.sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port);
+					if(res == EOK){
+						socket = socket_cores_find(&local_sockets, SOCKET_GET_SOCKET_ID(call));
+						if(socket){
+							socket_data = (tcp_socket_data_ref) socket->specific_data;
+							assert(socket_data);
+							socket_data->state = TCP_SOCKET_LISTEN;
+						}
+					}
+					fibril_rwlock_write_unlock(&lock);
+					fibril_rwlock_write_unlock(&tcp_globals.lock);
+					free(addr);
+				}
+				break;
+			case NET_SOCKET_LISTEN:
+				fibril_rwlock_read_lock(&tcp_globals.lock);
+//				fibril_rwlock_write_lock(&tcp_globals.lock);
+				fibril_rwlock_write_lock(&lock);
+				res = tcp_listen_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_BACKLOG(call));
+				fibril_rwlock_write_unlock(&lock);
+//				fibril_rwlock_write_unlock(&tcp_globals.lock);
+				fibril_rwlock_read_unlock(&tcp_globals.lock);
+				break;
+			case NET_SOCKET_CONNECT:
+				res = data_receive((void **) &addr, &addrlen);
+				if(res == EOK){
+					// the global lock may be released in the tcp_connect_message() function
+					fibril_rwlock_write_lock(&tcp_globals.lock);
+					fibril_rwlock_write_lock(&lock);
+					res = tcp_connect_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen);
+					if(res != EOK){
+						fibril_rwlock_write_unlock(&lock);
+						fibril_rwlock_write_unlock(&tcp_globals.lock);
+						free(addr);
+					}
+				}
+				break;
+			case NET_SOCKET_ACCEPT:
+				fibril_rwlock_read_lock(&tcp_globals.lock);
+				fibril_rwlock_write_lock(&lock);
+				res = tcp_accept_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_NEW_SOCKET_ID(call), &size, &addrlen);
+				SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
+				fibril_rwlock_write_unlock(&lock);
+				fibril_rwlock_read_unlock(&tcp_globals.lock);
+				if(res > 0){
+					SOCKET_SET_SOCKET_ID(answer, res);
+					SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
+					answer_count = 3;
+				}
+				break;
+			case NET_SOCKET_SEND:
+				fibril_rwlock_read_lock(&tcp_globals.lock);
+				fibril_rwlock_write_lock(&lock);
+				res = tcp_send_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_DATA_FRAGMENTS(call), &size, SOCKET_GET_FLAGS(call));
+				SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
+				if(res != EOK){
+					fibril_rwlock_write_unlock(&lock);
+					fibril_rwlock_read_unlock(&tcp_globals.lock);
+				}else{
+					answer_count = 2;
+				}
+				break;
+			case NET_SOCKET_SENDTO:
+				res = data_receive((void **) &addr, &addrlen);
+				if(res == EOK){
+					fibril_rwlock_read_lock(&tcp_globals.lock);
+					fibril_rwlock_write_lock(&lock);
+					res = tcp_send_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_DATA_FRAGMENTS(call), &size, SOCKET_GET_FLAGS(call));
+					SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
+					if(res != EOK){
+						fibril_rwlock_write_unlock(&lock);
+						fibril_rwlock_read_unlock(&tcp_globals.lock);
+					}else{
+						answer_count = 2;
+					}
+					free(addr);
+				}
+				break;
+			case NET_SOCKET_RECV:
+				fibril_rwlock_read_lock(&tcp_globals.lock);
+				fibril_rwlock_write_lock(&lock);
+				res = tcp_recvfrom_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), NULL);
+				fibril_rwlock_write_unlock(&lock);
+				fibril_rwlock_read_unlock(&tcp_globals.lock);
+				if(res > 0){
+					SOCKET_SET_READ_DATA_LENGTH(answer, res);
+					answer_count = 1;
+					res = EOK;
+				}
+				break;
+			case NET_SOCKET_RECVFROM:
+				fibril_rwlock_read_lock(&tcp_globals.lock);
+				fibril_rwlock_write_lock(&lock);
+				res = tcp_recvfrom_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), &addrlen);
+				fibril_rwlock_write_unlock(&lock);
+				fibril_rwlock_read_unlock(&tcp_globals.lock);
+				if(res > 0){
+					SOCKET_SET_READ_DATA_LENGTH(answer, res);
+					SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
+					answer_count = 3;
+					res = EOK;
+				}
+				break;
+			case NET_SOCKET_CLOSE:
+				fibril_rwlock_write_lock(&tcp_globals.lock);
+				fibril_rwlock_write_lock(&lock);
+				res = tcp_close_message(&local_sockets, SOCKET_GET_SOCKET_ID(call));
+				if(res != EOK){
+					fibril_rwlock_write_unlock(&lock);
+					fibril_rwlock_write_unlock(&tcp_globals.lock);
+				}
+				break;
+			case NET_SOCKET_GETSOCKOPT:
+			case NET_SOCKET_SETSOCKOPT:
+			default:
+				res = ENOTSUP;
+				break;
+		}
+	}
+
+	// release the application phone
+	ipc_hangup(app_phone);
+
+	printf("release\n");
+	// release all local sockets
+	socket_cores_release(tcp_globals.net_phone, &local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
+
+	return EOK;
+}
+
+int tcp_timeout(void * data){
+	tcp_timeout_ref timeout = data;
+	int keep_write_lock = false;
+	socket_core_ref socket;
+	tcp_socket_data_ref socket_data;
+
+	assert(timeout);
+
+	// sleep the given timeout
+	async_usleep(timeout->timeout);
+	// lock the globals
+	if(timeout->globals_read_only){
+		fibril_rwlock_read_lock(&tcp_globals.lock);
+	}else{
+		fibril_rwlock_write_lock(&tcp_globals.lock);
+	}
+	// find the pending operation socket
+	socket = socket_port_find(&tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length);
+	if(socket && (socket->socket_id == timeout->socket_id)){
+		socket_data = (tcp_socket_data_ref) socket->specific_data;
+		assert(socket_data);
+		if(socket_data->local_sockets == timeout->local_sockets){
+			fibril_rwlock_write_lock(socket_data->local_lock);
+			if(timeout->sequence_number){
+				// increase the timeout counter;
+				++ socket_data->timeout_count;
+				if(socket_data->timeout_count == TCP_MAX_TIMEOUTS){
+					// TODO release as connection lost
+					//tcp_refresh_socket_data(socket_data);
+					fibril_rwlock_write_unlock(socket_data->local_lock);
+				}else{
+					// retransmit
+//					tcp_retransmit_packet(socket, socket_data, timeout->sequence_number);
+					fibril_rwlock_write_unlock(socket_data->local_lock);
+				}
+			}else{
+				fibril_mutex_lock(&socket_data->operation.mutex);
+				// set the timeout operation result if state not changed
+				if(socket_data->state == timeout->state){
+					socket_data->operation.result = ETIMEOUT;
+					// notify the main fibril
+					fibril_condvar_signal(&socket_data->operation.condvar);
+					// keep the global write lock
+					keep_write_lock = true;
+				}else{
+					// operation is ok, do nothing
+					// unlocking from now on, so the unlock order does not matter...
+					fibril_rwlock_write_unlock(socket_data->local_lock);
+				}
+				fibril_mutex_unlock(&socket_data->operation.mutex);
+			}
+		}
+	}
+	// unlock only if no socket
+	if(timeout->globals_read_only){
+		fibril_rwlock_read_unlock(&tcp_globals.lock);
+	}else if(! keep_write_lock){
+		// release if not desired
+		fibril_rwlock_write_unlock(&tcp_globals.lock);
+	}
+	// release the timeout structure
+	free(timeout);
+	return EOK;
+}
+
+int tcp_release_after_timeout(void * data){
+	tcp_timeout_ref timeout = data;
+	socket_core_ref socket;
+	tcp_socket_data_ref socket_data;
+	fibril_rwlock_t * local_lock;
+
+	assert(timeout);
+
+	// sleep the given timeout
+	async_usleep(timeout->timeout);
+	// lock the globals
+	fibril_rwlock_write_lock(&tcp_globals.lock);
+	// find the pending operation socket
+	socket = socket_port_find(&tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length);
+	if(socket && (socket->socket_id == timeout->socket_id)){
+		socket_data = (tcp_socket_data_ref) socket->specific_data;
+		assert(socket_data);
+		if(socket_data->local_sockets == timeout->local_sockets){
+			local_lock = socket_data->local_lock;
+			fibril_rwlock_write_lock(local_lock);
+			socket_destroy(tcp_globals.net_phone, timeout->socket_id, timeout->local_sockets, &tcp_globals.sockets, tcp_free_socket_data);
+			fibril_rwlock_write_unlock(local_lock);
+		}
+	}
+	// unlock the globals
+	fibril_rwlock_write_unlock(&tcp_globals.lock);
+	// release the timeout structure
+	free(timeout);
+	return EOK;
+}
+
+void tcp_retransmit_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number){
+	packet_t packet;
+	packet_t copy;
+	size_t data_length;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+
+	// sent packet?
+	packet = pq_find(socket_data->outgoing, sequence_number);
+	printf("retransmit %d\n", packet_get_id(packet));
+	if(packet){
+		pq_get_order(packet, NULL, &data_length);
+		copy = tcp_prepare_copy(socket, socket_data, packet, data_length, sequence_number);
+		fibril_rwlock_write_unlock(socket_data->local_lock);
+//		printf("r send %d\n", packet_get_id(packet));
+		if(copy){
+			tcp_send_packets(socket_data->device_id, copy);
+		}
+	}else{
+		fibril_rwlock_write_unlock(socket_data->local_lock);
+	}
+}
+
+int tcp_listen_message(socket_cores_ref local_sockets, int socket_id, int backlog){
+	socket_core_ref socket;
+	tcp_socket_data_ref socket_data;
+
+	assert(local_sockets);
+
+	if(backlog < 0){
+		return EINVAL;
+	}
+	// find the socket
+	socket = socket_cores_find(local_sockets, socket_id);
+	if(! socket){
+		return ENOTSOCK;
+	}
+	// get the socket specific data
+	socket_data = (tcp_socket_data_ref) socket->specific_data;
+	assert(socket_data);
+	// set the backlog
+	socket_data->backlog = backlog;
+	return EOK;
+}
+
+int tcp_connect_message(socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen){
+	ERROR_DECLARE;
+
+	socket_core_ref socket;
+
+	assert(local_sockets);
+	assert(addr);
+	assert(addrlen > 0);
+
+	// find the socket
+	socket = socket_cores_find(local_sockets, socket_id);
+	if(! socket){
+		return ENOTSOCK;
+	}
+	if(ERROR_OCCURRED(tcp_connect_core(socket, local_sockets, addr, addrlen))){
+		tcp_free_socket_data(socket);
+		// unbind if bound
+		if(socket->port > 0){
+			socket_ports_exclude(&tcp_globals.sockets, socket->port);
+			socket->port = 0;
+		}
+	}
+	return ERROR_CODE;
+}
+
+int tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen){
+	ERROR_DECLARE;
+
+	tcp_socket_data_ref socket_data;
+	packet_t packet;
+
+	assert(socket);
+	assert(addr);
+	assert(addrlen > 0);
+
+	// get the socket specific data
+	socket_data = (tcp_socket_data_ref) socket->specific_data;
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+	if((socket_data->state != TCP_SOCKET_INITIAL)
+		&& ((socket_data->state != TCP_SOCKET_LISTEN) || (socket->port <= 0))){
+		return EINVAL;
+	}
+	// get the destination port
+	ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &socket_data->dest_port));
+	if(socket->port <= 0){
+		// try to find a free port
+		ERROR_PROPAGATE(socket_bind_free_port(&tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port));
+		// set the next port as the search starting port number
+		tcp_globals.last_used_port = socket->port;
+	}
+	ERROR_PROPAGATE(ip_get_route_req(tcp_globals.ip_phone, IPPROTO_TCP, addr, addrlen, &socket_data->device_id, &socket_data->pseudo_header, &socket_data->headerlen));
+
+	// create the notification packet
+	ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 1, 0));
+
+	// unlock the globals and wait for an operation
+	fibril_rwlock_write_unlock(&tcp_globals.lock);
+
+	socket_data->addr = addr;
+	socket_data->addrlen = addrlen;
+	// send the packet
+	if(ERROR_OCCURRED(tcp_queue_packet(socket, socket_data, packet, 1))
+		|| ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data, 0, TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false))){
+		socket_data->addr = NULL;
+		socket_data->addrlen = 0;
+		fibril_rwlock_write_lock(&tcp_globals.lock);
+	}else{
+		packet = tcp_get_packets_to_send(socket, socket_data);
+		if(packet){
+			fibril_mutex_lock(&socket_data->operation.mutex);
+			fibril_rwlock_write_unlock(socket_data->local_lock);
+			// send the packet
+			printf("connecting %d\n", packet_get_id(packet));
+			tcp_send_packets(socket_data->device_id, packet);
+			// wait for a reply
+			fibril_condvar_wait(&socket_data->operation.condvar, &socket_data->operation.mutex);
+			ERROR_CODE = socket_data->operation.result;
+			if(ERROR_CODE != EOK){
+				socket_data->addr = NULL;
+				socket_data->addrlen = 0;
+			}
+		}else{
+			socket_data->addr = NULL;
+			socket_data->addrlen = 0;
+			ERROR_CODE = EINTR;
+		}
+	}
+
+	fibril_mutex_unlock(&socket_data->operation.mutex);
+
+	// return the result
+	return ERROR_CODE;
+}
+
+int tcp_queue_prepare_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length){
+	ERROR_DECLARE;
+
+	tcp_header_ref header;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+
+	// get tcp header
+	header = (tcp_header_ref) packet_get_data(packet);
+	if(! header){
+		return NO_DATA;
+	}
+	header->destination_port = htons(socket_data->dest_port);
+	header->source_port = htons(socket->port);
+	header->sequence_number = htonl(socket_data->next_outgoing);
+	if(ERROR_OCCURRED(packet_set_addr(packet, NULL, (uint8_t *) socket_data->addr, socket_data->addrlen))){
+		return tcp_release_and_return(packet, EINVAL);
+	}
+	// remember the outgoing FIN
+	if(header->finalize){
+		socket_data->fin_outgoing = socket_data->next_outgoing;
+	}
+	return EOK;
+}
+
+int tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length){
+	ERROR_DECLARE;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+
+	ERROR_PROPAGATE(tcp_queue_prepare_packet(socket, socket_data, packet, data_length));
+
+	if(ERROR_OCCURRED(pq_add(&socket_data->outgoing, packet, socket_data->next_outgoing, data_length))){
+		return tcp_release_and_return(packet, ERROR_CODE);
+	}
+	socket_data->next_outgoing += data_length;
+	return EOK;
+}
+
+packet_t tcp_get_packets_to_send(socket_core_ref socket, tcp_socket_data_ref socket_data){
+	ERROR_DECLARE;
+
+	packet_t packet;
+	packet_t copy;
+	packet_t sending = NULL;
+	packet_t previous = NULL;
+	size_t data_length;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+
+	packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1);
+	while(packet){
+		pq_get_order(packet, NULL, &data_length);
+		// send only if fits into the window
+		// respecting the possible overflow
+		if(IS_IN_INTERVAL_OVERFLOW((uint32_t) socket_data->last_outgoing, (uint32_t)(socket_data->last_outgoing + data_length), (uint32_t)(socket_data->expected + socket_data->treshold))){
+			copy = tcp_prepare_copy(socket, socket_data, packet, data_length, socket_data->last_outgoing + 1);
+			if(! copy){
+				return sending;
+			}
+			if(! sending){
+				sending = copy;
+			}else{
+				if(ERROR_OCCURRED(pq_insert_after(previous, copy))){
+					pq_release_remote(tcp_globals.net_phone, packet_get_id(copy));
+					return sending;
+				}
+			}
+			previous = copy;
+			packet = pq_next(packet);
+			// overflow occurred ?
+			if((! packet) && (socket_data->last_outgoing > socket_data->next_outgoing)){
+				printf("gpts overflow\n");
+				// continue from the beginning
+				packet = socket_data->outgoing;
+			}
+			socket_data->last_outgoing += data_length;
+		}else{
+			break;
+		}
+	}
+	return sending;
+}
+
+packet_t tcp_send_prepare_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number){
+	ERROR_DECLARE;
+
+	tcp_header_ref header;
+	uint32_t checksum;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+
+	// adjust the pseudo header
+	if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(socket_data->pseudo_header, socket_data->headerlen, packet_get_data_length(packet)))){
+		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		return NULL;
+	}
+
+	// get the header
+	header = (tcp_header_ref) packet_get_data(packet);
+	if(! header){
+		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		return NULL;
+	}
+	assert(ntohl(header->sequence_number) == sequence_number);
+
+	// adjust the header
+	if(socket_data->next_incoming){
+		header->acknowledgement_number = htonl(socket_data->next_incoming);
+		header->acknowledge = 1;
+	}
+	header->window = htons(socket_data->window);
+
+	// checksum
+	header->checksum = 0;
+	checksum = compute_checksum(0, socket_data->pseudo_header, socket_data->headerlen);
+	checksum = compute_checksum(checksum, (uint8_t *) packet_get_data(packet), packet_get_data_length(packet));
+	header->checksum = htons(flip_checksum(compact_checksum(checksum)));
+	// prepare the packet
+	if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0))
+	// prepare the timeout
+		|| ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data, sequence_number, socket_data->state, socket_data->timeout, true))){
+		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		return NULL;
+	}
+	return packet;
+}
+
+packet_t tcp_prepare_copy(socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number){
+	packet_t copy;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+
+	// make a copy of the packet
+	copy = packet_get_copy(tcp_globals.net_phone, packet);
+	if(! copy){
+		return NULL;
+	}
+
+	return tcp_send_prepare_packet(socket, socket_data, copy, data_length, sequence_number);
+}
+
+void tcp_send_packets(device_id_t device_id, packet_t packet){
+	packet_t next;
+
+	while(packet){
+		next = pq_detach(packet);
+		ip_send_msg(tcp_globals.ip_phone, device_id, packet, SERVICE_TCP, 0);
+		packet = next;
+	}
+}
+
+void tcp_prepare_operation_header(socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize){
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+	assert(header);
+
+	bzero(header, sizeof(*header));
+	header->source_port = htons(socket->port);
+	header->source_port = htons(socket_data->dest_port);
+	header->header_length = TCP_COMPUTE_HEADER_LENGTH(sizeof(*header));
+	header->synchronize = synchronize;
+	header->finalize = finalize;
+}
+
+int tcp_prepare_timeout(int (*timeout_function)(void * tcp_timeout_t), socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, int globals_read_only){
+	tcp_timeout_ref operation_timeout;
+	fid_t fibril;
+
+	assert(socket);
+	assert(socket_data);
+	assert(socket->specific_data == socket_data);
+
+	// prepare the timeout with key bundle structure
+	operation_timeout = malloc(sizeof(*operation_timeout) + socket->key_length + 1);
+	if(! operation_timeout){
+		return ENOMEM;
+	}
+	bzero(operation_timeout, sizeof(*operation_timeout));
+	operation_timeout->globals_read_only = globals_read_only;
+	operation_timeout->port = socket->port;
+	operation_timeout->local_sockets = socket_data->local_sockets;
+	operation_timeout->socket_id = socket->socket_id;
+	operation_timeout->timeout = timeout;
+	operation_timeout->sequence_number = sequence_number;
+	operation_timeout->state = state;
+
+	// copy the key
+	operation_timeout->key = ((char *) operation_timeout) + sizeof(*operation_timeout);
+	operation_timeout->key_length = socket->key_length;
+	memcpy(operation_timeout->key, socket->key, socket->key_length);
+	operation_timeout->key[operation_timeout->key_length] = '\0';
+
+	// prepare the timeouting thread
+	fibril = fibril_create(timeout_function, operation_timeout);
+	if(! fibril){
+		free(operation_timeout);
+		return EPARTY;
+	}
+//	fibril_mutex_lock(&socket_data->operation.mutex);
+	// start the timeouting fibril
+	fibril_add_ready(fibril);
+	//socket_data->state = state;
+	return EOK;
+}
+
+int tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){
+	ERROR_DECLARE;
+
+	socket_core_ref socket;
+	tcp_socket_data_ref socket_data;
+	int packet_id;
+	packet_t packet;
+	size_t length;
+
+	assert(local_sockets);
+
+	// find the socket
+	socket = socket_cores_find(local_sockets, socket_id);
+	if(! socket){
+		return ENOTSOCK;
+	}
+	// get the socket specific data
+	if(! socket->specific_data){
+		return NO_DATA;
+	}
+	socket_data = (tcp_socket_data_ref) socket->specific_data;
+
+	// check state
+	if((socket_data->state != TCP_SOCKET_ESTABLISHED) && (socket_data->state != TCP_SOCKET_CLOSE_WAIT)){
+		return ENOTCONN;
+	}
+
+	// send the source address if desired
+	if(addrlen){
+		ERROR_PROPAGATE(data_reply(socket_data->addr, socket_data->addrlen));
+		*addrlen = socket_data->addrlen;
+	}
+
+	// get the next received packet
+	packet_id = dyn_fifo_value(&socket->received);
+	if(packet_id < 0){
+		return NO_DATA;
+	}
+	ERROR_PROPAGATE(packet_translate_remote(tcp_globals.net_phone, &packet, packet_id));
+
+	// reply the packets
+	ERROR_PROPAGATE(socket_reply_packets(packet, &length));
+
+	// release the packet
+	dyn_fifo_pop(&socket->received);
+	pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+	// return the total length
+	return (int) length;
+}
+
+int tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags){
+	ERROR_DECLARE;
+
+	socket_core_ref socket;
+	tcp_socket_data_ref socket_data;
+	packet_dimension_ref packet_dimension;
+	packet_t packet;
+	size_t total_length;
+	tcp_header_ref header;
+	int index;
+	int result;
+
+	assert(local_sockets);
+	assert(data_fragment_size);
+
+	// find the socket
+	socket = socket_cores_find(local_sockets, socket_id);
+	if(! socket){
+		return ENOTSOCK;
+	}
+	// get the socket specific data
+	if(! socket->specific_data){
+		return NO_DATA;
+	}
+	socket_data = (tcp_socket_data_ref) socket->specific_data;
+
+	// check state
+	if((socket_data->state != TCP_SOCKET_ESTABLISHED) && (socket_data->state != TCP_SOCKET_CLOSE_WAIT)){
+		return ENOTCONN;
+	}
+
+	ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
+
+	*data_fragment_size = ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size);
+
+	for(index = 0; index < fragments; ++ index){
+		// read the data fragment
+		result = tl_socket_read_packet_data(tcp_globals.net_phone, &packet, TCP_HEADER_SIZE, packet_dimension, socket_data->addr, socket_data->addrlen);
+		if(result < 0){
+			return result;
+		}
+		total_length = (size_t) result;
+		// prefix the tcp header
+		header = PACKET_PREFIX(packet, tcp_header_t);
+		if(! header){
+			return tcp_release_and_return(packet, ENOMEM);
+		}
+		tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
+		ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 0));
+	}
+
+	// flush packets
+	packet = tcp_get_packets_to_send(socket, socket_data);
+	fibril_rwlock_write_unlock(socket_data->local_lock);
+	fibril_rwlock_read_unlock(&tcp_globals.lock);
+	if(packet){
+		// send the packet
+		tcp_send_packets(socket_data->device_id, packet);
+	}
+
+	return EOK;
+}
+
+int tcp_close_message(socket_cores_ref local_sockets, int socket_id){
+	ERROR_DECLARE;
+
+	socket_core_ref socket;
+	tcp_socket_data_ref socket_data;
+	packet_t packet;
+
+	// find the socket
+	socket = socket_cores_find(local_sockets, socket_id);
+	if(! socket){
+		return ENOTSOCK;
+	}
+	// get the socket specific data
+	socket_data = (tcp_socket_data_ref) socket->specific_data;
+	assert(socket_data);
+
+	// check state
+	switch(socket_data->state){
+		case TCP_SOCKET_ESTABLISHED:
+			socket_data->state = TCP_SOCKET_FIN_WAIT_1;
+			break;
+		case TCP_SOCKET_CLOSE_WAIT:
+			socket_data->state = TCP_SOCKET_LAST_ACK;
+			break;
+//		case TCP_SOCKET_LISTEN:
+		default:
+			// just destroy
+			if(! ERROR_OCCURRED(socket_destroy(tcp_globals.net_phone, socket_id, local_sockets, &tcp_globals.sockets, tcp_free_socket_data))){
+				fibril_rwlock_write_unlock(socket_data->local_lock);
+				fibril_rwlock_write_unlock(&tcp_globals.lock);
+			}
+			return ERROR_CODE;
+	}
+	// send FIN
+	// TODO should I wait to complete?
+
+	// create the notification packet
+	ERROR_PROPAGATE(tcp_create_notification_packet(&packet, socket, socket_data, 0, 1));
+
+	// send the packet
+	ERROR_PROPAGATE(tcp_queue_packet(socket, socket_data, packet, 1));
+
+	// flush packets
+	packet = tcp_get_packets_to_send(socket, socket_data);
+	fibril_rwlock_write_unlock(socket_data->local_lock);
+	fibril_rwlock_write_unlock(&tcp_globals.lock);
+	if(packet){
+		// send the packet
+		tcp_send_packets(socket_data->device_id, packet);
+	}
+	return EOK;
+}
+
+int tcp_create_notification_packet(packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize){
+	ERROR_DECLARE;
+
+	packet_dimension_ref packet_dimension;
+	tcp_header_ref header;
+
+	assert(packet);
+
+	// get the device packet dimension
+	ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
+	// get a new packet
+	*packet = packet_get_4_remote(tcp_globals.net_phone, TCP_HEADER_SIZE, packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix);
+	if(! * packet){
+		return ENOMEM;
+	}
+	// allocate space in the packet
+	header = PACKET_SUFFIX(*packet, tcp_header_t);
+	if(! header){
+		tcp_release_and_return(*packet, ENOMEM);
+	}
+
+	tcp_prepare_operation_header(socket, socket_data, header, synchronize, finalize);
+	return EOK;
+}
+
+int tcp_accept_message(socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen){
+	ERROR_DECLARE;
+
+	socket_core_ref accepted;
+	socket_core_ref socket;
+	tcp_socket_data_ref socket_data;
+	packet_dimension_ref packet_dimension;
+
+	assert(local_sockets);
+	assert(data_fragment_size);
+	assert(addrlen);
+
+	// find the socket
+	socket = socket_cores_find(local_sockets, socket_id);
+	if(! socket){
+		return ENOTSOCK;
+	}
+	// get the socket specific data
+	socket_data = (tcp_socket_data_ref) socket->specific_data;
+	assert(socket_data);
+
+	// check state
+	if(socket_data->state != TCP_SOCKET_LISTEN){
+		return EINVAL;
+	}
+
+	do{
+		socket_id = dyn_fifo_value(&socket->accepted);
+		if(socket_id < 0){
+			return ENOTSOCK;
+		}
+		socket_id *= -1;
+
+		accepted = socket_cores_find(local_sockets, socket_id);
+		if(! accepted){
+			return ENOTSOCK;
+		}
+		// get the socket specific data
+		socket_data = (tcp_socket_data_ref) accepted->specific_data;
+		assert(socket_data);
+		// TODO can it be in another state?
+		if(socket_data->state == TCP_SOCKET_ESTABLISHED){
+			ERROR_PROPAGATE(data_reply(socket_data->addr, socket_data->addrlen));
+			ERROR_PROPAGATE(tl_get_ip_packet_dimension(tcp_globals.ip_phone, &tcp_globals.dimensions, socket_data->device_id, &packet_dimension));
+			*addrlen = socket_data->addrlen;
+			*data_fragment_size = ((packet_dimension->content < socket_data->data_fragment_size) ? packet_dimension->content : socket_data->data_fragment_size);
+			if(new_socket_id > 0){
+				ERROR_PROPAGATE(socket_cores_update(local_sockets, accepted->socket_id, new_socket_id));
+				accepted->socket_id = new_socket_id;
+			}
+		}
+		dyn_fifo_pop(&socket->accepted);
+	}while(socket_data->state != TCP_SOCKET_ESTABLISHED);
+	printf("ret accept %d\n", accepted->socket_id);
+	return accepted->socket_id;
+}
+
+void tcp_free_socket_data(socket_core_ref socket){
+	tcp_socket_data_ref socket_data;
+
+	assert(socket);
+
+	printf("destroy_socket %d\n", socket->socket_id);
+
+	// get the socket specific data
+	socket_data = (tcp_socket_data_ref) socket->specific_data;
+	assert(socket_data);
+	//free the pseudo header
+	if(socket_data->pseudo_header){
+		if(socket_data->headerlen){
+			printf("d pseudo\n");
+			free(socket_data->pseudo_header);
+			socket_data->headerlen = 0;
+		}
+		socket_data->pseudo_header = NULL;
+	}
+	socket_data->headerlen = 0;
+	// free the address
+	if(socket_data->addr){
+		if(socket_data->addrlen){
+			printf("d addr\n");
+			free(socket_data->addr);
+			socket_data->addrlen = 0;
+		}
+		socket_data->addr = NULL;
+	}
+	socket_data->addrlen = 0;
+}
+
+int tcp_release_and_return(packet_t packet, int result){
+	pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+	return result;
+}
+
+/** Default thread for new connections.
+ *
+ *  @param[in] iid The initial message identifier.
+ *  @param[in] icall The initial message call structure.
+ *
+ */
+static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
+{
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0(iid, EOK);
+	
+	while(true) {
+		ipc_call_t answer;
+		int answer_count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &answer_count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = tl_module_message_standalone(callid, &call, &answer,
+		    &answer_count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, answer_count);
+	}
+}
+
+/** Starts the module.
+ *
+ *  @param argc The count of the command line arguments. Ignored parameter.
+ *  @param argv The command line parameters. Ignored parameter.
+ *
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module start function.
+ *
+ */
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	/* Start the module */
+	if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
+		return ERROR_CODE;
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/tcp/tcp.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/tcp/tcp.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,298 @@
+/*
+ * 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.
+ */
+
+#ifndef __NET_TCP_H__
+#define __NET_TCP_H__
+
+#include <fibril_synch.h>
+
+#include <packet/packet.h>
+#include <net_device.h>
+#include <socket_core.h>
+#include <tl_common.h>
+
+/** Type definition of the TCP global data.
+ *  @see tcp_globals
+ */
+typedef struct tcp_globals	tcp_globals_t;
+
+/** Type definition of the TCP socket specific data.
+ *  @see tcp_socket_data
+ */
+typedef struct tcp_socket_data	tcp_socket_data_t;
+
+/** Type definition of the TCP socket specific data pointer.
+ *  @see tcp_socket_data
+ */
+typedef tcp_socket_data_t *	tcp_socket_data_ref;
+
+/** Type definition of the TCP operation data.
+ *  @see tcp_operation
+ */
+typedef struct tcp_operation	tcp_operation_t;
+
+/** Type definition of the TCP operation data pointer.
+ *  @see tcp_operation
+ */
+typedef tcp_operation_t *	tcp_operation_ref;
+
+/** TCP socket state type definition.
+ *  @see tcp_socket_state
+ */
+typedef enum tcp_socket_state	tcp_socket_state_t;
+
+/** TCP socket state.
+ */
+enum tcp_socket_state{
+	/** Initial.
+	 *  Not connected or bound.
+	 */
+	TCP_SOCKET_INITIAL,
+	/** Listening.
+	 *  Awaiting a connection request from another TCP layer.
+	 *  When SYN is received a new bound socket in the TCP_SOCKET_SYN_RECEIVED state should be created.
+	 */
+	TCP_SOCKET_LISTEN,
+	/** Connecting issued.
+	 *  A~SYN has been sent, and TCP is awaiting the response SYN.
+	 *  Should continue to the TCP_SOCKET_ESTABLISHED state.
+	 */
+	TCP_SOCKET_SYN_SENT,
+	/** Connecting received.
+	 *  A~SYN has been received, a~SYN has been sent, and TCP is awaiting an ACK.
+	 *  Should continue to the TCP_SOCKET_ESTABLISHED state.
+	 */
+	TCP_SOCKET_SYN_RECEIVED,
+	/** Connected.
+	 *  The three-way handshake has been completed.
+	 */
+	TCP_SOCKET_ESTABLISHED,
+	/** Closing started.
+	 *  The local application has issued a~CLOSE.
+	 *  TCP has sent a~FIN, and is awaiting an ACK or a~FIN.
+	 *  Should continue to the TCP_SOCKET_FIN_WAIT_2 state when an ACK is received.
+	 *  Should continue to the TCP_SOCKET_CLOSING state when a~FIN is received.
+	 */
+	TCP_SOCKET_FIN_WAIT_1,
+	/** Closing confirmed.
+	 *  A~FIN has been sent, and an ACK received.
+	 *  TCP is awaiting a~FIN from the remote TCP layer.
+	 *  Should continue to the TCP_SOCKET_CLOSING state.
+	 */
+	TCP_SOCKET_FIN_WAIT_2,
+	/** Closing.
+	 *  A FIN has been sent, a FIN has been received, and an ACK has been sent.
+	 *  TCP is awaiting an ACK for the FIN that was sent.
+	 *  Should continue to the TCP_SOCKET_TIME_WAIT state.
+	 */
+	TCP_SOCKET_CLOSING,
+	/** Closing received.
+	 *  TCP has received a~FIN, and has sent an ACK.
+	 *  It is awaiting a~close request from the local application before sending a~FIN.
+	 *  Should continue to the TCP_SOCKET_SOCKET_LAST_ACK state.
+	 */
+	TCP_SOCKET_CLOSE_WAIT,
+	/** 
+	 *  A~FIN has been received, and an ACK and a~FIN have been sent.
+	 *  TCP is awaiting an ACK.
+	 *  Should continue to the TCP_SOCKET_TIME_WAIT state.
+	 */
+	TCP_SOCKET_LAST_ACK,
+	/** Closing finished.
+	 *  FINs have been received and ACK’d, and TCP is waiting two MSLs to remove the connection from the table.
+	 */
+	TCP_SOCKET_TIME_WAIT,
+	/** Closed.
+	 *  Imaginary, this indicates that a~connection has been removed from the connection table.
+	 */
+	TCP_SOCKET_CLOSED
+};
+
+/** TCP operation data.
+ */
+struct tcp_operation{
+	/** Operation result.
+	 */
+	int result;
+	/** Safety lock.
+	 */
+	fibril_mutex_t mutex;
+	/** Operation result signaling.
+	 */
+	fibril_condvar_t condvar;
+};
+
+/** TCP socket specific data.
+ */
+struct tcp_socket_data{
+	/** TCP socket state.
+	 */
+	tcp_socket_state_t state;
+	/** Data fragment size.
+	 *  Sending optimalization.
+	 */
+	size_t data_fragment_size;
+	/** Device identifier.
+	 */
+	device_id_t device_id;
+	/** Listening backlog.
+	 *  The maximal number of connected but not yet accepted sockets.
+	 */
+	int backlog;
+//	/** Segment size.
+//	 */
+//	size_t			segment_size;
+	/** Parent listening socket identifier.
+	 *  Set if this socket is an accepted one.
+	 */
+	int listening_socket_id;
+	/** Treshold size in bytes.
+	 */
+	size_t treshold;
+	/** Window size in bytes.
+	 */
+	size_t window;
+	/** Acknowledgement timeout.
+	 */
+	suseconds_t timeout;
+	/** Last acknowledged byte.
+	 */
+	uint32_t acknowledged;
+	/** Next incoming sequence number.
+	 */
+	uint32_t next_incoming;
+	/** Incoming FIN.
+	 */
+	uint32_t fin_incoming;
+	/** Next outgoing sequence number.
+	 */
+	uint32_t next_outgoing;
+	/** Last outgoing sequence number.
+	 */
+	uint32_t last_outgoing;
+	/** Outgoing FIN.
+	 */
+	uint32_t fin_outgoing;
+	/** Expected sequence number by the remote host.
+	 *  The sequence number the other host expects.
+	 *  The notification is sent only upon a packet reecival.
+	 */
+	uint32_t expected;
+	/** Expected sequence number counter.
+	 *  Counts the number of received notifications for the same sequence number.
+	 */
+	int expected_count;
+	/** Incoming packet queue.
+	 *  Packets are buffered until received in the right order.
+	 *  The packets are excluded after successfully read.
+	 *  Packets are sorted by their starting byte.
+	 *  Packets metric is set as their data length.
+	 */
+	packet_t incoming;
+	/** Outgoing packet queue.
+	 *  Packets are buffered until acknowledged by the remote host in the right order.
+	 *  The packets are excluded after acknowledged.
+	 *  Packets are sorted by their starting byte.
+	 *  Packets metric is set as their data length.
+	 */
+	packet_t outgoing;
+	/** IP pseudo header.
+	 */
+	void *pseudo_header;
+	/** IP pseudo header length.
+	 */
+	size_t headerlen;
+	/** Remote host address.
+	 */
+	struct sockaddr * addr;
+	/** Remote host address length.
+	 */
+	socklen_t addrlen;
+	/** Remote host port.
+	 */
+	uint16_t dest_port;
+	/** Parent local sockets.
+	 */
+	socket_cores_ref local_sockets;
+	/** Local sockets safety lock.
+	 *  May be locked for writing while holding the global lock for reading when changing the local sockets only.
+	 *  The global lock may to be locked only before locking the local lock.
+	 *  The global lock may be locked more weakly than the local lock.
+	 *  The global lock may be released before releasing the local lock.
+	 *  @see tcp_globals:lock
+	 */
+	fibril_rwlock_t * local_lock;
+	/** Pending operation data.
+	 */
+	tcp_operation_t operation;
+	/** Timeouts in a row counter.
+	 *  If TCP_MAX_TIMEOUTS is reached, the connection is lost.
+	 */
+	int timeout_count;
+};
+
+/** TCP global data.
+ */
+struct	tcp_globals{
+	/** Networking module phone.
+	 */
+	int net_phone;
+	/** IP module phone.
+	 */
+	int ip_phone;
+	/** ICMP module phone.
+	 */
+	int icmp_phone;
+	/** Last used free port.
+	 */
+	int last_used_port;
+	/** Active sockets.
+	 */
+	socket_ports_t sockets;
+	/** Device packet dimensions.
+	 */
+	packet_dimensions_t dimensions;
+	/** Safety lock.
+	 *  Write lock is used only for adding or removing socket ports.
+	 */
+	fibril_rwlock_t lock;
+};
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/tl/tcp/tcp_header.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_header.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/tcp/tcp_header.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,226 @@
+/*
+ * 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 tcp
+ *  @{
+ */
+
+/** @file
+ *  TCP header definition.
+ *  Based on the RFC~793.
+ */
+
+#ifndef __NET_TCP_HEADER_H__
+#define __NET_TCP_HEADER_H__
+
+#include <sys/types.h>
+
+/** TCP header size in bytes.
+ */
+#define TCP_HEADER_SIZE			sizeof(tcp_header_t)
+
+/** Returns the actual TCP header length in bytes.
+ *  @param[in] header The TCP packet header.
+ */
+#define TCP_HEADER_LENGTH(header)		((header)->header_length * 4u)
+
+/** Returns the TCP header length.
+ *  @param[in] length The TCP header length in bytes.
+ */
+#define TCP_COMPUTE_HEADER_LENGTH(length)		((uint8_t) ((length) / 4u))
+
+/** Type definition of the transmission datagram header.
+ *  @see tcp_header
+ */
+typedef struct tcp_header	tcp_header_t;
+
+/** Type definition of the transmission datagram header pointer.
+ *  @see tcp_header
+ */
+typedef tcp_header_t *		tcp_header_ref;
+
+/** Type definition of the transmission datagram header option.
+ *  @see tcp_option
+ */
+typedef struct tcp_option	tcp_option_t;
+
+/** Type definition of the transmission datagram header option pointer.
+ *  @see tcp_option
+ */
+typedef tcp_option_t *		tcp_option_ref;
+
+/** Type definition of the Maximum segment size TCP option.
+ *  @see ...
+ */
+typedef struct tcp_max_segment_size_option	tcp_max_segment_size_option_t;
+
+/** Type definition of the Maximum segment size TCP option pointer.
+ *  @see tcp_max_segment_size_option
+ */
+typedef tcp_max_segment_size_option_t *		tcp_max_segment_size_option_ref;
+
+/** Transmission datagram header.
+ */
+struct tcp_header{
+	/** The source port number.
+	 */
+	uint16_t source_port;
+	/** The destination port number.
+	 */
+	uint16_t destination_port;
+	/** The sequence number of the first data octet in this segment (except when SYN is present).
+	 *  If SYN is present the sequence number is the initial sequence number (ISN) and the first data octet is ISN+1.
+	 */
+	uint32_t sequence_number;
+	/** If the ACK control bit is set this field contains the value of the next sequence number the sender of the segment is expecting to receive.
+	 *  Once a~connection is established this is always sent.
+	 *  @see acknowledge
+	 */
+	uint32_t acknowledgement_number;
+#ifdef ARCH_IS_BIG_ENDIAN
+	/** The number of 32~bit words in the TCP Header.
+	 *  This indicates where the data begins.
+	 *  The TCP header (even one including options) is an integral number of 32~bits long.
+	 */
+	uint8_t header_length:4;
+	/** Four bits reserved for future use.
+	 *  Must be zero.
+	 */
+	uint8_t reserved1:4;
+#else
+	/** Four bits reserved for future use.
+	 *  Must be zero.
+	 */
+	uint8_t reserved1:4;
+	/** The number of 32~bit words in the TCP Header.
+	 *  This indicates where the data begins.
+	 *  The TCP header (even one including options) is an integral number of 32~bits long.
+	 */
+	uint8_t header_length:4;
+#endif
+#ifdef ARCH_IS_BIG_ENDIAN
+	/** Two bits reserved for future use.
+	 *  Must be zero.
+	 */
+	uint8_t reserved2:2;
+	/** Urgent Pointer field significant.
+	 *  @see tcp_header:urgent_pointer
+	 */
+	uint8_t urgent:1;
+	/** Acknowledgment field significant
+	 *  @see tcp_header:acknowledgement_number
+	 */
+	uint8_t acknowledge:1;
+	/** Push function.
+	 */
+	uint8_t push:1;
+	/** Reset the connection.
+	 */
+	uint8_t reset:1;
+	/** Synchronize the sequence numbers.
+	 */
+	uint8_t synchronize:1;
+	/** No more data from the sender.
+	 */
+	uint8_t finalize:1;
+#else
+	/** No more data from the sender.
+	 */
+	uint8_t finalize:1;
+	/** Synchronize the sequence numbers.
+	 */
+	uint8_t synchronize:1;
+	/** Reset the connection.
+	 */
+	uint8_t reset:1;
+	/** Push function.
+	 */
+	uint8_t push:1;
+	/** Acknowledgment field significant.
+	 *  @see tcp_header:acknowledgement_number
+	 */
+	uint8_t acknowledge:1;
+	/** Urgent Pointer field significant.
+	 *  @see tcp_header:urgent_pointer
+	 */
+	uint8_t urgent:1;
+	/** Two bits reserved for future use.
+	 *  Must be zero.
+	 */
+	uint8_t reserved2:2;
+#endif
+	/** The number of data octets beginning with the one indicated in the acknowledgment field which the sender of this segment is willing to accept.
+	 *  @see tcp_header:acknowledge
+	 */
+	uint16_t window;
+	/** The checksum field is the 16~bit one's complement of the one's complement sum of all 16~bit words in the header and text.
+	 *  If a~segment contains an odd number of header and text octets to be checksummed, the last octet is padded on the right with zeros to form a~16~bit word for checksum purposes.
+	 *  The pad is not transmitted as part of the segment.
+	 *  While computing the checksum, the checksum field itself is replaced with zeros.
+	 *  The checksum also coves a~pseudo header conceptually.
+	 *  The pseudo header conceptually prefixed to the TCP header contains the source address, the destination address, the protocol, and the TCP length.
+	 *  This information gives protection against misrouted datagrams.
+	 *  If the computed checksum is zero, it is transmitted as all ones (the equivalent in one's complement arithmetic).
+	 */
+	uint16_t checksum;
+	/** This field communicates the current value of the urgent pointer as a~positive offset from the sequence number in this segment.
+	 *  The urgent pointer points to the sequence number of the octet following the urgent data.
+	 *  This field is only be interpreted in segments with the URG control bit set.
+	 *  @see tcp_header:urgent
+	 */
+	uint16_t urgent_pointer;
+} __attribute__ ((packed));
+
+/** Transmission datagram header option.
+ */
+struct tcp_option{
+	/** Option type.
+	 */
+	uint8_t type;
+	/** Option length.
+	 */
+	uint8_t length;
+};
+
+/** Maximum segment size TCP option.
+ */
+struct tcp_max_segment_size_option{
+	/** TCP option.
+	 *  @see TCPOPT_MAX_SEGMENT_SIZE
+	 *  @see TCPOPT_MAX_SEGMENT_SIZE_LENGTH
+	 */
+	tcp_option_t option;
+	/** Maximum segment size in bytes.
+	 */
+	uint16_t max_segment_size;
+} __attribute__ ((packed));
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/tcp/tcp_module.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/tcp/tcp_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,101 @@
+/*
+ * 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 <async.h>
+#include <stdio.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_modules.h>
+#include <packet/packet.h>
+#include <net_interface.h>
+#include <ip_protocols.h>
+#include <ip_interface.h>
+#include <tl_local.h>
+
+#include "tcp.h"
+#include "tcp_module.h"
+
+/** TCP module global data.
+ */
+extern tcp_globals_t	tcp_globals;
+
+/** Starts the TCP 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.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the tcp_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int tl_module_start_standalone(async_client_conn_t client_connection)
+{
+	ERROR_DECLARE;
+	
+	async_set_client_connection(client_connection);
+	tcp_globals.net_phone = net_connect_module(SERVICE_NETWORKING);
+	ERROR_PROPAGATE(pm_init());
+	
+	ipcarg_t phonehash;
+	if (ERROR_OCCURRED(tcp_initialize(client_connection))
+	    || ERROR_OCCURRED(REGISTER_ME(SERVICE_TCP, &phonehash))) {
+		pm_destroy();
+		return ERROR_CODE;
+	}
+	
+	async_manager();
+	
+	pm_destroy();
+	return EOK;
+}
+
+/** Processes the TCP 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the tcp_message() function.
+ */
+int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	return tcp_message_standalone(callid, call, answer, answer_count);
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/tcp/tcp_module.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_module.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/tcp/tcp_module.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,66 @@
+/*
+ * 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>
+
+/** Initializes the TCP module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+extern int tcp_initialize(async_client_conn_t client_connection);
+
+/** Processes the TCP 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see tcp_interface.h
+ *  @see IS_NET_TCP_MESSAGE()
+ */
+extern int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/udp/Makefile
===================================================================
--- uspace/srv/net/tl/udp/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/udp/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,39 @@
+#
+# 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 = ../../../..
+LIBS = $(LIBNET_PREFIX)/libnet.a $(LIBSOCKET_PREFIX)/libsocket.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBSOCKET_PREFIX)/include
+BINARY = udp
+
+SOURCES = \
+	udp.c \
+	udp_module.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/udp/udp.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,763 @@
+/*
+ * 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 implementation.
+ *  @see udp.h
+ */
+
+#include <async.h>
+#include <fibril_synch.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_messages.h>
+#include <net_modules.h>
+#include <adt/dynamic_fifo.h>
+#include <packet/packet_client.h>
+#include <packet_remote.h>
+#include <net_checksum.h>
+#include <in.h>
+#include <in6.h>
+#include <inet.h>
+#include <ip_client.h>
+#include <ip_interface.h>
+#include <ip_protocols.h>
+#include <icmp_client.h>
+#include <icmp_interface.h>
+#include <net_interface.h>
+#include <socket_codes.h>
+#include <socket_errno.h>
+#include <socket_core.h>
+#include <socket_messages.h>
+#include <tl_common.h>
+#include <tl_local.h>
+#include <tl_interface.h>
+#include <tl_messages.h>
+
+#include "udp.h"
+#include "udp_header.h"
+#include "udp_module.h"
+
+/** UDP module name.
+ */
+#define NAME	"UDP protocol"
+
+/** Default UDP checksum computing.
+ */
+#define NET_DEFAULT_UDP_CHECKSUM_COMPUTING	true
+
+/** Default UDP autobind when sending via unbound sockets.
+ */
+#define NET_DEFAULT_UDP_AUTOBINDING	true
+
+/** Maximum UDP fragment size.
+ */
+#define MAX_UDP_FRAGMENT_SIZE	65535
+
+/** Free ports pool start.
+ */
+#define UDP_FREE_PORTS_START	1025
+
+/** Free ports pool end.
+ */
+#define UDP_FREE_PORTS_END		65535
+
+/** Processes the received UDP packet queue.
+ *  Is used as an entry point from the underlying IP module.
+ *  Locks the global lock and calls udp_process_packet() function.
+ *  @param[in] device_id The receiving device identifier.
+ *  @param[in,out] packet The received packet queue.
+ *  @param receiver The target service. Ignored parameter.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the udp_process_packet() function.
+ */
+int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error);
+
+/** Processes the received UDP packet queue.
+ *  Notifies the destination socket application.
+ *  Releases the packet on error or sends an ICMP error notification..
+ *  @param[in] device_id The receiving device identifier.
+ *  @param[in,out] packet The received packet queue.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns EINVAL if the stored packet address is not the an_addr_t.
+ *  @returns EINVAL if the packet does not contain any data.
+ *  @returns NO_DATA if the packet content is shorter than the user datagram header.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EADDRNOTAVAIL if the destination socket does not exist.
+ *  @returns Other error codes as defined for the ip_client_process_packet() function.
+ */
+int udp_process_packet(device_id_t device_id, packet_t packet, services_t error);
+
+/** Releases the packet and returns the result.
+ *  @param[in] packet The packet queue to be released.
+ *  @param[in] result The result to be returned.
+ *  @return The result parameter.
+ */
+int udp_release_and_return(packet_t packet, int result);
+
+/** @name Socket messages processing functions
+ */
+/*@{*/
+
+/** Processes the socket client messages.
+ *  Runs until the client module disconnects.
+ *  @param[in] callid The message identifier.
+ *  @param[in] call The message parameters.
+ *  @returns EOK on success.
+ *  @see socket.h
+ */
+int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
+
+/** Sends data from the socket to the remote address.
+ *  Binds the socket to a free port if not already connected/bound.
+ *  Handles the NET_SOCKET_SENDTO message.
+ *  Supports AF_INET and AF_INET6 address families.
+ *  @param[in,out] local_sockets The application local sockets.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] addr The destination address.
+ *  @param[in] addrlen The address length.
+ *  @param[in] fragments The number of data fragments.
+ *  @param[out] data_fragment_size The data fragment size in bytes.
+ *  @param[in] flags Various send flags.
+ *  @returns EOK on success.
+ *  @returns EAFNOTSUPPORT if the address family is not supported.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EINVAL if the address is invalid.
+ *  @returns ENOTCONN if the sending socket is not and cannot be bound.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the socket_read_packet_data() function.
+ *  @returns Other error codes as defined for the ip_client_prepare_packet() function.
+ *  @returns Other error codes as defined for the ip_send_msg() function.
+ */
+int udp_sendto_message(socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags);
+
+/** Receives data to the socket.
+ *  Handles the NET_SOCKET_RECVFROM message.
+ *  Replies the source address as well.
+ *  @param[in] local_sockets The application local sockets.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] flags Various receive flags.
+ *  @param[out] addrlen The source address length.
+ *  @returns The number of bytes received.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns NO_DATA if there are no received packets or data.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EINVAL if the received address is not an IP address.
+ *  @returns Other error codes as defined for the packet_translate() function.
+ *  @returns Other error codes as defined for the data_reply() function.
+ */
+int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen);
+
+/*@}*/
+
+/** UDP global data.
+ */
+udp_globals_t	udp_globals;
+
+int udp_initialize(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+
+	measured_string_t names[] = {{str_dup("UDP_CHECKSUM_COMPUTING"), 22}, {str_dup("UDP_AUTOBINDING"), 15}};
+	measured_string_ref configuration;
+	size_t count = sizeof(names) / sizeof(measured_string_t);
+	char * data;
+
+	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, udp_received_msg);
+	if(udp_globals.ip_phone < 0){
+		return udp_globals.ip_phone;
+	}
+	// read default packet dimensions
+	ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension));
+	ERROR_PROPAGATE(socket_ports_initialize(&udp_globals.sockets));
+	if(ERROR_OCCURRED(packet_dimensions_initialize(&udp_globals.dimensions))){
+		socket_ports_destroy(&udp_globals.sockets);
+		return ERROR_CODE;
+	}
+	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;
+	// get configuration
+	udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
+	udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
+	configuration = &names[0];
+	ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, count, &data));
+	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;
+}
+
+int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
+	int result;
+
+	fibril_rwlock_write_lock(&udp_globals.lock);
+	result = udp_process_packet(device_id, packet, error);
+	if(result != EOK){
+		fibril_rwlock_write_unlock(&udp_globals.lock);
+	}
+
+	return result;
+}
+
+int udp_process_packet(device_id_t device_id, packet_t packet, services_t error){
+	ERROR_DECLARE;
+
+	size_t length;
+	size_t offset;
+	int result;
+	udp_header_ref header;
+	socket_core_ref socket;
+	packet_t next_packet;
+	size_t total_length;
+	uint32_t checksum;
+	int fragments;
+	packet_t tmp_packet;
+	icmp_type_t type;
+	icmp_code_t code;
+	void *ip_header;
+	struct sockaddr * src;
+	struct sockaddr * dest;
+	packet_dimension_ref packet_dimension;
+
+	if(error){
+		switch(error){
+			case SERVICE_ICMP:
+				// ignore error
+				// length = icmp_client_header_length(packet);
+				// process error
+				result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
+				if(result < 0){
+					return udp_release_and_return(packet, result);
+				}
+				length = (size_t) result;
+				if(ERROR_OCCURRED(packet_trim(packet, length, 0))){
+					return udp_release_and_return(packet, ERROR_CODE);
+				}
+				break;
+			default:
+				return udp_release_and_return(packet, ENOTSUP);
+		}
+	}
+	// TODO process received ipopts?
+	result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
+	if(result < 0){
+		return udp_release_and_return(packet, result);
+	}
+	offset = (size_t) result;
+
+	length = packet_get_data_length(packet);
+	if(length <= 0){
+		return udp_release_and_return(packet, EINVAL);
+	}
+	if(length < UDP_HEADER_SIZE + offset){
+		return udp_release_and_return(packet, NO_DATA);
+	}
+
+	// trim all but UDP header
+	if(ERROR_OCCURRED(packet_trim(packet, offset, 0))){
+		return udp_release_and_return(packet, ERROR_CODE);
+	}
+
+	// get udp header
+	header = (udp_header_ref) packet_get_data(packet);
+	if(! header){
+		return udp_release_and_return(packet, NO_DATA);
+	}
+	// find the destination socket
+	socket = socket_port_find(&udp_globals.sockets, ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
+	if(! socket){
+		if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){
+			icmp_destination_unreachable_msg(udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet);
+		}
+		return EADDRNOTAVAIL;
+	}
+
+	// count the received packet fragments
+	next_packet = packet;
+	fragments = 0;
+	total_length = ntohs(header->total_length);
+	// compute header checksum if set
+	if(header->checksum && (! error)){
+		result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
+		if(result <= 0){
+			return udp_release_and_return(packet, result);
+		}
+		if(ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest, result, total_length, &ip_header, &length))){
+			return udp_release_and_return(packet, ERROR_CODE);
+		}else{
+			checksum = compute_checksum(0, ip_header, length);
+			// the udp header checksum will be added with the first fragment later
+			free(ip_header);
+		}
+	}else{
+		header->checksum = 0;
+		checksum = 0;
+	}
+
+	do{
+		++ fragments;
+		length = packet_get_data_length(next_packet);
+		if(length <= 0){
+			return udp_release_and_return(packet, NO_DATA);
+		}
+		if(total_length < length){
+			if(ERROR_OCCURRED(packet_trim(next_packet, 0, length - total_length))){
+				return udp_release_and_return(packet, ERROR_CODE);
+			}
+			// add partial checksum if set
+			if(header->checksum){
+				checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
+			}
+			// relese the rest of the packet fragments
+			tmp_packet = pq_next(next_packet);
+			while(tmp_packet){
+				next_packet = pq_detach(tmp_packet);
+				pq_release_remote(udp_globals.net_phone, packet_get_id(tmp_packet));
+				tmp_packet = next_packet;
+			}
+			// exit the loop
+			break;
+		}
+		total_length -= length;
+		// add partial checksum if set
+		if(header->checksum){
+			checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
+		}
+	}while((next_packet = pq_next(next_packet)) && (total_length > 0));
+
+	// check checksum
+	if(header->checksum){
+		if(flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO){
+			if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){
+				// checksum error ICMP
+				icmp_parameter_problem_msg(udp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet);
+			}
+			return EINVAL;
+		}
+	}
+
+	// queue the received packet
+	if(ERROR_OCCURRED(dyn_fifo_push(&socket->received, packet_get_id(packet), SOCKET_MAX_RECEIVED_SIZE))
+	    || ERROR_OCCURRED(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension))){
+		return udp_release_and_return(packet, ERROR_CODE);
+	}
+
+	// notify the destination socket
+	fibril_rwlock_write_unlock(&udp_globals.lock);
+	async_msg_5(socket->phone, NET_SOCKET_RECEIVED, (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0, (ipcarg_t) fragments);
+	return EOK;
+}
+
+int udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	ERROR_DECLARE;
+
+	packet_t packet;
+
+	*answer_count = 0;
+	switch(IPC_GET_METHOD(*call)){
+		case NET_TL_RECEIVED:
+			if(! ERROR_OCCURRED(packet_translate_remote(udp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
+				ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_UDP, IPC_GET_ERROR(call));
+			}
+			return ERROR_CODE;
+		case IPC_M_CONNECT_TO_ME:
+			return udp_process_client_messages(callid, * call);
+	}
+	return ENOTSUP;
+}
+
+int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
+	int res;
+	bool keep_on_going = true;
+	socket_cores_t local_sockets;
+	int app_phone = IPC_GET_PHONE(&call);
+	struct sockaddr * addr;
+	int socket_id;
+	size_t addrlen;
+	size_t size;
+	ipc_call_t answer;
+	int answer_count;
+	packet_dimension_ref packet_dimension;
+
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_TO_ME call.
+	 */
+	res = EOK;
+	answer_count = 0;
+
+	// The client connection is only in one fibril and therefore no additional locks are needed.
+
+	socket_cores_initialize(&local_sockets);
+
+	while(keep_on_going){
+
+		// answer the call
+		answer_call(callid, res, &answer, answer_count);
+
+		// refresh data
+		refresh_answer(&answer, &answer_count);
+
+		// get the next call
+		callid = async_get_call(&call);
+
+		// process the call
+		switch(IPC_GET_METHOD(call)){
+			case IPC_M_PHONE_HUNGUP:
+				keep_on_going = false;
+				res = EHANGUP;
+				break;
+			case NET_SOCKET:
+				socket_id = SOCKET_GET_SOCKET_ID(call);
+				res = socket_create(&local_sockets, app_phone, NULL, &socket_id);
+				SOCKET_SET_SOCKET_ID(answer, socket_id);
+
+				if(res == EOK){
+					if (tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, DEVICE_INVALID_ID, &packet_dimension) == EOK){
+						SOCKET_SET_DATA_FRAGMENT_SIZE(answer, packet_dimension->content);
+					}
+//					SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_UDP_FRAGMENT_SIZE);
+					SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
+					answer_count = 3;
+				}
+				break;
+			case NET_SOCKET_BIND:
+				res = data_receive((void **) &addr, &addrlen);
+				if(res == EOK){
+					fibril_rwlock_write_lock(&udp_globals.lock);
+					res = socket_bind(&local_sockets, &udp_globals.sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port);
+					fibril_rwlock_write_unlock(&udp_globals.lock);
+					free(addr);
+				}
+				break;
+			case NET_SOCKET_SENDTO:
+				res = data_receive((void **) &addr, &addrlen);
+				if(res == EOK){
+					fibril_rwlock_write_lock(&udp_globals.lock);
+					res = udp_sendto_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS(call), &size, SOCKET_GET_FLAGS(call));
+					SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
+					if(res != EOK){
+						fibril_rwlock_write_unlock(&udp_globals.lock);
+					}else{
+						answer_count = 2;
+					}
+					free(addr);
+				}
+				break;
+			case NET_SOCKET_RECVFROM:
+				fibril_rwlock_write_lock(&udp_globals.lock);
+				res = udp_recvfrom_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), &addrlen);
+				fibril_rwlock_write_unlock(&udp_globals.lock);
+				if(res > 0){
+					SOCKET_SET_READ_DATA_LENGTH(answer, res);
+					SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
+					answer_count = 3;
+					res = EOK;
+				}
+				break;
+			case NET_SOCKET_CLOSE:
+				fibril_rwlock_write_lock(&udp_globals.lock);
+				res = socket_destroy(udp_globals.net_phone, SOCKET_GET_SOCKET_ID(call), &local_sockets, &udp_globals.sockets, NULL);
+				fibril_rwlock_write_unlock(&udp_globals.lock);
+				break;
+			case NET_SOCKET_GETSOCKOPT:
+			case NET_SOCKET_SETSOCKOPT:
+			default:
+				res = ENOTSUP;
+				break;
+		}
+	}
+
+	// release the application phone
+	ipc_hangup(app_phone);
+
+	// release all local sockets
+	socket_cores_release(udp_globals.net_phone, &local_sockets, &udp_globals.sockets, NULL);
+
+	return res;
+}
+
+int udp_sendto_message(socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags){
+	ERROR_DECLARE;
+
+	socket_core_ref socket;
+	packet_t packet;
+	packet_t next_packet;
+	udp_header_ref header;
+	int index;
+	size_t total_length;
+	int result;
+	uint16_t dest_port;
+	uint32_t checksum;
+	void *ip_header;
+	size_t headerlen;
+	device_id_t device_id;
+	packet_dimension_ref packet_dimension;
+
+	ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &dest_port));
+
+	socket = socket_cores_find(local_sockets, socket_id);
+	if(! socket){
+		return ENOTSOCK;
+	}
+
+	if((socket->port <= 0) && udp_globals.autobinding){
+		// bind the socket to a random free port if not bound
+//		do{
+			// try to find a free port
+//			fibril_rwlock_read_unlock(&udp_globals.lock);
+//			fibril_rwlock_write_lock(&udp_globals.lock);
+			// might be changed in the meantime
+//			if(socket->port <= 0){
+				if(ERROR_OCCURRED(socket_bind_free_port(&udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port))){
+//					fibril_rwlock_write_unlock(&udp_globals.lock);
+//					fibril_rwlock_read_lock(&udp_globals.lock);
+					return ERROR_CODE;
+				}
+				// set the next port as the search starting port number
+				udp_globals.last_used_port = socket->port;
+//			}
+//			fibril_rwlock_write_unlock(&udp_globals.lock);
+//			fibril_rwlock_read_lock(&udp_globals.lock);
+			// might be changed in the meantime
+//		}while(socket->port <= 0);
+	}
+
+	if(udp_globals.checksum_computing){
+		if(ERROR_OCCURRED(ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, &device_id, &ip_header, &headerlen))){
+			return udp_release_and_return(packet, ERROR_CODE);
+		}
+		// get the device packet dimension
+//		ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension));
+	}
+//	}else{
+		// do not ask all the time
+		ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension));
+		packet_dimension = &udp_globals.packet_dimension;
+//	}
+
+	// read the first packet fragment
+	result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
+	if(result < 0){
+		return result;
+	}
+	total_length = (size_t) result;
+	if(udp_globals.checksum_computing){
+		checksum = compute_checksum(0, packet_get_data(packet), packet_get_data_length(packet));
+	}else{
+		checksum = 0;
+	}
+	// prefix the udp header
+	header = PACKET_PREFIX(packet, udp_header_t);
+	if(! header){
+		return udp_release_and_return(packet, ENOMEM);
+	}
+	bzero(header, sizeof(*header));
+	// read the rest of the packet fragments
+	for(index = 1; index < fragments; ++ index){
+		result = tl_socket_read_packet_data(udp_globals.net_phone, &next_packet, 0, packet_dimension, addr, addrlen);
+		if(result < 0){
+			return udp_release_and_return(packet, result);
+		}
+		if(ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0))){
+			return udp_release_and_return(packet, ERROR_CODE);
+		}
+		total_length += (size_t) result;
+		if(udp_globals.checksum_computing){
+			checksum = compute_checksum(checksum, packet_get_data(next_packet), packet_get_data_length(next_packet));
+		}
+	}
+	// set the udp header
+	header->source_port = htons((socket->port > 0) ? socket->port : 0);
+	header->destination_port = htons(dest_port);
+	header->total_length = htons(total_length + sizeof(*header));
+	header->checksum = 0;
+	if(udp_globals.checksum_computing){
+		// update the pseudo header
+		if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(ip_header, headerlen, total_length + UDP_HEADER_SIZE))){
+			free(ip_header);
+			return udp_release_and_return(packet, ERROR_CODE);
+		}
+		// finish the checksum computation
+		checksum = compute_checksum(checksum, ip_header, headerlen);
+		checksum = compute_checksum(checksum, (uint8_t *) header, sizeof(*header));
+		header->checksum = htons(flip_checksum(compact_checksum(checksum)));
+		free(ip_header);
+	}else{
+		device_id = DEVICE_INVALID_ID;
+	}
+	// prepare the first packet fragment
+	if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0))){
+		return udp_release_and_return(packet, ERROR_CODE);
+	}
+	// send the packet
+	fibril_rwlock_write_unlock(&udp_globals.lock);
+	ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);
+	return EOK;
+}
+
+int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){
+	ERROR_DECLARE;
+
+	socket_core_ref socket;
+	int packet_id;
+	packet_t packet;
+	udp_header_ref header;
+	struct sockaddr * addr;
+	size_t length;
+	uint8_t * data;
+	int result;
+
+	// find the socket
+	socket = socket_cores_find(local_sockets, socket_id);
+	if(! socket){
+		return ENOTSOCK;
+	}
+	// get the next received packet
+	packet_id = dyn_fifo_value(&socket->received);
+	if(packet_id < 0){
+		return NO_DATA;
+	}
+	ERROR_PROPAGATE(packet_translate_remote(udp_globals.net_phone, &packet, packet_id));
+	// get udp header
+	data = packet_get_data(packet);
+	if(! data){
+		pq_release_remote(udp_globals.net_phone, packet_id);
+		return NO_DATA;
+	}
+	header = (udp_header_ref) data;
+
+	// set the source address port
+	result = packet_get_addr(packet, (uint8_t **) &addr, NULL);
+	if(ERROR_OCCURRED(tl_set_address_port(addr, result, ntohs(header->source_port)))){
+		pq_release_remote(udp_globals.net_phone, packet_id);
+		return ERROR_CODE;
+	}
+	*addrlen = (size_t) result;
+	// send the source address
+	ERROR_PROPAGATE(data_reply(addr, * addrlen));
+
+	// trim the header
+	ERROR_PROPAGATE(packet_trim(packet, UDP_HEADER_SIZE, 0));
+
+	// reply the packets
+	ERROR_PROPAGATE(socket_reply_packets(packet, &length));
+
+	// release the packet
+	dyn_fifo_pop(&socket->received);
+	pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
+	// return the total length
+	return (int) length;
+}
+
+int udp_release_and_return(packet_t packet, int result){
+	pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
+	return result;
+}
+
+/** Default thread for new connections.
+ *
+ *  @param[in] iid The initial message identifier.
+ *  @param[in] icall The initial message call structure.
+ *
+ */
+static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
+{
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0(iid, EOK);
+	
+	while(true) {
+		ipc_call_t answer;
+		int answer_count;
+		
+		/* Clear the answer structure */
+		refresh_answer(&answer, &answer_count);
+		
+		/* Fetch the next message */
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		/* Process the message */
+		int res = tl_module_message_standalone(callid, &call, &answer,
+		    &answer_count);
+		
+		/* End if said to either by the message or the processing result */
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+			return;
+		
+		/* Answer the message */
+		answer_call(callid, res, &answer, answer_count);
+	}
+}
+
+/** Starts the module.
+ *
+ *  @param argc The count of the command line arguments. Ignored parameter.
+ *  @param argv The command line parameters. Ignored parameter.
+ *
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module start function.
+ *
+ */
+int main(int argc, char *argv[])
+{
+	ERROR_DECLARE;
+	
+	/* Start the module */
+	if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
+		return ERROR_CODE;
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/udp/udp.h
===================================================================
--- uspace/srv/net/tl/udp/udp.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/udp/udp.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#ifndef __NET_UDP_H__
+#define __NET_UDP_H__
+
+#include <fibril_synch.h>
+#include <socket_core.h>
+#include <tl_common.h>
+
+/** Type definition of the UDP global data.
+ *  @see udp_globals
+ */
+typedef struct udp_globals	udp_globals_t;
+
+/** UDP global data.
+ */
+struct	udp_globals{
+	/** Networking module phone.
+	 */
+	int net_phone;
+	/** IP module phone.
+	 */
+	int ip_phone;
+	/** ICMP module phone.
+	 */
+	int icmp_phone;
+	/** Packet dimension.
+	 */
+	packet_dimension_t packet_dimension;
+	/** Indicates whether UDP checksum computing is enabled.
+	 */
+	int checksum_computing;
+	/** Indicates whether UDP autobnding on send is enabled.
+	 */
+	int autobinding;
+	/** Last used free port.
+	 */
+	int last_used_port;
+	/** Active sockets.
+	 */
+	socket_ports_t sockets;
+	/** Device packet dimensions.
+	 */
+	packet_dimensions_t dimensions;
+	/** Safety lock.
+	 */
+	fibril_rwlock_t lock;
+};
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/tl/udp/udp_header.h
===================================================================
--- uspace/srv/net/tl/udp/udp_header.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/udp/udp_header.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,83 @@
+/*
+ * 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 udp
+ *  @{
+ */
+
+/** @file
+ *  UDP header definition.
+ *  Based on the RFC~768.
+ */
+
+#ifndef __NET_UDP_HEADER_H__
+#define __NET_UDP_HEADER_H__
+
+#include <sys/types.h>
+
+/** UDP header size in bytes.
+ */
+#define UDP_HEADER_SIZE			sizeof(udp_header_t)
+
+/** Type definition of the user datagram header.
+ *  @see udp_header
+ */
+typedef struct udp_header	udp_header_t;
+
+/** Type definition of the user datagram header pointer.
+ *  @see udp_header
+ */
+typedef udp_header_t *		udp_header_ref;
+
+/** User datagram header.
+ */
+struct udp_header{
+	/** Source Port is an optional field, when meaningful, it indicates the port of the sending process, and may be assumed to be the port to which a reply should be addressed in the absence of any other information.
+	 *  If not used, a value of zero is inserted.
+	 */
+	uint16_t source_port;
+	/** Destination port has a meaning within the context of a particular internet destination address.
+	 */
+	uint16_t destination_port;
+	/** Length is the length in octets of this user datagram including this header and the data.
+	 *  This means the minimum value of the length is eight.
+	 */
+	uint16_t total_length;
+	/** Checksum is the 16-bit one's complement of the one's complement sum of a pseudo header of information from the IP header, the UDP header, and the data, padded with zero octets at the end (if necessary) to make a multiple of two octets.
+	 *  The pseudo header conceptually prefixed to the UDP header contains the source address, the destination address, the protocol, and the UDP length.
+	 *  This information gives protection against misrouted datagrams.
+	 *  If the computed checksum is zero, it is transmitted as all ones (the equivalent in one's complement arithmetic).
+	 *  An all zero transmitted checksum value means that the transmitter generated no checksum (for debugging or for higher level protocols that don't care).
+	 */
+	uint16_t checksum;
+} __attribute__ ((packed));
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/udp/udp_module.c
===================================================================
--- uspace/srv/net/tl/udp/udp_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/udp/udp_module.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,101 @@
+/*
+ * 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 <async.h>
+#include <stdio.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <net_err.h>
+#include <net_modules.h>
+#include <packet/packet.h>
+#include <net_interface.h>
+#include <tl_local.h>
+
+#include "udp.h"
+#include "udp_module.h"
+
+/** UDP module global data.
+ */
+extern udp_globals_t	udp_globals;
+
+/** Starts the UDP 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.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the udp_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int tl_module_start_standalone(async_client_conn_t client_connection){
+	ERROR_DECLARE;
+
+	ipcarg_t phonehash;
+
+	async_set_client_connection(client_connection);
+	udp_globals.net_phone = net_connect_module(SERVICE_NETWORKING);
+	if(udp_globals.net_phone < 0){
+		return udp_globals.net_phone;
+	}
+	ERROR_PROPAGATE(pm_init());
+	if(ERROR_OCCURRED(udp_initialize(client_connection))
+		|| ERROR_OCCURRED(REGISTER_ME(SERVICE_UDP, &phonehash))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+/** Processes the UDP 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the udp_message() function.
+ */
+int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+	return udp_message_standalone(callid, call, answer, answer_count);
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/udp/udp_module.h
===================================================================
--- uspace/srv/net/tl/udp/udp_module.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
+++ uspace/srv/net/tl/udp/udp_module.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -0,0 +1,66 @@
+/*
+ * 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>
+
+/** Initializes the UDP module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+extern int udp_initialize(async_client_conn_t client_connection);
+
+/** Processes the UDP 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see udp_interface.h
+ *  @see IS_NET_UDP_MESSAGE()
+ */
+extern int udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/ns/Makefile
===================================================================
--- uspace/srv/ns/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/ns/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,7 +29,5 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = ns
+BINARY = ns
 
 SOURCES = \
@@ -39,3 +37,3 @@
 	task.c
 
-include ../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/ns/ns.c
===================================================================
--- uspace/srv/ns/ns.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/ns/ns.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -55,8 +55,8 @@
 static void *klogaddr = NULL;
 
-static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr,
+static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *faddr,
     size_t pages, void **addr)
 {
-	if (ph_addr == NULL) {
+	if ((faddr == NULL) || (pages == 0)) {
 		ipc_answer_0(callid, ENOENT);
 		return;
@@ -71,5 +71,5 @@
 		}
 		
-		if (physmem_map(ph_addr, *addr, pages,
+		if (physmem_map(faddr, *addr, pages,
 		    AS_AREA_READ | AS_AREA_CACHEABLE) != 0) {
 			ipc_answer_0(callid, ENOENT);
@@ -81,4 +81,32 @@
 }
 
+static void setup_clock_area(ipc_callid_t callid, ipc_call_t *call, void **addr)
+{
+	uintptr_t faddr;
+	int err = sysinfo_get_value("clock.faddr", &faddr);
+	
+	if (err != EOK)
+		ipc_answer_0(callid, err);
+	
+	get_as_area(callid, call, (void *) faddr, 1, addr);
+}
+
+static void setup_klog_area(ipc_callid_t callid, ipc_call_t *call, void **addr)
+{
+	uintptr_t faddr;
+	int err = sysinfo_get_value("klog.faddr", &faddr);
+	
+	if (err != EOK)
+		ipc_answer_0(callid, err);
+	
+	size_t pages;
+	err = sysinfo_get_value("klog.pages", &pages);
+	
+	if (err != EOK)
+		ipc_answer_0(callid, err);
+	
+	get_as_area(callid, call, (void *) faddr, pages, addr);
+}
+
 int main(int argc, char **argv)
 {
@@ -97,5 +125,5 @@
 		return rc;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
 	
 	while (true) {
@@ -113,12 +141,8 @@
 			switch (IPC_GET_ARG3(call)) {
 			case SERVICE_MEM_REALTIME:
-				get_as_area(callid, &call,
-				    (void *) sysinfo_value("clock.faddr"),
-				    1, &clockaddr);
+				setup_clock_area(callid, &call, &clockaddr);
 				break;
 			case SERVICE_MEM_KLOG:
-				get_as_area(callid, &call,
-				    (void *) sysinfo_value("klog.faddr"),
-				    sysinfo_value("klog.pages"), &klogaddr);
+				setup_klog_area(callid, &call, &klogaddr);
 				break;
 			default:
Index: uspace/srv/taskmon/Makefile
===================================================================
--- uspace/srv/taskmon/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/taskmon/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -28,10 +28,8 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = taskmon
+BINARY = taskmon
 
 SOURCES = \
 	taskmon.c
 
-include ../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/taskmon/taskmon.c
===================================================================
--- uspace/srv/taskmon/taskmon.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/taskmon/taskmon.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -44,4 +44,5 @@
 #include <macros.h>
 #include <errno.h>
+#include <str_error.h>
 
 #define NAME  "taskmon"
@@ -49,9 +50,9 @@
 static void fault_event(ipc_callid_t callid, ipc_call_t *call)
 {
-	char *argv[11];
-	char *fname;
+	const char *argv[6];
+	const char *fname;
 	char *dump_fname;
 	char *s_taskid;
-	char **s;
+	const char **s;
 
 	task_id_t taskid;
@@ -66,5 +67,5 @@
 	}
 
-	if (asprintf(&dump_fname, "/scratch/d" PRIuTASKID ".txt", taskid) < 0) {
+	if (asprintf(&dump_fname, "/data/core%" PRIuTASKID, taskid) < 0) {
 		printf("Memory allocation failed.\n");
 		return;
@@ -73,16 +74,11 @@
 	printf(NAME ": Task %" PRIuTASKID " fault in thread %p.\n", taskid, thread);
 
-#ifdef CONFIG_VERBOSE_DUMPS
-	argv[0] = "/app/redir";
-	argv[1] = "-i";
-	argv[2] = "/readme";
-	argv[3] = "-o";
-	argv[4] = dump_fname;
-	argv[5] = "--";
-	argv[6] = "/app/taskdump";
-	argv[7] = "-m";
-	argv[8] = "-t";
-	argv[9] = s_taskid;
-	argv[10] = NULL;
+#ifdef CONFIG_WRITE_CORE_FILES
+	argv[0] = "/app/taskdump";
+	argv[1] = "-c";
+	argv[2] = dump_fname;
+	argv[3] = "-t";
+	argv[4] = s_taskid;
+	argv[5] = NULL;
 #else
 	argv[0] = "/app/taskdump";
@@ -94,5 +90,6 @@
 
 	printf(NAME ": Executing");
-        s = argv;
+	
+	s = argv;
 	while (*s != NULL) {
 		printf(" %s", *s);
@@ -100,7 +97,9 @@
 	}
 	putchar('\n');
-
-	if (!task_spawn(fname, argv))
-		printf(NAME ": Error spawning taskdump.\n", fname);
+	
+	int err;
+	if (!task_spawn(fname, argv, &err))
+		printf("%s: Error spawning %s (%s).\n", NAME, fname,
+		    str_error(err));
 }
 
Index: uspace/srv/vfs/Makefile
===================================================================
--- uspace/srv/vfs/Makefile	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/vfs/Makefile	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -29,7 +29,5 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBC_PREFIX)/libc.a
-
-OUTPUT = vfs
+BINARY = vfs
 
 SOURCES = \
@@ -41,3 +39,3 @@
 	vfs_register.c
 
-include ../Makefile.common
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/vfs/vfs.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -42,5 +42,5 @@
 #include <stdio.h>
 #include <bool.h>
-#include <string.h>
+#include <str.h>
 #include <as.h>
 #include <atomic.h>
@@ -72,7 +72,4 @@
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
-		
-		fs_handle_t fs_handle;
-		int phone;
 		
 		switch (IPC_GET_METHOD(call)) {
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/vfs/vfs.h	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -42,8 +42,7 @@
 #include <ipc/vfs.h>
 
-// FIXME: according to CONFIG_DEBUG
-// #define dprintf(...)  printf(__VA_ARGS__)
-
-#define dprintf(...)
+#ifndef dprintf
+	#define dprintf(...)
+#endif
 
 /**
@@ -93,6 +92,6 @@
 	vfs_triplet_t triplet;
 	vfs_node_type_t type;
-	size_t size;
-	unsigned lnkcnt;
+	aoff64_t size;
+	unsigned int lnkcnt;
 } vfs_lookup_res_t;
 
@@ -117,5 +116,5 @@
 	vfs_node_type_t type;	/**< Partial info about the node type. */
 
-	size_t size;		/**< Cached size if the node is a file. */
+	aoff64_t size;		/**< Cached size if the node is a file. */
 
 	/**
@@ -141,6 +140,6 @@
 	bool append;
 
-	/** Current position in the file. */
-	off_t pos;
+	/** Current absolute position in the file. */
+	aoff64_t pos;
 } vfs_file_t;
 
@@ -214,5 +213,4 @@
 extern void vfs_truncate(ipc_callid_t, ipc_call_t *);
 extern void vfs_fstat(ipc_callid_t, ipc_call_t *);
-extern void vfs_fstat(ipc_callid_t, ipc_call_t *);
 extern void vfs_stat(ipc_callid_t, ipc_call_t *);
 extern void vfs_mkdir(ipc_callid_t, ipc_call_t *);
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/vfs/vfs_file.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -38,5 +38,5 @@
 #include <errno.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <assert.h>
 #include <bool.h>
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/vfs/vfs_lookup.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -38,7 +38,8 @@
 #include "vfs.h"
 #include <ipc/ipc.h>
+#include <macros.h>
 #include <async.h>
 #include <errno.h>
-#include <string.h>
+#include <str.h>
 #include <stdarg.h>
 #include <bool.h>
@@ -99,6 +100,6 @@
 	entry.len = len;
 
-	off_t first;	/* the first free index */
-	off_t last;	/* the last free index */
+	size_t first;	/* the first free index */
+	size_t last;	/* the last free index */
 
 	if (list_empty(&plb_head)) {
@@ -177,20 +178,23 @@
 	memset(plb, 0, cnt2);
 	fibril_mutex_unlock(&plb_mutex);
-
-	if ((rc == EOK) && (result)) {
-		result->triplet.fs_handle = (fs_handle_t) IPC_GET_ARG1(answer);
-		result->triplet.dev_handle = (dev_handle_t) IPC_GET_ARG2(answer);
-		result->triplet.index = (fs_index_t) IPC_GET_ARG3(answer);
-		result->size = (size_t) IPC_GET_ARG4(answer);
-		result->lnkcnt = (unsigned) IPC_GET_ARG5(answer);
-		if (lflag & L_FILE)
-			result->type = VFS_NODE_FILE;
-		else if (lflag & L_DIRECTORY)
-			result->type = VFS_NODE_DIRECTORY;
-		else
-			result->type = VFS_NODE_UNKNOWN;
-	}
-
-	return rc;
+	
+	if (((int) rc < EOK) || (!result))
+		return (int) rc;
+	
+	result->triplet.fs_handle = (fs_handle_t) rc;
+	result->triplet.dev_handle = (dev_handle_t) IPC_GET_ARG1(answer);
+	result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer);
+	result->size =
+	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(answer), IPC_GET_ARG4(answer));
+	result->lnkcnt = (unsigned int) IPC_GET_ARG5(answer);
+	
+	if (lflag & L_FILE)
+		result->type = VFS_NODE_FILE;
+	else if (lflag & L_DIRECTORY)
+		result->type = VFS_NODE_DIRECTORY;
+	else
+		result->type = VFS_NODE_UNKNOWN;
+	
+	return EOK;
 }
 
@@ -214,9 +218,10 @@
 	
 	if (rc == EOK) {
-		result->size = (size_t) IPC_GET_ARG1(answer);
-		result->lnkcnt = (unsigned) IPC_GET_ARG2(answer);
-		if (IPC_GET_ARG3(answer) & L_FILE)
+		result->size =
+		    MERGE_LOUP32(IPC_GET_ARG1(answer), IPC_GET_ARG2(answer));
+		result->lnkcnt = (unsigned int) IPC_GET_ARG3(answer);
+		if (IPC_GET_ARG4(answer) & L_FILE)
 			result->type = VFS_NODE_FILE;
-		else if (IPC_GET_ARG3(answer) & L_DIRECTORY)
+		else if (IPC_GET_ARG4(answer) & L_DIRECTORY)
 			result->type = VFS_NODE_DIRECTORY;
 		else
Index: uspace/srv/vfs/vfs_node.c
===================================================================
--- uspace/srv/vfs/vfs_node.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/vfs/vfs_node.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -38,5 +38,5 @@
 #include "vfs.h"
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <fibril_synch.h>
 #include <adt/hash_table.h>
@@ -242,5 +242,5 @@
 {
 	vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link);
-	return (node->fs_handle == key[KEY_FS_HANDLE]) &&
+	return (node->fs_handle == (fs_handle_t) key[KEY_FS_HANDLE]) &&
 	    (node->dev_handle == key[KEY_DEV_HANDLE]) &&
 	    (node->index == key[KEY_INDEX]);
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/vfs/vfs_ops.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -38,9 +38,11 @@
 #include "vfs.h"
 #include <ipc/ipc.h>
+#include <macros.h>
+#include <limits.h>
 #include <async.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <bool.h>
 #include <fibril_synch.h>
@@ -53,5 +55,5 @@
 
 /* Forward declarations of static functions. */
-static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t);
+static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, aoff64_t);
 
 /**
@@ -267,5 +269,6 @@
 	/* We want the client to send us the mount point. */
 	char *mp;
-	int rc = async_string_receive(&mp, MAX_PATH_LEN, NULL);
+	int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
+	    0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(rid, rc);
@@ -275,5 +278,6 @@
 	/* Now we expect to receive the mount options. */
 	char *opts;
-	rc = async_string_receive(&opts, MAX_MNTOPTS_LEN, NULL);
+	rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
+	    0, NULL);
 	if (rc != EOK) {
 		free(mp);
@@ -287,5 +291,6 @@
 	 */
 	char *fs_name;
-	rc = async_string_receive(&fs_name, FS_NAME_MAXLEN, NULL);
+	rc = async_data_write_accept((void **) &fs_name, true, 0, FS_NAME_MAXLEN,
+	    0, NULL);
 	if (rc != EOK) {
 		free(mp);
@@ -350,5 +355,4 @@
 	vfs_lookup_res_t mp_res;
 	vfs_lookup_res_t mr_res;
-	vfs_node_t *mp_node;
 	vfs_node_t *mr_node;
 	int phone;
@@ -357,5 +361,6 @@
 	 * Receive the mount point path.
 	 */
-	rc = async_string_receive(&mp, MAX_PATH_LEN, NULL);
+	rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
+	    0, NULL);
 	if (rc != EOK)
 		ipc_answer_0(rid, rc);
@@ -499,5 +504,4 @@
 	int oflag = IPC_GET_ARG2(*request);
 	int mode = IPC_GET_ARG3(*request);
-	size_t len;
 
 	/* Ignore mode for now. */
@@ -522,5 +526,5 @@
 	
 	char *path;
-	int rc = async_string_receive(&path, 0, NULL);
+	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(rid, rc);
@@ -836,5 +840,5 @@
 		    &answer);
 	} else {
-		rc = async_data_forward_3_1(fs_phone, VFS_OUT_WRITE,
+		rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE,
 		    file->node->dev_handle, file->node->index, file->pos,
 		    &answer);
@@ -883,8 +887,8 @@
 {
 	int fd = (int) IPC_GET_ARG1(*request);
-	off_t off = (off_t) IPC_GET_ARG2(*request);
-	int whence = (int) IPC_GET_ARG3(*request);
-
-
+	off64_t off =
+	    (off64_t) MERGE_LOUP32(IPC_GET_ARG2(*request), IPC_GET_ARG3(*request));
+	int whence = (int) IPC_GET_ARG4(*request);
+	
 	/* Lookup the file structure corresponding to the file descriptor. */
 	vfs_file_t *file = vfs_file_get(fd);
@@ -893,47 +897,69 @@
 		return;
 	}
-
-	off_t newpos;
+	
 	fibril_mutex_lock(&file->lock);
-	if (whence == SEEK_SET) {
-		file->pos = off;
-		fibril_mutex_unlock(&file->lock);
-		ipc_answer_1(rid, EOK, off);
-		return;
-	}
-	if (whence == SEEK_CUR) {
-		if (file->pos + off < file->pos) {
+	
+	off64_t newoff;
+	switch (whence) {
+		case SEEK_SET:
+			if (off >= 0) {
+				file->pos = (aoff64_t) off;
+				fibril_mutex_unlock(&file->lock);
+				ipc_answer_1(rid, EOK, off);
+				return;
+			}
+			break;
+		case SEEK_CUR:
+			if ((off >= 0) && (file->pos + off < file->pos)) {
+				fibril_mutex_unlock(&file->lock);
+				ipc_answer_0(rid, EOVERFLOW);
+				return;
+			}
+			
+			if ((off < 0) && (file->pos < (aoff64_t) -off)) {
+				fibril_mutex_unlock(&file->lock);
+				ipc_answer_0(rid, EOVERFLOW);
+				return;
+			}
+			
+			file->pos += off;
+			newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos;
+			
 			fibril_mutex_unlock(&file->lock);
-			ipc_answer_0(rid, EOVERFLOW);
+			ipc_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff));
 			return;
-		}
-		file->pos += off;
-		newpos = file->pos;
-		fibril_mutex_unlock(&file->lock);
-		ipc_answer_1(rid, EOK, newpos);
-		return;
-	}
-	if (whence == SEEK_END) {
-		fibril_rwlock_read_lock(&file->node->contents_rwlock);
-		size_t size = file->node->size;
-		fibril_rwlock_read_unlock(&file->node->contents_rwlock);
-		if (size + off < size) {
+		case SEEK_END:
+			fibril_rwlock_read_lock(&file->node->contents_rwlock);
+			aoff64_t size = file->node->size;
+			
+			if ((off >= 0) && (size + off < size)) {
+				fibril_rwlock_read_unlock(&file->node->contents_rwlock);
+				fibril_mutex_unlock(&file->lock);
+				ipc_answer_0(rid, EOVERFLOW);
+				return;
+			}
+			
+			if ((off < 0) && (size < (aoff64_t) -off)) {
+				fibril_rwlock_read_unlock(&file->node->contents_rwlock);
+				fibril_mutex_unlock(&file->lock);
+				ipc_answer_0(rid, EOVERFLOW);
+				return;
+			}
+			
+			file->pos = size + off;
+			newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos;
+			
+			fibril_rwlock_read_unlock(&file->node->contents_rwlock);
 			fibril_mutex_unlock(&file->lock);
-			ipc_answer_0(rid, EOVERFLOW);
+			ipc_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff));
 			return;
-		}
-		newpos = size + off;
-		file->pos = newpos;
-		fibril_mutex_unlock(&file->lock);
-		ipc_answer_1(rid, EOK, newpos);
-		return;
-	}
+	}
+	
 	fibril_mutex_unlock(&file->lock);
 	ipc_answer_0(rid, EINVAL);
 }
 
-int
-vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle,
-    fs_index_t index, size_t size)
+int vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle,
+    fs_index_t index, aoff64_t size)
 {
 	ipcarg_t rc;
@@ -941,6 +967,6 @@
 	
 	fs_phone = vfs_grab_phone(fs_handle);
-	rc = async_req_3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle,
-	    (ipcarg_t)index, (ipcarg_t)size);
+	rc = async_req_4_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t) dev_handle,
+	    (ipcarg_t) index, LOWER32(size), UPPER32(size));
 	vfs_release_phone(fs_phone);
 	return (int)rc;
@@ -950,5 +976,6 @@
 {
 	int fd = IPC_GET_ARG1(*request);
-	size_t size = IPC_GET_ARG2(*request);
+	aoff64_t size =
+	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(*request), IPC_GET_ARG3(*request));
 	int rc;
 
@@ -1007,5 +1034,5 @@
 {
 	char *path;
-	int rc = async_string_receive(&path, 0, NULL);
+	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(rid, rc);
@@ -1061,5 +1088,5 @@
 	
 	char *path;
-	int rc = async_string_receive(&path, 0, NULL);
+	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(rid, rc);
@@ -1083,5 +1110,5 @@
 	
 	char *path;
-	int rc = async_string_receive(&path, 0, NULL);
+	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(rid, rc);
@@ -1118,5 +1145,5 @@
 	/* Retrieve the old path. */
 	char *old;
-	int rc = async_string_receive(&old, 0, NULL);
+	int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(rid, rc);
@@ -1126,5 +1153,5 @@
 	/* Retrieve the new path. */
 	char *new;
-	rc = async_string_receive(&new, 0, NULL);
+	rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL);
 	if (rc != EOK) {
 		free(old);
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision cf8cc3692ffb17058d5881b6bfdde3a4a5d050fd)
+++ uspace/srv/vfs/vfs_register.c	(revision c47e1a8fb8e2a2556518fd57f186595422ca4484)
@@ -43,5 +43,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
+#include <str.h>
 #include <ctype.h>
 #include <bool.h>
@@ -114,6 +114,6 @@
 	
 	vfs_info_t *vfs_info;
-	int rc = async_data_receive(&vfs_info, sizeof(vfs_info_t),
-	    sizeof(vfs_info_t), 0, NULL);
+	int rc = async_data_write_accept((void **) &vfs_info, false,
+	    sizeof(vfs_info_t), sizeof(vfs_info_t), 0, NULL);
 	
 	if (rc != EOK) {
