Index: .bzrignore
===================================================================
--- .bzrignore	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ .bzrignore	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -44,4 +44,6 @@
 ./uspace/app/getterm/getterm
 ./uspace/app/init/init
+./uspace/app/kill/kill
+./uspace/app/killall/killall
 ./uspace/app/klog/klog
 ./uspace/app/mkfat/mkfat
@@ -65,4 +67,5 @@
 ./uspace/app/usbinfo/usbinfo
 ./uspace/app/virtusbkbd/vuk
+./uspace/app/websrv/websrv
 ./uspace/dist/app/*
 ./uspace/dist/cfg/net/general
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ boot/Makefile.common	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -101,4 +101,6 @@
 	$(USPACE_PATH)/srv/hw/bus/usb/hcd/virtual/vhcd \
 	$(USPACE_PATH)/srv/net/netif/lo/lo \
+	$(USPACE_PATH)/srv/net/nil/eth/eth \
+	$(USPACE_PATH)/srv/net/nil/nildummy/nildummy \
 	$(USPACE_PATH)/srv/net/il/arp/arp \
 	$(USPACE_PATH)/srv/net/il/ip/ip \
@@ -117,10 +119,4 @@
 RD_DRV_CFG = 
 
-ifneq ($(CONFIG_NETIF_NIL_BUNDLE),y)
-	RD_SRVS_NON_ESSENTIAL += \
-		$(USPACE_PATH)/srv/net/nil/eth/eth \
-		$(USPACE_PATH)/srv/net/nil/nildummy/nildummy
-endif
-
 RD_APPS_ESSENTIAL = \
 	$(USPACE_PATH)/app/bdsh/bdsh \
@@ -130,4 +126,6 @@
 RD_APPS_NON_ESSENTIAL = \
 	$(USPACE_PATH)/app/edit/edit \
+	$(USPACE_PATH)/app/kill/kill \
+	$(USPACE_PATH)/app/killall/killall \
 	$(USPACE_PATH)/app/mkfat/mkfat \
 	$(USPACE_PATH)/app/sbi/sbi \
@@ -148,5 +146,6 @@
 	$(USPACE_PATH)/app/top/top \
 	$(USPACE_PATH)/app/usbinfo/usbinfo \
-	$(USPACE_PATH)/app/virtusbkbd/vuk
+	$(USPACE_PATH)/app/virtusbkbd/vuk \
+	$(USPACE_PATH)/app/websrv/websrv
 
 ifneq ($(CONFIG_BAREBONE),y)
Index: boot/arch/ia64/Makefile.inc
===================================================================
--- boot/arch/ia64/Makefile.inc	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ boot/arch/ia64/Makefile.inc	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -34,5 +34,5 @@
 ENDIANESS = LE
 PAGE_SIZE = 16384
-EXTRA_CFLAGS = -fno-unwind-tables -mfixed-range=f32-f127 -mno-pic
+EXTRA_CFLAGS = -fno-unwind-tables -mfixed-range=f32-f127 -mno-pic -mno-sdata
 
 RD_SRVS_NON_ESSENTIAL +=
Index: contrib/conf/net-qe.sh
===================================================================
--- contrib/conf/net-qe.sh	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ contrib/conf/net-qe.sh	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -1,9 +1,12 @@
 #!/bin/sh
 
-arguments="-vga std -M isapc -net nic,model=ne2k_isa -net user -boot d -redir udp:8080::8080 -redir udp:8081::8081 -redir tcp:8080::8080 -redir tcp:8081::8081 -cdrom image.iso"
+# Obsolete versions of QEMU
+#
+#   QEMU 0.10.2 and later 0.10.*
+#    qemu $@ -no-kqemu -vga std -M isapc -net nic,model=ne2k_isa -net user -boot d -redir udp:8080::8080 -redir udp:8081::8081 -redir tcp:8080::8080 -redir tcp:8081::8081 -cdrom image.iso
+#
+#   QEMU 0.11.* and 0.12.*
+#    qemu $@ -vga std -M isapc -net nic,model=ne2k_isa -net user -boot d -redir udp:8080::8080 -redir udp:8081::8081 -redir tcp:8080::8080 -redir tcp:8081::8081 -cdrom image.iso
 
-#qemu 0.10.2 and later 0.10.*:
-#qemu $@ -no-kqemu $arguments
-
-#qemu 0.11:
-qemu $@ $arguments
+# QEMU 0.13 and later
+qemu $@ -device ne2k_isa,irq=5,vlan=0 -net user -boot d -redir udp:8080::8080 -redir udp:8081::8081 -redir tcp:8080::8080 -redir tcp:8081::8081 -cdrom image.iso
Index: defaults/amd64/Makefile.config
===================================================================
--- defaults/amd64/Makefile.config	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ defaults/amd64/Makefile.config	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -65,4 +65,2 @@
 CONFIG_MOUNT_DATA = n
 
-# Bundle netif/nil network layer
-CONFIG_NETIF_NIL_BUNDLE = n
Index: defaults/arm32/Makefile.config
===================================================================
--- defaults/arm32/Makefile.config	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ defaults/arm32/Makefile.config	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -41,4 +41,2 @@
 CONFIG_MOUNT_DATA = n
 
-# Bundle netif/nil network layer
-CONFIG_NETIF_NIL_BUNDLE = n
Index: defaults/ia32/Makefile.config
===================================================================
--- defaults/ia32/Makefile.config	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ defaults/ia32/Makefile.config	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -71,4 +71,2 @@
 CONFIG_MOUNT_DATA = n
 
-# Bundle netif/nil network layer
-CONFIG_NETIF_NIL_BUNDLE = n
Index: defaults/ia64/Makefile.config
===================================================================
--- defaults/ia64/Makefile.config	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ defaults/ia64/Makefile.config	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -53,4 +53,2 @@
 CONFIG_MOUNT_DATA = n
 
-# Bundle netif/nil network layer
-CONFIG_NETIF_NIL_BUNDLE = n
Index: defaults/mips32/Makefile.config
===================================================================
--- defaults/mips32/Makefile.config	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ defaults/mips32/Makefile.config	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -47,4 +47,2 @@
 CONFIG_MOUNT_DATA = n
 
-# Bundle netif/nil network layer
-CONFIG_NETIF_NIL_BUNDLE = n
Index: defaults/ppc32/Makefile.config
===================================================================
--- defaults/ppc32/Makefile.config	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ defaults/ppc32/Makefile.config	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -47,4 +47,2 @@
 CONFIG_MOUNT_DATA = n
 
-# Bundle netif/nil network layer
-CONFIG_NETIF_NIL_BUNDLE = n
Index: defaults/sparc64/Makefile.config
===================================================================
--- defaults/sparc64/Makefile.config	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ defaults/sparc64/Makefile.config	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -62,4 +62,2 @@
 CONFIG_MOUNT_DATA = n
 
-# Bundle netif/nil network layer
-CONFIG_NETIF_NIL_BUNDLE = n
Index: defaults/special/Makefile.config
===================================================================
--- defaults/special/Makefile.config	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ defaults/special/Makefile.config	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -32,4 +32,2 @@
 CONFIG_START_BD = n
 
-# Bundle netif/nil network layer
-CONFIG_NETIF_NIL_BUNDLE = n
Index: kernel/arch/ia32/include/interrupt.h
===================================================================
--- kernel/arch/ia32/include/interrupt.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ kernel/arch/ia32/include/interrupt.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -55,5 +55,5 @@
 #define IRQ_PIC_SPUR  7
 #define IRQ_MOUSE     12
-#define IRQ_DP8390    9
+#define IRQ_DP8390    5
 
 /* This one must have four least significant bits set to ones */
Index: kernel/generic/include/ddi/irq.h
===================================================================
--- kernel/generic/include/ddi/irq.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ kernel/generic/include/ddi/irq.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -54,4 +54,5 @@
 	/** Read 4 bytes from the I/O space. */
 	CMD_PIO_READ_32,
+	
 	/** Write 1 byte to the I/O space. */
 	CMD_PIO_WRITE_8,
@@ -62,12 +63,29 @@
 	
 	/**
-	 * Perform a bit test on the source argument and store the result into
-	 * the destination argument.
+	 * Write 1 byte from the source argument
+	 * to the I/O space.
+	 */
+	CMD_PIO_WRITE_A_8,
+	/**
+	 * Write 2 bytes from the source argument
+	 * to the I/O space.
+	 */
+	CMD_PIO_WRITE_A_16,
+	/**
+	 * Write 4 bytes from the source argument
+	 * to the I/O space.
+	 */
+	CMD_PIO_WRITE_A_32,
+	
+	/**
+	 * Perform a bit masking on the source argument
+	 * and store the result into the destination argument.
 	 */
 	CMD_BTEST,
 	
 	/**
-	 * Predicate the execution of the following N commands by the boolean
-	 * value of the source argument.
+	 * Predicate the execution of the following
+	 * N commands by the boolean value of the source
+	 * argument.
 	 */
 	CMD_PREDICATE,
@@ -75,4 +93,5 @@
 	/** Accept the interrupt. */
 	CMD_ACCEPT,
+	
 	/** Decline the interrupt. */
 	CMD_DECLINE,
Index: kernel/generic/include/interrupt.h
===================================================================
--- kernel/generic/include/interrupt.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ kernel/generic/include/interrupt.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -60,4 +60,5 @@
 extern void fault_if_from_uspace(istate_t *, const char *, ...)
     PRINTF_ATTRIBUTE(2, 3);
+extern istate_t *istate_get(thread_t *);
 extern iroutine_t exc_register(unsigned int, const char *, bool, iroutine_t);
 extern void exc_dispatch(unsigned int, istate_t *);
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ kernel/generic/include/proc/task.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -154,4 +154,5 @@
 
 extern sysarg_t sys_task_set_name(const char *, size_t);
+extern sysarg_t sys_task_kill(task_id_t *);
 
 #endif
Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ kernel/generic/include/syscall/syscall.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -47,4 +47,5 @@
 	SYS_TASK_GET_ID,
 	SYS_TASK_SET_NAME,
+	SYS_TASK_KILL,
 	SYS_PROGRAM_SPAWN_LOADER,
 	
Index: kernel/generic/src/interrupt/interrupt.c
===================================================================
--- kernel/generic/src/interrupt/interrupt.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ kernel/generic/src/interrupt/interrupt.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -209,4 +209,23 @@
 }
 
+/** Get istate structure of a thread.
+ *
+ * Get pointer to the istate structure at the bottom of the kernel stack.
+ *
+ * This function can be called in interrupt or user context. In interrupt
+ * context the istate structure is created by the low-level exception
+ * handler. In user context the istate structure is created by the
+ * low-level syscall handler.
+ */
+istate_t *istate_get(thread_t *thread)
+{
+	/*
+	 * The istate structure should be right at the bottom of the kernel
+	 * stack.
+	 */
+	return (istate_t *) ((uint8_t *) thread->kstack + THREAD_STACK_SIZE -
+	    sizeof(istate_t));
+}
+
 #ifdef CONFIG_KCONSOLE
 
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ kernel/generic/src/ipc/irq.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -404,4 +404,22 @@
 			    (uint32_t) code->cmds[i].value);
 			break;
+		case CMD_PIO_WRITE_A_8:
+			if (srcarg) {
+				pio_write_8((ioport8_t *) code->cmds[i].addr,
+				    (uint8_t) scratch[srcarg]);
+			}
+			break;
+		case CMD_PIO_WRITE_A_16:
+			if (srcarg) {
+				pio_write_16((ioport16_t *) code->cmds[i].addr,
+				    (uint16_t) scratch[srcarg]);
+			}
+			break;
+		case CMD_PIO_WRITE_A_32:
+			if (srcarg) {
+				pio_write_32((ioport32_t *) code->cmds[i].addr,
+				    (uint32_t) scratch[srcarg]);
+			}
+			break;
 		case CMD_BTEST:
 			if ((srcarg) && (dstarg)) {
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ kernel/generic/src/main/main.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -185,6 +185,6 @@
 	LOG("\nconfig.base=%p config.kernel_size=%zu"
 	    "\nconfig.stack_base=%p config.stack_size=%zu",
-	    config.base, config.kernel_size, config.stack_base,
-	    config.stack_size);
+	    (void *) config.base, config.kernel_size,
+	    (void *) config.stack_base, config.stack_size);
 	
 #ifdef CONFIG_KCONSOLE
@@ -242,5 +242,5 @@
 		for (i = 0; i < init.cnt; i++)
 			LOG("init[%zu].addr=%p, init[%zu].size=%zu",
-			    i, init.tasks[i].addr, i, init.tasks[i].size);
+			    i, (void *) init.tasks[i].addr, i, init.tasks[i].size);
 	} else
 		printf("No init binaries found.\n");
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ kernel/generic/src/proc/task.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -360,4 +360,23 @@
 }
 
+/** Syscall to forcefully terminate a task
+ *
+ * @param uspace_taskid Pointer to task ID in user space.
+ *
+ * @return 0 on success or an error code from @ref errno.h.
+ *
+ */
+sysarg_t sys_task_kill(task_id_t *uspace_taskid)
+{
+	task_id_t taskid;
+	int rc;
+
+	rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(taskid));
+	if (rc != 0)
+		return (sysarg_t) rc;
+
+	return (sysarg_t) task_kill(taskid);
+}
+
 /** Find task structure corresponding to task ID.
  *
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ kernel/generic/src/syscall/syscall.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -45,4 +45,5 @@
 #include <debug.h>
 #include <ddi/device.h>
+#include <interrupt.h>
 #include <ipc/sysipc.h>
 #include <synch/futex.h>
@@ -66,7 +67,13 @@
 #ifdef CONFIG_UDEBUG
 	/*
+	 * An istate_t-compatible record was created on the stack by the
+	 * low-level syscall handler. This is the userspace space state
+	 * structure.
+	 */
+	THREAD->udebug.uspace_state = istate_get(THREAD);
+
+	/*
 	 * Early check for undebugged tasks. We do not lock anything as this
 	 * test need not be precise in either direction.
-	 *
 	 */
 	if (THREAD->udebug.active)
@@ -98,4 +105,7 @@
 		udebug_stoppable_end();
 	}
+
+	/* Clear userspace state pointer */
+	THREAD->udebug.uspace_state = NULL;
 #endif
 	
@@ -120,4 +130,5 @@
 	(syshandler_t) sys_task_get_id,
 	(syshandler_t) sys_task_set_name,
+	(syshandler_t) sys_task_kill,
 	(syshandler_t) sys_program_spawn_loader,
 	
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -38,4 +38,6 @@
 	app/getterm \
 	app/init \
+	app/kill \
+	app/killall \
 	app/klog \
 	app/mkfat \
@@ -55,4 +57,5 @@
 	app/nettest2 \
 	app/ping \
+	app/websrv \
 	app/sysinfo \
 	srv/clip \
@@ -80,5 +83,4 @@
 	srv/hw/char/s3c24xx_uart \
 	srv/hw/netif/dp8390 \
-	srv/net/cfg \
 	srv/net/netif/lo \
 	srv/net/il/arp \
@@ -96,13 +98,7 @@
 #
 
-ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
-	LIBN = \
-		srv/net/nil/eth \
-		srv/net/nil/nildummy
-else
-	DIRS += \
-		srv/net/nil/eth \
-		srv/net/nil/nildummy
-endif
+DIRS += \
+	srv/net/nil/eth \
+	srv/net/nil/nildummy
 
 ## Platform-specific hardware support
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/app/init/init.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -61,5 +61,5 @@
 
 #define DATA_FS_TYPE      "fat"
-#define DATA_DEVICE       "bd/disk0"
+#define DATA_DEVICE       "bd/ata1disk0"
 #define DATA_MOUNT_POINT  "/data"
 
Index: uspace/app/kill/Makefile
===================================================================
--- uspace/app/kill/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/app/kill/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 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.
+#
+
+USPACE_PREFIX = ../..
+LIBS =
+EXTRA_CFLAGS =
+BINARY = kill
+
+SOURCES = \
+	kill.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/kill/kill.c
===================================================================
--- uspace/app/kill/kill.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/app/kill/kill.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kill
+ * @{
+ */
+/**
+ * @file Forcefully terminate a task.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <task.h>
+#include <str_error.h>
+
+#define NAME  "kill"
+
+static void print_syntax(void)
+{
+	printf("Syntax: " NAME " <task ID>\n");
+}
+
+int main(int argc, char *argv[])
+{
+	char *eptr;
+	task_id_t taskid;
+	int rc;
+
+	if (argc != 2) {
+		print_syntax();
+		return 1;
+	}
+
+	taskid = strtoul(argv[1], &eptr, 0);
+	if (*eptr != '\0') {
+		printf("Invalid task ID argument '%s'.\n", argv[1]);
+		return 2;
+	}
+
+	rc = task_kill(taskid);
+	if (rc != EOK) {
+		printf("Failed to kill task ID %" PRIu64 ": %s\n",
+		    taskid, str_error(rc));
+		return 3;
+	}
+
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/killall/Makefile
===================================================================
--- uspace/app/killall/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/app/killall/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,37 @@
+#
+# 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 = ../..
+LIBS =
+EXTRA_CFLAGS =
+BINARY = killall
+
+SOURCES = \
+	killall.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/killall/killall.c
===================================================================
--- uspace/app/killall/killall.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/app/killall/killall.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2010 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup killall
+ * @{
+ */
+/**
+ * @file Forcefully terminate a task specified by name.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <task.h>
+#include <stats.h>
+#include <str_error.h>
+#include <malloc.h>
+
+#define NAME  "killall"
+
+static void print_syntax(void)
+{
+	printf("Syntax: " NAME " <task name>\n");
+}
+
+int main(int argc, char *argv[])
+{
+	if (argc != 2) {
+		print_syntax();
+		return 1;
+	}
+	
+	size_t count;
+	stats_task_t *stats_tasks = stats_get_tasks(&count);
+	
+	if (stats_tasks == NULL) {
+		fprintf(stderr, "%s: Unable to get tasks\n", NAME);
+		return 2;
+	}
+	
+	size_t i;
+	for (i = 0; i < count; i++) {
+		if (str_cmp(stats_tasks[i].name, argv[1]) == 0) {
+			task_id_t taskid = stats_tasks[i].task_id;
+			int rc = task_kill(taskid);
+			if (rc != EOK)
+				printf("Failed to kill task ID %" PRIu64 ": %s\n",
+				    taskid, str_error(rc));
+			else
+				printf("Killed task ID %" PRIu64 "\n", taskid);
+		}
+	}
+	
+	free(stats_tasks);
+	
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/netecho/netecho.c
===================================================================
--- uspace/app/netecho/netecho.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/app/netecho/netecho.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -32,10 +32,13 @@
 
 /** @file
- * Network echo application.
- * Answers received packets.
+ * Network echo server.
+ *
+ * Sockets-based server that echoes incomming messages. If stream mode
+ * is selected, accepts incoming connections.
  */
 
-#include <malloc.h>
+#include <assert.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <str.h>
 #include <task.h>
@@ -50,178 +53,296 @@
 #include "print_error.h"
 
-/** Network echo module name. */
-#define NAME	"Network Echo"
+#define NAME "netecho"
+
+static int count = -1;
+static int family = PF_INET;
+static sock_type_t type = SOCK_DGRAM;
+static uint16_t port = 7;
+static int backlog = 3;
+static size_t size = 1024;
+static int verbose = 0;
+
+static char *reply = NULL;
+static size_t reply_length;
+
+static char *data;
 
 static void echo_print_help(void)
 {
 	printf(
-		"Network Echo aplication\n" \
-		"Usage: echo [options]\n" \
-		"Where options are:\n" \
-		"-b backlog | --backlog=size\n" \
-		"\tThe size of the accepted sockets queue. Only for SOCK_STREAM. The default is 3.\n" \
-		"\n" \
-		"-c count | --count=count\n" \
-		"\tThe number of received messages to handle. A negative number means infinity. The default is infinity.\n" \
-		"\n" \
-		"-f protocol_family | --family=protocol_family\n" \
-		"\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
-		"\n" \
-		"-h | --help\n" \
-		"\tShow this application help.\n"
-		"\n" \
-		"-p port_number | --port=port_number\n" \
-		"\tThe port number the application should listen at. The default is 7.\n" \
-		"\n" \
-		"-r reply_string | --reply=reply_string\n" \
-		"\tThe constant reply string. The default is the original data received.\n" \
-		"\n" \
-		"-s receive_size | --size=receive_size\n" \
-		"\tThe maximum receive data size the application should accept. The default is 1024 bytes.\n" \
-		"\n" \
-		"-t socket_type | --type=socket_type\n" \
-		"\tThe listenning socket type. Only the SOCK_DGRAM and the SOCK_STREAM are supported.\n" \
-		"\n" \
-		"-v | --verbose\n" \
-		"\tShow all output messages.\n"
+	    "Network echo server\n"
+	    "Usage: " NAME " [options]\n"
+	    "Where options are:\n"
+	    "-b backlog | --backlog=size\n"
+	    "\tThe size of the accepted sockets queue. Only for SOCK_STREAM. "
+	    "The default is 3.\n"
+	    "\n"
+	    "-c count | --count=count\n"
+	    "\tThe number of received messages to handle. A negative number "
+	    "means infinity. The default is infinity.\n"
+	    "\n"
+	    "-f protocol_family | --family=protocol_family\n"
+	    "\tThe listenning socket protocol family. Only the PF_INET and "
+	    "PF_INET6 are supported.\n"
+	    "\n"
+	    "-h | --help\n"
+	    "\tShow this application help.\n"
+	    "\n"
+	    "-p port_number | --port=port_number\n"
+	    "\tThe port number the application should listen at. The default "
+	    "is 7.\n"
+	    "\n"
+	    "-r reply_string | --reply=reply_string\n"
+	    "\tThe constant reply string. The default is the original data "
+	    "received.\n"
+	    "\n"
+	    "-s receive_size | --size=receive_size\n"
+	    "\tThe maximum receive data size the application should accept. "
+	    "The default is 1024 bytes.\n"
+	    "\n"
+	    "-t socket_type | --type=socket_type\n"
+	    "\tThe listenning socket type. Only the SOCK_DGRAM and the "
+	    "SOCK_STREAM are supported.\n"
+	    "\n"
+	    "-v | --verbose\n"
+	    "\tShow all output messages.\n"
 	);
 }
 
-int main(int argc, char *argv[])
+static int netecho_parse_option(int argc, char *argv[], int *index)
 {
-	size_t size = 1024;
-	int verbose = 0;
-	char *reply = NULL;
-	sock_type_t type = SOCK_DGRAM;
-	int count = -1;
-	int family = PF_INET;
-	uint16_t port = 7;
-	int backlog = 3;
-
-	socklen_t max_length = sizeof(struct sockaddr_in6);
-	uint8_t address_data[max_length];
-	struct sockaddr *address = (struct sockaddr *) address_data;
-	struct sockaddr_in *address_in = (struct sockaddr_in *) address;
-	struct sockaddr_in6 *address_in6 = (struct sockaddr_in6 *) address;
-	socklen_t addrlen;
-	char address_string[INET6_ADDRSTRLEN];
-	uint8_t *address_start;
-	int socket_id;
-	int listening_id;
-	char *data;
-	size_t length;
-	int index;
-	size_t reply_length;
 	int value;
 	int rc;
 
-	// parse the command line arguments
-	for (index = 1; index < argc; ++ index) {
-		if (argv[index][0] == '-') {
-			switch (argv[index][1]) {
-			case 'b':
-				rc = arg_parse_int(argc, argv, &index, &backlog, 0);
-				if (rc != EOK)
-					return rc;
-				break;
-			case 'c':
-				rc = arg_parse_int(argc, argv, &index, &count, 0);
-				if (rc != EOK)
-					return rc;
-				break;
-			case 'f':
-				rc = arg_parse_name_int(argc, argv, &index, &family, 0, socket_parse_protocol_family);
-				if (rc != EOK)
-					return rc;
-				break;
-			case 'h':
-				echo_print_help();
-				return EOK;
-				break;
-			case 'p':
-				rc = arg_parse_int(argc, argv, &index, &value, 0);
-				if (rc != EOK)
-					return rc;
-				port = (uint16_t) value;
-				break;
-			case 'r':
-				rc = arg_parse_string(argc, argv, &index, &reply, 0);
-				if (rc != EOK)
-					return rc;
-				break;
-			case 's':
-				rc = arg_parse_int(argc, argv, &index, &value, 0);
-				if (rc != EOK)
-					return rc;
-				size = (value >= 0) ? (size_t) value : 0;
-				break;
-			case 't':
-				rc = arg_parse_name_int(argc, argv, &index, &value, 0, socket_parse_socket_type);
-				if (rc != EOK)
-					return rc;
-				type = (sock_type_t) value;
-				break;
-			case 'v':
-				verbose = 1;
-				break;
-			// long options with the double minus sign ('-')
-			case '-':
-				if (str_lcmp(argv[index] + 2, "backlog=", 6) == 0) {
-					rc = arg_parse_int(argc, argv, &index, &backlog, 8);
-					if (rc != EOK)
-						return rc;
-				} else if (str_lcmp(argv[index] + 2, "count=", 6) == 0) {
-					rc = arg_parse_int(argc, argv, &index, &count, 8);
-					if (rc != EOK)
-						return rc;
-				} else if (str_lcmp(argv[index] + 2, "family=", 7) == 0) {
-					rc = arg_parse_name_int(argc, argv, &index, &family, 9, socket_parse_protocol_family);
-					if (rc != EOK)
-						return rc;
-				} else if (str_lcmp(argv[index] + 2, "help", 5) == 0) {
-					echo_print_help();
-					return EOK;
-				} else if (str_lcmp(argv[index] + 2, "port=", 5) == 0) {
-					rc = arg_parse_int(argc, argv, &index, &value, 7);
-					if (rc != EOK)
-						return rc;
-					port = (uint16_t) value;
-				} else if (str_lcmp(argv[index] + 2, "reply=", 6) == 0) {
-					rc = arg_parse_string(argc, argv, &index, &reply, 8);
-					if (rc != EOK)
-						return rc;
-				} else if (str_lcmp(argv[index] + 2, "size=", 5) == 0) {
-					rc = arg_parse_int(argc, argv, &index, &value, 7);
-					if (rc != EOK)
-						return rc;
-					size = (value >= 0) ? (size_t) value : 0;
-				} else if (str_lcmp(argv[index] + 2, "type=", 5) == 0) {
-					rc = arg_parse_name_int(argc, argv, &index, &value, 7, socket_parse_socket_type);
-					if (rc != EOK)
-						return rc;
-					type = (sock_type_t) value;
-				} else if (str_lcmp(argv[index] + 2, "verbose", 8) == 0) {
-					verbose = 1;
-				} else {
-					echo_print_help();
-					return EINVAL;
-				}
-				break;
-			default:
-				echo_print_help();
-				return EINVAL;
-			}
+	switch (argv[*index][1]) {
+	case 'b':
+		rc = arg_parse_int(argc, argv, index, &backlog, 0);
+		if (rc != EOK)
+			return rc;
+		break;
+	case 'c':
+		rc = arg_parse_int(argc, argv, index, &count, 0);
+		if (rc != EOK)
+			return rc;
+		break;
+	case 'f':
+		rc = arg_parse_name_int(argc, argv, index, &family, 0,
+		    socket_parse_protocol_family);
+		if (rc != EOK)
+			return rc;
+		break;
+	case 'h':
+		echo_print_help();
+		exit(0);
+		break;
+	case 'p':
+		rc = arg_parse_int(argc, argv, index, &value, 0);
+		if (rc != EOK)
+			return rc;
+		port = (uint16_t) value;
+		break;
+	case 'r':
+		rc = arg_parse_string(argc, argv, index, &reply, 0);
+		if (rc != EOK)
+			return rc;
+		break;
+	case 's':
+		rc = arg_parse_int(argc, argv, index, &value, 0);
+		if (rc != EOK)
+			return rc;
+		size = (value >= 0) ? (size_t) value : 0;
+		break;
+	case 't':
+		rc = arg_parse_name_int(argc, argv, index, &value, 0,
+		    socket_parse_socket_type);
+		if (rc != EOK)
+			return rc;
+		type = (sock_type_t) value;
+		break;
+	case 'v':
+		verbose = 1;
+		break;
+	/* Long options with double dash */
+	case '-':
+		if (str_lcmp(argv[*index] + 2, "backlog=", 6) == 0) {
+			rc = arg_parse_int(argc, argv, index, &backlog, 8);
+			if (rc != EOK)
+				return rc;
+		} else if (str_lcmp(argv[*index] + 2, "count=", 6) == 0) {
+			rc = arg_parse_int(argc, argv, index, &count, 8);
+			if (rc != EOK)
+				return rc;
+		} else if (str_lcmp(argv[*index] + 2, "family=", 7) == 0) {
+			rc = arg_parse_name_int(argc, argv, index, &family, 9,
+			    socket_parse_protocol_family);
+			if (rc != EOK)
+				return rc;
+		} else if (str_lcmp(argv[*index] + 2, "help", 5) == 0) {
+			echo_print_help();
+			exit(0);
+		} else if (str_lcmp(argv[*index] + 2, "port=", 5) == 0) {
+			rc = arg_parse_int(argc, argv, index, &value, 7);
+			if (rc != EOK)
+				return rc;
+			port = (uint16_t) value;
+		} else if (str_lcmp(argv[*index] + 2, "reply=", 6) == 0) {
+			rc = arg_parse_string(argc, argv, index, &reply, 8);
+			if (rc != EOK)
+				return rc;
+		} else if (str_lcmp(argv[*index] + 2, "size=", 5) == 0) {
+			rc = arg_parse_int(argc, argv, index, &value, 7);
+			if (rc != EOK)
+				return rc;
+			size = (value >= 0) ? (size_t) value : 0;
+		} else if (str_lcmp(argv[*index] + 2, "type=", 5) == 0) {
+			rc = arg_parse_name_int(argc, argv, index, &value, 7,
+			    socket_parse_socket_type);
+			if (rc != EOK)
+				return rc;
+			type = (sock_type_t) value;
+		} else if (str_lcmp(argv[*index] + 2, "verbose", 8) == 0) {
+			verbose = 1;
 		} else {
 			echo_print_help();
 			return EINVAL;
 		}
-	}
-
-	// check the buffer size
+		break;
+	default:
+		echo_print_help();
+		return EINVAL;
+	}
+
+	return EOK;
+}
+
+/** Echo one message (accept one connection and echo message).
+ *
+ * @param listening_id	Listening socket.
+ * @return		EOK on success or negative error code.
+ */
+static int netecho_socket_process_message(int listening_id)
+{
+	uint8_t address_buf[sizeof(struct sockaddr_in6)];
+
+	socklen_t addrlen;
+	int socket_id;
+	ssize_t rcv_size;
+	size_t length;
+	uint8_t *address_start;
+
+	char address_string[INET6_ADDRSTRLEN];
+	struct sockaddr_in *address_in = (struct sockaddr_in *) address_buf;
+	struct sockaddr_in6 *address_in6 = (struct sockaddr_in6 *) address_buf;
+	struct sockaddr *address = (struct sockaddr *) address_buf;
+
+	int rc;
+
+	if (type == SOCK_STREAM) {
+		/* Accept a socket if a stream socket is used */
+		addrlen = sizeof(address_buf);
+            	socket_id = accept(listening_id, (void *) address_buf, &addrlen);
+		if (socket_id <= 0) {
+			socket_print_error(stderr, socket_id, "Socket accept: ", "\n");
+		} else {
+			if (verbose)
+				printf("Socket %d accepted\n", socket_id);
+		}
+
+		assert((size_t) addrlen <= sizeof(address_buf));
+	} else {
+		socket_id = listening_id;
+	}
+
+	/* if the datagram socket is used or the stream socked was accepted */
+	if (socket_id > 0) {
+
+		/* Receive a message to echo */
+		rcv_size = recvfrom(socket_id, data, size, 0, address,
+		    &addrlen);
+		if (rcv_size < 0) {
+			socket_print_error(stderr, rcv_size, "Socket receive: ", "\n");
+		} else {
+			length = (size_t) rcv_size;
+			if (verbose) {
+				/* Print the header */
+
+				/* Get the source port and prepare the address buffer */
+				address_start = NULL;
+				switch (address->sa_family) {
+				case AF_INET:
+					port = ntohs(address_in->sin_port);
+					address_start = (uint8_t *) &address_in->sin_addr.s_addr;
+					break;
+				case AF_INET6:
+					port = ntohs(address_in6->sin6_port);
+					address_start = (uint8_t *) &address_in6->sin6_addr.s6_addr;
+					break;
+				default:
+					fprintf(stderr, "Address family %u (%#x) is not supported.\n",
+					    address->sa_family, address->sa_family);
+				}
+
+				/* Parse source address */
+				if (address_start) {
+					rc = inet_ntop(address->sa_family, address_start, address_string, sizeof(address_string));
+					if (rc != EOK) {
+						fprintf(stderr, "Received address error %d\n", rc);
+					} else {
+						data[length] = '\0';
+						printf("Socket %d received %zu bytes from %s:%d\n%s\n",
+						    socket_id, length, address_string, port, data);
+					}
+				}
+			}
+
+			/* Answer the request either with the static reply or the original data */
+			rc = sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen);
+			if (rc != EOK)
+				socket_print_error(stderr, rc, "Socket send: ", "\n");
+		}
+
+		/* Close accepted stream socket */
+		if (type == SOCK_STREAM) {
+			rc = closesocket(socket_id);
+			if (rc != EOK)
+				socket_print_error(stderr, rc, "Close socket: ", "\n");
+		}
+
+	}
+
+	return EOK;
+}
+
+
+int main(int argc, char *argv[])
+{
+	struct sockaddr *address;;
+	struct sockaddr_in address_in;
+	struct sockaddr_in6 address_in6;
+	socklen_t addrlen;
+
+	int listening_id;
+	int index;
+	int rc;
+
+	/* Parse command line arguments */
+	for (index = 1; index < argc; ++index) {
+		if (argv[index][0] == '-') {
+			rc = netecho_parse_option(argc, argv, &index);
+			if (rc != EOK)
+				return rc;
+		} else {
+			echo_print_help();
+			return EINVAL;
+		}
+	}
+
+	/* Check buffer size */
 	if (size <= 0) {
 		fprintf(stderr, "Receive size too small (%zu). Using 1024 bytes instead.\n", size);
 		size = 1024;
 	}
-	// size plus the terminating null (\0)
+
+	/* size plus the terminating null character. */
 	data = (char *) malloc(size + 1);
 	if (!data) {
@@ -230,19 +351,20 @@
 	}
 
-	// set the reply size if set
+	/* Set the reply size if set */
 	reply_length = reply ? str_length(reply) : 0;
 
-	// prepare the address buffer
-	bzero(address_data, max_length);
+	/* Prepare the address buffer */
 	switch (family) {
 	case PF_INET:
-		address_in->sin_family = AF_INET;
-		address_in->sin_port = htons(port);
-		addrlen = sizeof(struct sockaddr_in);
+		address_in.sin_family = AF_INET;
+		address_in.sin_port = htons(port);
+		address = (struct sockaddr *) &address_in;
+		addrlen = sizeof(address_in);
 		break;
 	case PF_INET6:
-		address_in6->sin6_family = AF_INET6;
-		address_in6->sin6_port = htons(port);
-		addrlen = sizeof(struct sockaddr_in6);
+		address_in6.sin6_family = AF_INET6;
+		address_in6.sin6_port = htons(port);
+		address = (struct sockaddr *) &address_in6;
+		addrlen = sizeof(address_in6);
 		break;
 	default:
@@ -251,5 +373,5 @@
 	}
 
-	// get a listening socket
+	/* Get a listening socket */
 	listening_id = socket(family, type, 0);
 	if (listening_id < 0) {
@@ -258,12 +380,13 @@
 	}
 
-	// if the stream socket is used
+	/* if the stream socket is used */
 	if (type == SOCK_STREAM) {
-		// check the backlog
+		/* Check backlog size */
 		if (backlog <= 0) {
 			fprintf(stderr, "Accepted sockets queue size too small (%zu). Using 3 instead.\n", size);
 			backlog = 3;
 		}
-		// set the backlog
+
+		/* Set the backlog */
 		rc = listen(listening_id, backlog);
 		if (rc != EOK) {
@@ -273,5 +396,5 @@
 	}
 
-	// bind the listenning socket
+	/* Bind the listening socket */
 	rc = bind(listening_id, address, addrlen);
 	if (rc != EOK) {
@@ -283,82 +406,18 @@
 		printf("Socket %d listenning at %d\n", listening_id, port);
 
-	socket_id = listening_id;
-
-	// do count times
-	// or indefinitely if set to a negative value
+	/*
+	 * do count times
+	 * or indefinitely if set to a negative value
+	 */
 	while (count) {
-
-		addrlen = max_length;
-		if (type == SOCK_STREAM) {
-			// acceept a socket if the stream socket is used
-			socket_id = accept(listening_id, address, &addrlen);
-			if (socket_id <= 0) {
-				socket_print_error(stderr, socket_id, "Socket accept: ", "\n");
-			} else {
-				if (verbose)
-					printf("Socket %d accepted\n", socket_id);
-			}
-		}
-
-		// if the datagram socket is used or the stream socked was accepted
-		if (socket_id > 0) {
-
-			// receive an echo request
-			value = recvfrom(socket_id, data, size, 0, address, &addrlen);
-			if (value < 0) {
-				socket_print_error(stderr, value, "Socket receive: ", "\n");
-			} else {
-				length = (size_t) value;
-				if (verbose) {
-					// print the header
-
-					// get the source port and prepare the address buffer
-					address_start = NULL;
-					switch (address->sa_family) {
-					case AF_INET:
-						port = ntohs(address_in->sin_port);
-						address_start = (uint8_t *) &address_in->sin_addr.s_addr;
-						break;
-					case AF_INET6:
-						port = ntohs(address_in6->sin6_port);
-						address_start = (uint8_t *) &address_in6->sin6_addr.s6_addr;
-						break;
-					default:
-						fprintf(stderr, "Address family %u (%#x) is not supported.\n",
-						    address->sa_family, address->sa_family);
-					}
-					// parse the source address
-					if (address_start) {
-						rc = inet_ntop(address->sa_family, address_start, address_string, sizeof(address_string));
-						if (rc != EOK) {
-							fprintf(stderr, "Received address error %d\n", rc);
-						} else {
-							data[length] = '\0';
-							printf("Socket %d received %zu bytes from %s:%d\n%s\n",
-							    socket_id, length, address_string, port, data);
-						}
-					}
-				}
-
-				// answer the request either with the static reply or the original data
-				rc = sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen);
-				if (rc != EOK)
-					socket_print_error(stderr, rc, "Socket send: ", "\n");
-			}
-
-			// close the accepted stream socket
-			if (type == SOCK_STREAM) {
-				rc = closesocket(socket_id);
-				if (rc != EOK)
-					socket_print_error(stderr, rc, "Close socket: ", "\n");
-			}
-
-		}
-
-		// decrease the count if positive
+		rc = netecho_socket_process_message(listening_id);
+		if (rc != EOK)
+			break;
+
+		/* Decrease count if positive */
 		if (count > 0) {
 			count--;
 			if (verbose)
-				printf("Waiting for next %d packet(s)\n", count);
+				printf("Waiting for next %d message(s)\n", count);
 		}
 	}
@@ -367,5 +426,5 @@
 		printf("Closing the socket\n");
 
-	// close the listenning socket
+	/* Close listenning socket */
 	rc = closesocket(listening_id);
 	if (rc != EOK) {
Index: uspace/app/taskdump/taskdump.c
===================================================================
--- uspace/app/taskdump/taskdump.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/app/taskdump/taskdump.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -326,5 +326,5 @@
 
 	sym_pc = fmt_sym_address(pc);
-	printf("Thread %p crashed at %s. FP = %p\n", (void *) thash,
+	printf("Thread %p: PC = %s. FP = %p\n", (void *) thash,
 	    sym_pc, (void *) fp);
 	free(sym_pc);
Index: uspace/app/websrv/Makefile
===================================================================
--- uspace/app/websrv/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/app/websrv/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 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.
+#
+
+USPACE_PREFIX = ../..
+LIBS =
+EXTRA_CFLAGS =
+BINARY = websrv
+
+SOURCES = \
+	websrv.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/websrv/websrv.c
===================================================================
--- uspace/app/websrv/websrv.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/app/websrv/websrv.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup websrv
+ * @{
+ */
+/**
+ * @file (Less-than-skeleton) web server.
+ */
+
+#include <stdio.h>
+
+#include <net/in.h>
+#include <net/inet.h>
+#include <net/socket.h>
+
+#include <str.h>
+
+#define PORT_NUMBER 8080
+
+/** Buffer for receiving the request. */
+#define BUFFER_SIZE 1024
+static char buf[BUFFER_SIZE];
+
+/** Response to send to client. */
+static const char *response_msg =
+    "HTTP/1.0 200 OK\r\n"
+    "\r\n"
+    "<h1>Hello from HelenOS!</h1>\r\n";
+
+int main(int argc, char *argv[])
+{
+	struct sockaddr_in addr;
+	struct sockaddr_in raddr;
+
+	socklen_t raddr_len;
+
+	int listen_sd, conn_sd;
+	int rc;
+
+	size_t response_size;
+
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(PORT_NUMBER);
+
+	rc = inet_pton(AF_INET, "127.0.0.1", (void *) &addr.sin_addr.s_addr);
+	if (rc != EOK) {
+		printf("Error parsing network address.\n");
+		return 1;
+	}
+
+	printf("Creating socket.\n");
+
+	listen_sd = socket(PF_INET, SOCK_STREAM, 0);
+	if (listen_sd < 0) {
+		printf("Error creating listening socket.\n");
+		return 1;
+	}
+
+	rc = bind(listen_sd, (struct sockaddr *) &addr, sizeof(addr));
+	if (rc != EOK) {
+		printf("Error binding socket.\n");
+		return 1;
+	}
+
+	rc = listen(listen_sd, 1);
+	if (rc != EOK) {
+		printf("Error calling listen() (%d).\n", rc);
+		return 1;
+	}
+
+	response_size = str_size(response_msg);
+
+	printf("Listening for connections at port number %u.\n", PORT_NUMBER);
+	while (true) {
+		raddr_len = sizeof(raddr);
+		conn_sd = accept(listen_sd, (struct sockaddr *) &raddr,
+		    &raddr_len);
+
+		if (conn_sd < 0) {
+			printf("accept() failed.\n");
+			return 1;
+		}
+
+		printf("Accepted connection, sd=%d.\n", conn_sd);
+
+		printf("Wait for client request\n");
+
+		/* Really we should wait for a blank line. */
+		rc = recv(conn_sd, buf, BUFFER_SIZE, 0);
+		if (rc < 0) {
+			printf("recv() failed\n");
+			return 1;
+		}
+
+		/* Send a canned response. */
+                printf("Send response...\n");
+		rc = send(conn_sd, (void *) response_msg, response_size, 0);
+		if (rc < 0) {
+			printf("send() failed.\n");
+			return 1;
+		}
+
+		rc = closesocket(conn_sd);
+		if (rc != EOK) {
+			printf("Error closing connection socket: %d\n", rc);
+			return 1;
+		}
+
+		printf("Closed connection.\n");
+	}
+
+	/* Not reached. */
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/drv/uhci/main.c
===================================================================
--- uspace/drv/uhci/main.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/drv/uhci/main.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -27,4 +27,5 @@
  */
 #include <usb/hcdhubd.h>
+#include <usb_iface.h>
 #include <usb/debug.h>
 #include <errno.h>
@@ -32,6 +33,20 @@
 #include "uhci.h"
 
+static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
+{
+	/* This shall be called only for the UHCI itself. */
+	assert(dev->parent == NULL);
+
+	*handle = dev->handle;
+	return EOK;
+}
+
+static usb_iface_t hc_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle
+};
+
 static device_ops_t uhci_ops = {
-	.interfaces[USBHC_DEV_IFACE] = &uhci_iface,
+	.interfaces[USB_DEV_IFACE] = &hc_usb_iface,
+	.interfaces[USBHC_DEV_IFACE] = &uhci_iface
 };
 
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/drv/usbhub/usbhub.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -37,5 +37,5 @@
 #include <errno.h>
 
-#include <usbhc_iface.h>
+#include <usb_iface.h>
 #include <usb/usbdrv.h>
 #include <usb/descriptor.h>
@@ -46,4 +46,12 @@
 #include "usbhub_private.h"
 #include "port_status.h"
+
+static usb_iface_t hub_usb_iface = {
+	.get_hc_handle = usb_drv_find_hc
+};
+
+static device_ops_t hub_device_ops = {
+	.interfaces[USB_DEV_IFACE] = &hub_usb_iface
+};
 
 //*********************************************
@@ -135,8 +143,12 @@
 	 * connected devices.
 	 */
+	dev->ops = &hub_device_ops;
 
 	//create the hub structure
 	//get hc connection
-	int hc = usb_drv_hc_connect(dev, 0);
+	int hc = usb_drv_hc_connect_auto(dev, 0);
+	if (hc < 0) {
+		return hc;
+	}
 
 	usb_hub_info_t * hub_info = usb_create_hub_info(dev, hc);
@@ -464,5 +476,5 @@
 		 * Connect to respective HC.
 		 */
-		int hc = usb_drv_hc_connect(hub_info->device, 0);
+		int hc = usb_drv_hc_connect_auto(hub_info->device, 0);
 		if (hc < 0) {
 			continue;
Index: uspace/drv/usbkbd/main.c
===================================================================
--- uspace/drv/usbkbd/main.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/drv/usbkbd/main.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -190,5 +190,5 @@
 	// get phone to my HC and save it as my parent's phone
 	// TODO: maybe not a good idea if DDF will use parent_phone
-	kbd_dev->device->parent_phone = usb_drv_hc_connect(dev, 0);
+	kbd_dev->device->parent_phone = usb_drv_hc_connect_auto(dev, 0);
 
 	kbd_dev->address = usb_drv_get_my_address(dev->parent_phone,
@@ -325,5 +325,5 @@
 	 * Not supported yet, skip..
 	 */
-//	int phone = usb_drv_hc_connect(dev, 0);
+//	int phone = usb_drv_hc_connect_auto(dev, 0);
 //	if (phone < 0) {
 //		/*
Index: uspace/drv/vhc/hcd.c
===================================================================
--- uspace/drv/vhc/hcd.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/drv/vhc/hcd.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -46,4 +46,5 @@
 
 #include <usb/usb.h>
+#include <usb_iface.h>
 #include "vhcd.h"
 #include "hc.h"
@@ -52,6 +53,20 @@
 #include "conn.h"
 
+static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
+{
+	/* This shall be called only for VHC device. */
+	assert(dev->parent == NULL);
+
+	*handle = dev->handle;
+	return EOK;
+}
+
+static usb_iface_t hc_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle
+};
+
 static device_ops_t vhc_ops = {
 	.interfaces[USBHC_DEV_IFACE] = &vhc_iface,
+	.interfaces[USB_DEV_IFACE] = &hc_usb_iface,
 	.default_handler = default_connection_handler
 };
Index: uspace/drv/vhc/hub.c
===================================================================
--- uspace/drv/vhc/hub.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/drv/vhc/hub.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -79,5 +79,5 @@
 	device_t *hc_dev = (device_t *) arg;
 
-	int hc = usb_drv_hc_connect(hc_dev, IPC_FLAG_BLOCKING);
+	int hc = usb_drv_hc_connect(hc_dev, hc_dev->handle, IPC_FLAG_BLOCKING);
 	if (hc < 0) {
 		printf(NAME ": failed to register root hub\n");
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -87,5 +87,5 @@
 	generic/ipc.c \
 	generic/async.c \
-	generic/async_rel.c \
+	generic/async_sess.c \
 	generic/loader.c \
 	generic/getopt.c \
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/generic/async.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -749,4 +749,6 @@
 		return ENOMEM;
 	}
+
+	_async_sess_init();
 	
 	return 0;
Index: pace/lib/c/generic/async_rel.c
===================================================================
--- uspace/lib/c/generic/async_rel.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ 	(revision )
@@ -1,307 +1,0 @@
-/*
- * Copyright (c) 2010 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-/**
- * This file implements simple relation support for the async framework.
- *
- * By the term "relation", we mean a logical data path between a client and a
- * server over which the client can send multiple, potentially blocking,
- * requests to the server.
- *
- * Clients and servers are naturally connected using IPC phones, thus an IPC
- * phone represents a connection between a client and a server. In one
- * connection, there can be many relations.
- *
- * Relations are useful in situations in which there is only one IPC connection
- * between the client and the server, but the client wants to be able to make
- * multiple parallel requests. Using only a single phone and without any other
- * provisions, all requests would have to be serialized. On the other hand, the
- * client can make as many parallel requests as there are active relations.
- *
- * There are several possible implementations of relations. This implementation
- * uses additional phones to represent relations. Using phones both for the
- * primary connection and also for its relations has several advantages:
- *
- * - to make a series of requests over a relation, the client can continue to
- *   use the existing async framework APIs
- * - the server supports relations by the virtue of spawning a new connection
- *   fibril, just as it does for every new connection even without relations
- * - the implementation is pretty straightforward; a very naive implementation
- *   would be to make each request using a fresh phone (that is what we have
- *   done in the past); a slightly better approach would be to cache connected
- *   phones so that they can be reused by a later relation within the same
- *   connection (that is what this implementation does)
- *
- * The main disadvantages of using phones to represent relations are:
- *
- * - if there are too many relations (even cached ones), the task may hit its
- *   limit on the maximum number of connected phones, which could prevent the
- *   task from making new IPC connections to other tasks
- * - if there are too many IPC connections already, it may be impossible to
- *   create a relation by connecting a new phone thanks to the task's limit on
- *   the maximum number of connected phones
- *
- * These problems can be helped by increasing the limit on the maximum number of
- * connected phones to some reasonable value and by limiting the number of
- * phones cached to some fraction of this limit.
- *
- * The cache itself has a mechanism to close some number of unused phones if a
- * new phone cannot be connected, but the outter world currently does not have a
- * way to ask the phone cache to shrink.
- *
- * To minimize the confusion stemming from the fact that we use phones for two
- * things (the primary IPC connection and also each relation), this file makes
- * the distinction by using the term 'key phone' for the former and 'relation
- * phone' for the latter. Under the hood, all phones remain equal, of course.
- *
- * There is a small inefficiency in that the cache repeatedly allocates and
- * deallocated the rel_node_t structures when in fact it could keep the
- * allocated structures around and reuse them later. But such a solution would
- * be effectively implementing a poor man's slab allocator while it would be
- * better to have the slab allocator ported to uspace so that everyone could
- * benefit from it.
- */
-
-#include <async_rel.h>
-#include <ipc/ipc.h>
-#include <fibril_synch.h>
-#include <adt/list.h>
-#include <adt/hash_table.h>
-#include <malloc.h>
-#include <errno.h>
-#include <assert.h>
-
-#define KEY_NODE_HASH_BUCKETS	16
-
-typedef struct {
-	link_t link;		/**< Key node hash table link. */
-	int key_phone;		/**< The phone serving as a key. */
-	link_t rel_head;	/**< List of open relation phones. */
-} key_node_t;
-
-typedef struct {
-	link_t rel_link;	/**< Link for the list of relation phones. */
-	link_t global_link;	/**< Link for the global list of phones. */
-	int rel_phone;		/**< Connected relation phone. */
-} rel_node_t;
-
-/**
- * Mutex protecting the global_rel_head list and the key_node_hash hash table.
- */
-static fibril_mutex_t async_rel_mutex;
-
-/**
- * List of all currently unused relation phones.
- */
-static LIST_INITIALIZE(global_rel_head);
-
-/**
- * Hash table containing lists of available relation phones for all key
- * phones.
- */
-static hash_table_t key_node_hash;
-
-static hash_index_t kn_hash(unsigned long *key)
-{
-	return *key % KEY_NODE_HASH_BUCKETS;
-}
-
-static int kn_compare(unsigned long *key, hash_count_t keys, link_t *item)
-{
-	key_node_t *knp = hash_table_get_instance(item, key_node_t, link);
-
-	return *key == (unsigned long) knp->key_phone;
-}
-
-static void kn_remove_callback(link_t *item)
-{
-}
-
-static hash_table_operations_t key_node_hash_ops = {
-	.hash = kn_hash,
-	.compare = kn_compare,
-	.remove_callback = kn_remove_callback
-};
-
-/** Initialize the async_rel subsystem.
- *
- * Needs to be called prior to any other interface in this file.
- */
-int async_rel_init(void)
-{
-	fibril_mutex_initialize(&async_rel_mutex);
-	list_initialize(&global_rel_head);
-	return hash_table_create(&key_node_hash, KEY_NODE_HASH_BUCKETS, 1,
-	    &key_node_hash_ops);
-}
-
-static void key_node_initialize(key_node_t *knp)
-{
-	link_initialize(&knp->link);
-	knp->key_phone = -1;
-	list_initialize(&knp->rel_head);
-}
-
-static void rel_node_initialize(rel_node_t *rnp)
-{
-	link_initialize(&rnp->rel_link);
-	link_initialize(&rnp->global_link);
-	rnp->rel_phone = -1;
-}
-
-/** Create a new relation for a connection represented by a key phone.
- *
- * @param key_phone	Phone representing the connection.
- * @return		Phone representing the new relation or a negative error
- *			code.
- */
-int async_relation_create(int key_phone)
-{
-	unsigned long key = (unsigned long) key_phone;
-	link_t *lnk;
-	key_node_t *knp;
-	rel_node_t *rnp;
-	int rel_phone;
-
-	fibril_mutex_lock(&async_rel_mutex);
-	lnk = hash_table_find(&key_node_hash, &key);
-	if (!lnk) {
-		/*
-		 * The key node was not found in the hash table. Try to allocate
-		 * and hash in a new one.
-		 */
-		knp = (key_node_t *) malloc(sizeof(key_node_t));
-		if (!knp) {
-			/*
-			 * As a possible improvement, we could make a one-time
-			 * attempt to create a phone without trying to add the
-			 * key node into the hash.
-			 */
-			fibril_mutex_unlock(&async_rel_mutex);
-			return ENOMEM;
-		}
-		key_node_initialize(knp);
-		knp->key_phone = key_phone;
-		hash_table_insert(&key_node_hash, &key, &knp->link);
-	} else {
-		/*
-		 * Found the key node.
-		 */
-		knp = hash_table_get_instance(lnk, key_node_t, link);
-	}
-
-	if (!list_empty(&knp->rel_head)) {
-		/*
-		 * There are available relation phones for the key phone.
-		 */
-		rnp = list_get_instance(knp->rel_head.next, rel_node_t,
-		    rel_link);
-		list_remove(&rnp->rel_link);
-		list_remove(&rnp->global_link);
-		
-		rel_phone = rnp->rel_phone;
-		free(rnp);
-	} else {
-		/*
-		 * There are no available relation phones for the key phone.
-		 * Make a one-time attempt to connect a new relation phone.
-		 */
-retry:
-		rel_phone = async_connect_me_to(key_phone, 0, 0, 0);
-		if (rel_phone >= 0) {
-			/* success, do nothing */
-		} else if (!list_empty(&global_rel_head)) {
-			/*
-			 * We did not manage to connect a new phone. But we can
-			 * try to hangup some currently unused phones and try
-			 * again.
-			 */
-			rnp = list_get_instance(global_rel_head.next,
-			    rel_node_t, global_link);
-			list_remove(&rnp->global_link);
-			list_remove(&rnp->rel_link);
-			rel_phone = rnp->rel_phone;
-			free(rnp);
-			ipc_hangup(rel_phone);
-			goto retry;
-		} else {
-			/*
-			 * This is unfortunate. We failed both to find a cached
-			 * phone or to create a new one even after cleaning up
-			 * the cache. This is most likely due to too many key
-			 * phones being kept connected.
-			 */
-			rel_phone = ELIMIT;
-		}
-	}
-
-	fibril_mutex_unlock(&async_rel_mutex);
-	return rel_phone;
-}
-
-/** Destroy a relation.
- *
- * @param key_phone	Phone representing the connection.
- * @param rel_phone	Phone representing the relation within the connection.
- */
-void async_relation_destroy(int key_phone, int rel_phone)
-{
-	unsigned long key = (unsigned long) key_phone;
-	key_node_t *knp;
-	rel_node_t *rnp;
-	link_t *lnk;
-
-	fibril_mutex_lock(&async_rel_mutex);
-	lnk = hash_table_find(&key_node_hash, &key);
-	assert(lnk);
-	knp = hash_table_get_instance(lnk, key_node_t, link);
-	rnp = (rel_node_t *) malloc(sizeof(rel_node_t));
-	if (!rnp) {
-		/*
-		 * Being unable to remember the connected relation phone here
-		 * means that we simply hangup.
-		 */
-		fibril_mutex_unlock(&async_rel_mutex);
-		ipc_hangup(rel_phone);
-		return;
-	}
-	rel_node_initialize(rnp);
-	rnp->rel_phone = rel_phone;
-	list_append(&rnp->rel_link, &knp->rel_head);
-	list_append(&rnp->global_link, &global_rel_head);
-	fibril_mutex_unlock(&async_rel_mutex);
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/async_sess.c
===================================================================
--- uspace/lib/c/generic/async_sess.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/lib/c/generic/async_sess.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2010 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+/**
+ * This file implements simple session support for the async framework.
+ *
+ * By the term 'session', we mean a logical data path between a client and a
+ * server over which the client can perform multiple concurrent exchanges.
+ * Each exchange consists of one or more requests (IPC calls) which can
+ * be potentially blocking.
+ *
+ * Clients and servers are naturally connected using IPC phones, thus an IPC
+ * phone represents a session between a client and a server. In one
+ * session, there can be many outstanding exchanges. In the current
+ * implementation each concurrent exchanges takes place over a different
+ * connection (there can be at most one active exchage per connection).
+ *
+ * Sessions make it useful for a client or client API to support concurrent
+ * requests, independent of the actual implementation. Sessions provide
+ * an abstract interface to concurrent IPC communication. This is especially
+ * useful for client API stubs that aim to be reentrant (i.e. that allow
+ * themselves to be called from different fibrils and threads concurrently).
+ *
+ * There are several possible implementations of sessions. This implementation
+ * uses additional phones to represent sessions. Using phones both for the
+ * session and also for its exchages/connections has several advantages:
+ *
+ * - to make a series of exchanges over a session, the client can continue to
+ *   use the existing async framework APIs
+ * - the server supports sessions by the virtue of spawning a new connection
+ *   fibril, just as it does for every new connection even without sessions
+ * - the implementation is pretty straightforward; a very naive implementation
+ *   would be to make each exchage using a fresh phone (that is what we
+ *   have done in the past); a slightly better approach would be to cache
+ *   connections so that they can be reused by a later exchange within
+ *   the same session (that is what this implementation does)
+ *
+ * The main disadvantages of using phones to represent sessions are:
+ *
+ * - if there are too many exchanges (even cached ones), the task may hit its
+ *   limit on the maximum number of connected phones, which could prevent the
+ *   task from making new IPC connections to other tasks
+ * - if there are too many IPC connections already, it may be impossible to
+ *   create an exchange by connecting a new phone thanks to the task's limit on
+ *   the maximum number of connected phones
+ *
+ * These problems can be alleviated by increasing the limit on the maximum
+ * number of connected phones to some reasonable value and by limiting the number
+ * of cached connections to some fraction of this limit.
+ *
+ * The cache itself has a mechanism to close some number of unused phones if a
+ * new phone cannot be connected, but the outer world currently does not have a
+ * way to ask the phone cache to shrink.
+ *
+ * To minimize the confusion stemming from the fact that we use phones for two
+ * things (the session itself and also one for each data connection), this file
+ * makes the distinction by using the term 'session phone' for the former and
+ * 'data phone' for the latter. Under the hood, all phones remain equal,
+ * of course.
+ *
+ * There is a small inefficiency in that the cache repeatedly allocates and
+ * deallocates the conn_node_t structures when in fact it could keep the
+ * allocated structures around and reuse them later. But such a solution would
+ * be effectively implementing a poor man's slab allocator while it would be
+ * better to have the slab allocator ported to uspace so that everyone could
+ * benefit from it.
+ */
+
+#include <async_sess.h>
+#include <ipc/ipc.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <adt/hash_table.h>
+#include <malloc.h>
+#include <errno.h>
+#include <assert.h>
+
+/** An inactive open connection. */
+typedef struct {
+	link_t sess_link;	/**< Link for the session list of inactive connections. */
+	link_t global_link;	/**< Link for the global list of inactive connectinos. */
+	int data_phone;		/**< Connected data phone. */
+} conn_node_t;
+
+/**
+ * Mutex protecting the inactive_conn_head list and the session list.
+ */
+static fibril_mutex_t async_sess_mutex;
+
+/**
+ * List of all currently inactive connections.
+ */
+static LIST_INITIALIZE(inactive_conn_head);
+
+/**
+ * List of all open sessions.
+ */
+static LIST_INITIALIZE(session_list_head);
+
+/** Initialize the async_sess subsystem.
+ *
+ * Needs to be called prior to any other interface in this file.
+ */
+void _async_sess_init(void)
+{
+	fibril_mutex_initialize(&async_sess_mutex);
+	list_initialize(&inactive_conn_head);
+	list_initialize(&session_list_head);
+}
+
+/** Create a session.
+ *
+ * Session is a logical datapath from a client task to a server task.
+ * One session can accomodate multiple concurrent exchanges. Here
+ * @a phone is a phone connected to the desired server task.
+ *
+ * This function always succeeds.
+ *
+ * @param sess	Session structure provided by caller, will be filled in.
+ * @param phone	Phone connected to the desired server task.
+ */
+void async_session_create(async_sess_t *sess, int phone)
+{
+	sess->sess_phone = phone;
+	list_initialize(&sess->conn_head);
+	
+	/* Add to list of sessions. */
+	fibril_mutex_lock(&async_sess_mutex);
+	list_append(&sess->sess_link, &session_list_head);
+	fibril_mutex_unlock(&async_sess_mutex);
+}
+
+/** Destroy a session.
+ *
+ * Dismantle session structure @a sess and release any resources (connections)
+ * held by the session.
+ *
+ * @param sess	Session to destroy.
+ */
+void async_session_destroy(async_sess_t *sess)
+{
+	conn_node_t *conn;
+
+	/* Remove from list of sessions. */
+	fibril_mutex_lock(&async_sess_mutex);
+	list_remove(&sess->sess_link);
+	fibril_mutex_unlock(&async_sess_mutex);
+
+	/* We did not connect the phone so we do not hang it up either. */
+	sess->sess_phone = -1;
+
+	/* Tear down all data connections. */
+	while (!list_empty(&sess->conn_head)) {
+		conn = list_get_instance(sess->conn_head.next, conn_node_t,
+		    sess_link);
+
+		list_remove(&conn->sess_link);
+		list_remove(&conn->global_link);
+		
+		ipc_hangup(conn->data_phone);
+		free(conn);
+	}
+}
+
+static void conn_node_initialize(conn_node_t *conn)
+{
+	link_initialize(&conn->sess_link);
+	link_initialize(&conn->global_link);
+	conn->data_phone = -1;
+}
+
+/** Start new exchange in a session.
+ *
+ * @param sess_phone	Session.
+ * @return		Phone representing the new exchange or a negative error
+ *			code.
+ */
+int async_exchange_begin(async_sess_t *sess)
+{
+	conn_node_t *conn;
+	int data_phone;
+
+	fibril_mutex_lock(&async_sess_mutex);
+
+	if (!list_empty(&sess->conn_head)) {
+		/*
+		 * There are inactive connections in the session.
+		 */
+		conn = list_get_instance(sess->conn_head.next, conn_node_t,
+		    sess_link);
+		list_remove(&conn->sess_link);
+		list_remove(&conn->global_link);
+		
+		data_phone = conn->data_phone;
+		free(conn);
+	} else {
+		/*
+		 * There are no available connections in the session.
+		 * Make a one-time attempt to connect a new data phone.
+		 */
+retry:
+		data_phone = async_connect_me_to(sess->sess_phone, 0, 0, 0);
+		if (data_phone >= 0) {
+			/* success, do nothing */
+		} else if (!list_empty(&inactive_conn_head)) {
+			/*
+			 * We did not manage to connect a new phone. But we can
+			 * try to close some of the currently inactive
+			 * connections in other sessions and try again.
+			 */
+			conn = list_get_instance(inactive_conn_head.next,
+			    conn_node_t, global_link);
+			list_remove(&conn->global_link);
+			list_remove(&conn->sess_link);
+			data_phone = conn->data_phone;
+			free(conn);
+			ipc_hangup(data_phone);
+			goto retry;
+		} else {
+			/*
+			 * This is unfortunate. We failed both to find a cached
+			 * connection or to create a new one even after cleaning up
+			 * the cache. This is most likely due to too many
+			 * open sessions (connected session phones).
+			 */
+			data_phone = ELIMIT;
+		}
+	}
+
+	fibril_mutex_unlock(&async_sess_mutex);
+	return data_phone;
+}
+
+/** Finish an exchange.
+ *
+ * @param sess		Session.
+ * @param data_phone	Phone representing the exchange within the session.
+ */
+void async_exchange_end(async_sess_t *sess, int data_phone)
+{
+	conn_node_t *conn;
+
+	fibril_mutex_lock(&async_sess_mutex);
+	conn = (conn_node_t *) malloc(sizeof(conn_node_t));
+	if (!conn) {
+		/*
+		 * Being unable to remember the connected data phone here
+		 * means that we simply hang up.
+		 */
+		fibril_mutex_unlock(&async_sess_mutex);
+		ipc_hangup(data_phone);
+		return;
+	}
+
+	conn_node_initialize(conn);
+	conn->data_phone = data_phone;
+	list_append(&conn->sess_link, &sess->conn_head);
+	list_append(&conn->global_link, &inactive_conn_head);
+	fibril_mutex_unlock(&async_sess_mutex);
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/generic/libc.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -50,5 +50,4 @@
 #include <ipc/ipc.h>
 #include <async.h>
-#include <async_rel.h>
 #include <as.h>
 #include <loader/pcb.h>
@@ -66,5 +65,4 @@
 	__heap_init();
 	__async_init();
-	(void) async_rel_init();
 	fibril_t *fibril = fibril_setup();
 	__tcb_set(fibril->tcb);
Index: uspace/lib/c/generic/net/icmp_api.c
===================================================================
--- uspace/lib/c/generic/net/icmp_api.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/generic/net/icmp_api.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -89,5 +89,5 @@
 	    tos, (sysarg_t) dont_fragment, NULL);
 
-	// send the address
+	/* Send the address */
 	async_data_write_start(icmp_phone, addr, (size_t) addrlen);
 
Index: uspace/lib/c/generic/net/inet.c
===================================================================
--- uspace/lib/c/generic/net/inet.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/generic/net/inet.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -64,9 +64,9 @@
 	switch (family) {
 	case AF_INET:
-		// check the output buffer size
+		/* Check output buffer size */
 		if (length < INET_ADDRSTRLEN)
 			return ENOMEM;
 			
-		// fill the buffer with the IPv4 address
+		/* Fill buffer with IPv4 address */
 		snprintf(address, length, "%hhu.%hhu.%hhu.%hhu",
 		    data[0], data[1], data[2], data[3]);
@@ -75,9 +75,9 @@
 
 	case AF_INET6:
-		// check the output buffer size
+		/* Check output buffer size */
 		if (length < INET6_ADDRSTRLEN)
 			return ENOMEM;
 		
-		// fill the buffer with the IPv6 address
+		/* Fill buffer with IPv6 address */
 		snprintf(address, length,
 		    "%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:"
@@ -124,5 +124,5 @@
 		return EINVAL;
 
-	// set the processing parameters
+	/* Set processing parameters */
 	switch (family) {
 	case AF_INET:
@@ -142,5 +142,5 @@
 	}
 
-	// erase if no address
+	/* Erase if no address */
 	if (!address) {
 		bzero(data, count);
@@ -148,28 +148,30 @@
 	}
 
-	// process the string from the beginning
+	/* Process string from the beginning */
 	next = address;
 	index = 0;
 	do {
-		// if the actual character is set
+		/* If the actual character is set */
 		if (next && *next) {
 
-			// if not on the first character
+			/* If not on the first character */
 			if (index) {
-				// move to the next character
+				/* Move to the next character */
 				++next;
 			}
 
-			// parse the actual integral value
+			/* Parse the actual integral value */
 			value = strtoul(next, &last, base);
-			// remember the last problematic character
-			// should be either '.' or ':' but is ignored to be more
-			// generic
+			/*
+			 * Remember the last problematic character
+			 * should be either '.' or ':' but is ignored to be
+			 * more generic
+			 */
 			next = last;
 
-			// fill the address data byte by byte
+			/* Fill the address data byte by byte */
 			shift = bytes - 1;
 			do {
-				// like little endian
+				/* like little endian */
 				data[index + shift] = value;
 				value >>= 8;
@@ -178,5 +180,5 @@
 			index += bytes;
 		} else {
-			// erase the rest of the address
+			/* Erase the rest of the address */
 			bzero(data + index, count - index);
 			return EOK;
Index: uspace/lib/c/generic/net/modules.c
===================================================================
--- uspace/lib/c/generic/net/modules.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/generic/net/modules.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -63,5 +63,5 @@
     int answer_count)
 {
-	// choose the most efficient answer function
+	/* Choose the most efficient answer function */
 	if (answer || (!answer_count)) {
 		switch (answer_count) {
@@ -178,5 +178,5 @@
 	int phone;
 
-	// if no timeout is set
+	/* If no timeout is set */
 	if (timeout <= 0)
 		return async_connect_me_to_blocking(PHONE_NS, need, 0, 0);
@@ -187,9 +187,9 @@
 			return phone;
 
-		// end if no time is left
+		/* Abort if no time is left */
 		if (timeout <= 0)
 			return ETIMEOUT;
 
-		// wait the minimum of the module wait time and the timeout
+		/* Wait the minimum of the module wait time and the timeout */
 		usleep((timeout <= MODULE_WAIT_TIME) ?
 		    timeout : MODULE_WAIT_TIME);
@@ -214,9 +214,9 @@
 	ipc_callid_t callid;
 
-	// fetch the request
+	/* Fetch the request */
 	if (!async_data_read_receive(&callid, &length))
 		return EINVAL;
 
-	// check the requested data size
+	/* Check the requested data size */
 	if (length < data_length) {
 		async_data_read_finalize(callid, data, length);
@@ -224,5 +224,5 @@
 	}
 
-	// send the data
+	/* Send the data */
 	return async_data_read_finalize(callid, data, data_length);
 }
@@ -242,5 +242,5 @@
 	if (answer) {
 		IPC_SET_RETVAL(*answer, 0);
-		// just to be precize
+		/* Just to be precise */
 		IPC_SET_IMETHOD(*answer, 0);
 		IPC_SET_ARG1(*answer, 0);
Index: uspace/lib/c/generic/net/packet.c
===================================================================
--- uspace/lib/c/generic/net/packet.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/generic/net/packet.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -191,5 +191,5 @@
 	}
 	gpm_destroy(&pm_globals.packet_map);
-	// leave locked
+	/* leave locked */
 }
 
Index: uspace/lib/c/generic/net/socket_client.c
===================================================================
--- uspace/lib/c/generic/net/socket_client.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/generic/net/socket_client.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -220,5 +220,5 @@
 		fibril_rwlock_read_lock(&socket_globals.lock);
 
-		// find the socket
+		/* Find the socket */
 		socket = sockets_find(socket_get_sockets(),
 		    SOCKET_GET_SOCKET_ID(call));
@@ -232,10 +232,10 @@
 		case NET_SOCKET_RECEIVED:
 			fibril_mutex_lock(&socket->receive_lock);
-			// push the number of received packet fragments
+			/* Push the number of received packet fragments */
 			rc = dyn_fifo_push(&socket->received,
 			    SOCKET_GET_DATA_FRAGMENTS(call),
 			    SOCKET_MAX_RECEIVED_SIZE);
 			if (rc == EOK) {
-				// signal the received packet
+				/* Signal the received packet */
 				fibril_condvar_signal(&socket->receive_signal);
 			}
@@ -244,10 +244,10 @@
 
 		case NET_SOCKET_ACCEPTED:
-			// push the new socket identifier
+			/* Push the new socket identifier */
 			fibril_mutex_lock(&socket->accept_lock);
 			rc = dyn_fifo_push(&socket->accepted, 1,
 			    SOCKET_MAX_ACCEPTED_SIZE);
 			if (rc == EOK) {
-				// signal the accepted socket
+				/* Signal the accepted socket */
 				fibril_condvar_signal(&socket->accept_signal);
 			}
@@ -264,5 +264,5 @@
 			fibril_rwlock_write_lock(&socket->sending_lock);
 
-			// set the data fragment size
+			/* Set the data fragment size */
 			socket->data_fragment_size =
 			    SOCKET_GET_DATA_FRAGMENT_SIZE(call);
@@ -342,5 +342,5 @@
 			socket_id = 1;
 			++count;
-		// only this branch for last_id
+		/* Only this branch for last_id */
 		} else {
 			if (socket_id < INT_MAX) {
@@ -408,5 +408,5 @@
 	int rc;
 
-	// find the appropriate service
+	/* Find the appropriate service */
 	switch (domain) {
 	case PF_INET:
@@ -457,5 +457,5 @@
 		return phone;
 
-	// create a new socket structure
+	/* Create a new socket structure */
 	socket = (socket_t *) malloc(sizeof(socket_t));
 	if (!socket)
@@ -465,5 +465,5 @@
 	fibril_rwlock_write_lock(&socket_globals.lock);
 
-	// request a new socket
+	/* Request a new socket */
 	socket_id = socket_generate_new_id();
 	if (socket_id <= 0) {
@@ -484,7 +484,7 @@
 	socket->header_size = (size_t) header_size;
 
-	// finish the new socket initialization
+	/* Finish the new socket initialization */
 	socket_initialize(socket, socket_id, phone, service);
-	// store the new socket
+	/* Store the new socket */
 	rc = sockets_add(socket_get_sockets(), socket_id, socket);
 
@@ -531,5 +531,5 @@
 	fibril_rwlock_read_lock(&socket_globals.lock);
 
-	// find the socket
+	/* Find the socket */
 	socket = sockets_find(socket_get_sockets(), socket_id);
 	if (!socket) {
@@ -538,8 +538,8 @@
 	}
 
-	// request the message
+	/* Request the message */
 	message_id = async_send_3(socket->phone, message,
 	    (sysarg_t) socket->socket_id, arg2, socket->service, NULL);
-	// send the address
+	/* Send the address */
 	async_data_write_start(socket->phone, data, datalength);
 
@@ -566,5 +566,5 @@
 		return EINVAL;
 
-	// send the address
+	/* Send the address */
 	return socket_send_data(socket_id, NET_SOCKET_BIND, 0, my_addr,
 	    (size_t) addrlen);
@@ -591,5 +591,5 @@
 	fibril_rwlock_read_lock(&socket_globals.lock);
 
-	// find the socket
+	/* Find the socket */
 	socket = sockets_find(socket_get_sockets(), socket_id);
 	if (!socket) {
@@ -598,5 +598,5 @@
 	}
 
-	// request listen backlog change
+	/* Request listen backlog change */
 	result = (int) async_req_3_0(socket->phone, NET_SOCKET_LISTEN,
 	    (sysarg_t) socket->socket_id, (sysarg_t) backlog, socket->service);
@@ -634,5 +634,5 @@
 	fibril_rwlock_write_lock(&socket_globals.lock);
 
-	// find the socket
+	/* Find the socket */
 	socket = sockets_find(socket_get_sockets(), socket_id);
 	if (!socket) {
@@ -643,10 +643,10 @@
 	fibril_mutex_lock(&socket->accept_lock);
 
-	// wait for an accepted socket
+	/* Wait for an accepted socket */
 	++ socket->blocked;
 	while (dyn_fifo_value(&socket->accepted) <= 0) {
 		fibril_rwlock_write_unlock(&socket_globals.lock);
 		fibril_condvar_wait(&socket->accept_signal, &socket->accept_lock);
-		// drop the accept lock to avoid deadlock
+		/* Drop the accept lock to avoid deadlock */
 		fibril_mutex_unlock(&socket->accept_lock);
 		fibril_rwlock_write_lock(&socket_globals.lock);
@@ -655,5 +655,5 @@
 	-- socket->blocked;
 
-	// create a new scoket
+	/* Create a new socket */
 	new_socket = (socket_t *) malloc(sizeof(socket_t));
 	if (!new_socket) {
@@ -681,10 +681,10 @@
 	}
 
-	// request accept
+	/* Request accept */
 	message_id = async_send_5(socket->phone, NET_SOCKET_ACCEPT,
 	    (sysarg_t) socket->socket_id, 0, socket->service, 0,
 	    new_socket->socket_id, &answer);
 
-	// read address
+	/* Read address */
 	ipc_data_read_start(socket->phone, cliaddr, *addrlen);
 	fibril_rwlock_write_unlock(&socket_globals.lock);
@@ -695,12 +695,12 @@
 			result = EINVAL;
 
-		// dequeue the accepted socket if successful
+		/* Dequeue the accepted socket if successful */
 		dyn_fifo_pop(&socket->accepted);
-		// set address length
+		/* Set address length */
 		*addrlen = SOCKET_GET_ADDRESS_LENGTH(answer);
 		new_socket->data_fragment_size =
 		    SOCKET_GET_DATA_FRAGMENT_SIZE(answer);
 	} else if (result == ENOTSOCK) {
-		// empty the queue if no accepted sockets
+		/* Empty the queue if no accepted sockets */
 		while (dyn_fifo_pop(&socket->accepted) > 0)
 			;
@@ -731,5 +731,5 @@
 		return EDESTADDRREQ;
 
-	// send the address
+	/* Send the address */
 	return socket_send_data(socket_id, NET_SOCKET_CONNECT, 0, serv_addr,
 	    addrlen);
@@ -744,5 +744,5 @@
 	int accepted_id;
 
-	// destroy all accepted sockets
+	/* Destroy all accepted sockets */
 	while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0)
 		socket_destroy(sockets_find(socket_get_sockets(), accepted_id));
@@ -780,5 +780,5 @@
 	}
 
-	// request close
+	/* Request close */
 	rc = (int) async_req_3_0(socket->phone, NET_SOCKET_CLOSE,
 	    (sysarg_t) socket->socket_id, 0, socket->service);
@@ -787,5 +787,5 @@
 		return rc;
 	}
-	// free the socket structure
+	/* Free the socket structure */
 	socket_destroy(socket);
 
@@ -833,5 +833,5 @@
 	fibril_rwlock_read_lock(&socket_globals.lock);
 
-	// find socket
+	/* Find socket */
 	socket = sockets_find(socket_get_sockets(), socket_id);
 	if (!socket) {
@@ -842,5 +842,5 @@
 	fibril_rwlock_read_lock(&socket->sending_lock);
 
-	// compute data fragment count
+	/* Compute data fragment count */
 	if (socket->data_fragment_size > 0) {
 		fragments = (datalength + socket->header_size) /
@@ -853,5 +853,5 @@
 	}
 
-	// request send
+	/* Request send */
 	message_id = async_send_5(socket->phone, message,
 	    (sysarg_t) socket->socket_id,
@@ -859,12 +859,12 @@
 	    socket->service, (sysarg_t) flags, fragments, &answer);
 
-	// send the address if given
+	/* Send the address if given */
 	if (!toaddr ||
 	    (async_data_write_start(socket->phone, toaddr, addrlen) == EOK)) {
 		if (fragments == 1) {
-			// send all if only one fragment
+			/* Send all if only one fragment */
 			async_data_write_start(socket->phone, data, datalength);
 		} else {
-			// send the first fragment
+			/* Send the first fragment */
 			async_data_write_start(socket->phone, data,
 			    socket->data_fragment_size - socket->header_size);
@@ -872,5 +872,5 @@
 			    socket->data_fragment_size - socket->header_size;
 	
-			// send the middle fragments
+			/* Send the middle fragments */
 			while (--fragments > 1) {
 				async_data_write_start(socket->phone, data,
@@ -880,5 +880,5 @@
 			}
 
-			// send the last fragment
+			/* Send the last fragment */
 			async_data_write_start(socket->phone, data,
 			    (datalength + socket->header_size) %
@@ -892,5 +892,5 @@
 	    (SOCKET_GET_DATA_FRAGMENT_SIZE(answer) !=
 	    socket->data_fragment_size)) {
-		// set the data fragment size
+		/* Set the data fragment size */
 		socket->data_fragment_size =
 		    SOCKET_GET_DATA_FRAGMENT_SIZE(answer);
@@ -917,5 +917,5 @@
 int send(int socket_id, void *data, size_t datalength, int flags)
 {
-	// without the address
+	/* Without the address */
 	return sendto_core(NET_SOCKET_SEND, socket_id, data, datalength, flags,
 	    NULL, 0);
@@ -950,5 +950,5 @@
 		return EDESTADDRREQ;
 
-	// with the address
+	/* With the address */
 	return sendto_core(NET_SOCKET_SENDTO, socket_id, data, datalength,
 	    flags, toaddr, addrlen);
@@ -966,5 +966,6 @@
  *			read. The actual address length is set. Used only if
  *			fromaddr is not NULL.
- * @return		EOK on success.
+ * @return		Positive received message size in bytes on success.
+ * @return		Zero if no more data (other side closed the connection).
  * @return		ENOTSOCK if the socket is not found.
  * @return		EBADMEM if the data parameter is NULL.
@@ -972,5 +973,5 @@
  * @return		Other error codes as defined for the spcific message.
  */
-static int
+static ssize_t
 recvfrom_core(sysarg_t message, int socket_id, void *data, size_t datalength,
     int flags, struct sockaddr *fromaddr, socklen_t *addrlen)
@@ -984,4 +985,5 @@
 	size_t index;
 	ipc_call_t answer;
+	ssize_t retval;
 
 	if (!data)
@@ -996,5 +998,5 @@
 	fibril_rwlock_read_lock(&socket_globals.lock);
 
-	// find the socket
+	/* Find the socket */
 	socket = sockets_find(socket_get_sockets(), socket_id);
 	if (!socket) {
@@ -1004,12 +1006,12 @@
 
 	fibril_mutex_lock(&socket->receive_lock);
-	// wait for a received packet
+	/* Wait for a received packet */
 	++socket->blocked;
-	while ((result = dyn_fifo_value(&socket->received)) <= 0) {
+	while ((result = dyn_fifo_value(&socket->received)) < 0) {
 		fibril_rwlock_read_unlock(&socket_globals.lock);
 		fibril_condvar_wait(&socket->receive_signal,
 		    &socket->receive_lock);
 
-		// drop the receive lock to avoid deadlock
+		/* Drop the receive lock to avoid deadlock */
 		fibril_mutex_unlock(&socket->receive_lock);
 		fibril_rwlock_read_lock(&socket_globals.lock);
@@ -1019,5 +1021,12 @@
 	fragments = (size_t) result;
 
-	// prepare lengths if more fragments
+	if (fragments == 0) {
+		/* No more data, other side has closed the connection. */
+		fibril_mutex_unlock(&socket->receive_lock);
+		fibril_rwlock_read_unlock(&socket_globals.lock);
+		return 0;
+	}
+
+	/* Prepare lengths if more fragments */
 	if (fragments > 1) {
 		lengths = (size_t *) malloc(sizeof(size_t) * fragments +
@@ -1029,19 +1038,19 @@
 		}
 
-		// request packet data
+		/* Request packet data */
 		message_id = async_send_4(socket->phone, message,
 		    (sysarg_t) socket->socket_id, 0, socket->service,
 		    (sysarg_t) flags, &answer);
 
-		// read the address if desired
+		/* Read the address if desired */
 		if(!fromaddr ||
 		    (async_data_read_start(socket->phone, fromaddr,
 		    *addrlen) == EOK)) {
-			// read the fragment lengths
+			/* Read the fragment lengths */
 			if (async_data_read_start(socket->phone, lengths,
 			    sizeof(int) * (fragments + 1)) == EOK) {
 				if (lengths[fragments] <= datalength) {
 
-					// read all fragments if long enough
+					/* Read all fragments if long enough */
 					for (index = 0; index < fragments;
 					    ++index) {
@@ -1057,15 +1066,15 @@
 
 		free(lengths);
-	} else {
-		// request packet data
+	} else { /* fragments == 1 */
+		/* Request packet data */
 		message_id = async_send_4(socket->phone, message,
 		    (sysarg_t) socket->socket_id, 0, socket->service,
 		    (sysarg_t) flags, &answer);
 
-		// read the address if desired
+		/* Read the address if desired */
 		if (!fromaddr ||
 		    (async_data_read_start(socket->phone, fromaddr,
 		        *addrlen) == EOK)) {
-			// read all if only one fragment
+			/* Read all if only one fragment */
 			async_data_read_start(socket->phone, data, datalength);
 		}
@@ -1075,16 +1084,18 @@
 	result = (int) ipc_result;
 	if (result == EOK) {
-		// dequeue the received packet
+		/* Dequeue the received packet */
 		dyn_fifo_pop(&socket->received);
-		// return read data length
-		result = SOCKET_GET_READ_DATA_LENGTH(answer);
-		// set address length
+		/* Return read data length */
+		retval = SOCKET_GET_READ_DATA_LENGTH(answer);
+		/* Set address length */
 		if (fromaddr && addrlen)
 			*addrlen = SOCKET_GET_ADDRESS_LENGTH(answer);
+	} else {
+		retval = (ssize_t) result;
 	}
 
 	fibril_mutex_unlock(&socket->receive_lock);
 	fibril_rwlock_read_unlock(&socket_globals.lock);
-	return result;
+	return retval;
 }
 
@@ -1095,5 +1106,6 @@
  * @param[in] datalength The data length.
  * @param[in] flags	Various receive flags.
- * @return		EOK on success.
+ * @return		Positive received message size in bytes on success.
+ * @return		Zero if no more data (other side closed the connection).
  * @return		ENOTSOCK if the socket is not found.
  * @return		EBADMEM if the data parameter is NULL.
@@ -1102,7 +1114,7 @@
  *			message.
  */
-int recv(int socket_id, void *data, size_t datalength, int flags)
-{
-	// without the address
+ssize_t recv(int socket_id, void *data, size_t datalength, int flags)
+{
+	/* Without the address */
 	return recvfrom_core(NET_SOCKET_RECV, socket_id, data, datalength,
 	    flags, NULL, NULL);
@@ -1118,5 +1130,6 @@
  * @param[in,out] addrlen The address length. The maximum address length is
  *			read. The actual address length is set.
- * @return		EOK on success.
+ * @return		Positive received message size in bytes on success.
+ * @return		Zero if no more data (other side closed the connection).
  * @return		ENOTSOCK if the socket is not found.
  * @return		EBADMEM if the data or fromaddr parameter is NULL.
@@ -1125,5 +1138,5 @@
  *			message.
  */
-int
+ssize_t
 recvfrom(int socket_id, void *data, size_t datalength, int flags,
     struct sockaddr *fromaddr, socklen_t *addrlen)
@@ -1135,5 +1148,5 @@
 		return NO_DATA;
 
-	// with the address
+	/* With the address */
 	return recvfrom_core(NET_SOCKET_RECVFROM, socket_id, data, datalength,
 	    flags, fromaddr, addrlen);
@@ -1170,5 +1183,5 @@
 	fibril_rwlock_read_lock(&socket_globals.lock);
 
-	// find the socket
+	/* Find the socket */
 	socket = sockets_find(socket_get_sockets(), socket_id);
 	if (!socket) {
@@ -1177,13 +1190,13 @@
 	}
 
-	// request option value
+	/* Request option value */
 	message_id = async_send_3(socket->phone, NET_SOCKET_GETSOCKOPT,
 	    (sysarg_t) socket->socket_id, (sysarg_t) optname, socket->service,
 	    NULL);
 
-	// read the length
+	/* Read the length */
 	if (async_data_read_start(socket->phone, optlen,
 	    sizeof(*optlen)) == EOK) {
-		// read the value
+		/* Read the value */
 		async_data_read_start(socket->phone, value, *optlen);
 	}
@@ -1212,5 +1225,5 @@
     size_t optlen)
 {
-	// send the value
+	/* Send the value */
 	return socket_send_data(socket_id, NET_SOCKET_SETSOCKOPT,
 	    (sysarg_t) optname, value, optlen);
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/generic/task.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -65,9 +65,20 @@
  *
  * @return Zero on success or negative error code.
- *
  */
 int task_set_name(const char *name)
 {
 	return __SYSCALL2(SYS_TASK_SET_NAME, (sysarg_t) name, str_size(name));
+}
+
+/** Kill a task.
+ *
+ * @param task_id ID of task to kill.
+ *
+ * @return Zero on success or negative error code.
+ */
+
+int task_kill(task_id_t task_id)
+{
+	return (int) __SYSCALL1(SYS_TASK_KILL, (sysarg_t) &task_id);
 }
 
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/include/async.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -37,4 +37,5 @@
 
 #include <ipc/ipc.h>
+#include <async_sess.h>
 #include <fibril.h>
 #include <sys/time.h>
Index: pace/lib/c/include/async_rel.h
===================================================================
--- uspace/lib/c/include/async_rel.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2010 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ASYNC_REL_H_
-#define LIBC_ASYNC_REL_H_
-
-extern int async_rel_init(void);
-extern int async_relation_create(int);
-extern void async_relation_destroy(int, int);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/async_sess.h
===================================================================
--- uspace/lib/c/include/async_sess.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/lib/c/include/async_sess.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ASYNC_SESS_H_
+#define LIBC_ASYNC_SESS_H_
+
+#include <adt/list.h>
+
+typedef struct {
+	int sess_phone;		/**< Phone for cloning off the connections. */
+	link_t conn_head;	/**< List of open data connections. */
+	link_t sess_link;	/**< Link in global list of open sessions. */
+} async_sess_t;
+
+extern void _async_sess_init(void);
+extern void async_session_create(async_sess_t *, int);
+extern void async_session_destroy(async_sess_t *);
+extern int async_exchange_begin(async_sess_t *);
+extern void async_exchange_end(async_sess_t *, int);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -39,4 +39,6 @@
 	CHAR_DEV_IFACE,
 
+	/** Interface provided by any USB device. */
+	USB_DEV_IFACE,
 	/** Interface provided by USB host controller. */
 	USBHC_DEV_IFACE,
Index: uspace/lib/c/include/net/socket.h
===================================================================
--- uspace/lib/c/include/net/socket.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/include/net/socket.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -60,6 +60,6 @@
 extern int sendto(int, const void *, size_t, int, const struct sockaddr *,
     socklen_t);
-extern int recv(int, void *, size_t, int);
-extern int recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *);
+extern ssize_t recv(int, void *, size_t, int);
+extern ssize_t recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *);
 extern int getsockopt(int, int, int, void *, size_t *);
 extern int setsockopt(int, int, int, const void *, size_t);
Index: uspace/lib/c/include/task.h
===================================================================
--- uspace/lib/c/include/task.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/c/include/task.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -47,4 +47,6 @@
 extern task_id_t task_get_id(void);
 extern int task_set_name(const char *);
+extern int task_kill(task_id_t);
+
 extern task_id_t task_spawn(const char *, const char *const[], int *);
 extern int task_spawnv(task_id_t *, const char *path, const char *const []);
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/drv/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -36,4 +36,5 @@
 	generic/dev_iface.c \
 	generic/remote_res.c \
+	generic/remote_usb.c \
 	generic/remote_usbhc.c \
 	generic/remote_char.c
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/drv/generic/dev_iface.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -39,4 +39,5 @@
 #include "remote_res.h"
 #include "remote_char.h"
+#include "remote_usb.h"
 #include "remote_usbhc.h"
 
@@ -45,4 +46,5 @@
 		&remote_res_iface,
 		&remote_char_iface,
+		&remote_usb_iface,
 		&remote_usbhc_iface
 	}
Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/lib/drv/generic/remote_usb.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/ipc.h>
+#include <async.h>
+#include <errno.h>
+
+#include "usb_iface.h"
+#include "driver.h"
+
+
+static void remote_usb_get_hc_handle(device_t *, void *, ipc_callid_t, ipc_call_t *);
+//static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);
+
+/** Remote USB interface operations. */
+static remote_iface_func_ptr_t remote_usb_iface_ops [] = {
+	remote_usb_get_hc_handle
+};
+
+/** Remote USB interface structure.
+ */
+remote_iface_t remote_usb_iface = {
+	.method_count = sizeof(remote_usb_iface_ops) /
+	    sizeof(remote_usb_iface_ops[0]),
+	.methods = remote_usb_iface_ops
+};
+
+
+void remote_usb_get_hc_handle(device_t *device, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (usb_iface->get_hc_handle == NULL) {
+		ipc_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	devman_handle_t handle;
+	int rc = usb_iface->get_hc_handle(device, &handle);
+	if (rc != EOK) {
+		ipc_answer_0(callid, rc);
+	}
+
+	ipc_answer_1(callid, EOK, (sysarg_t) handle);
+}
+
+
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -59,5 +59,5 @@
 //static void remote_usbhc(device_t *, void *, ipc_callid_t, ipc_call_t *);
 
-/** Remote USB interface operations. */
+/** Remote USB host controller interface operations. */
 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
 	remote_usbhc_get_address,
@@ -84,5 +84,5 @@
 };
 
-/** Remote USB interface structure.
+/** Remote USB host controller interface structure.
  */
 remote_iface_t remote_usbhc_iface = {
Index: uspace/lib/drv/include/remote_usb.h
===================================================================
--- uspace/lib/drv/include/remote_usb.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/lib/drv/include/remote_usb.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_USB_H_
+#define LIBDRV_REMOTE_USB_H_
+
+remote_iface_t remote_usb_iface;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/usb_iface.h
===================================================================
--- uspace/lib/drv/include/usb_iface.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/lib/drv/include/usb_iface.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv usb
+ * @{
+ */
+/** @file
+ * @brief USB interface definition.
+ */
+
+#ifndef LIBDRV_USB_IFACE_H_
+#define LIBDRV_USB_IFACE_H_
+
+#include "driver.h"
+#include <usb/usb.h>
+typedef enum {
+	/** Tell devman handle of device host controller.
+	 * Parameters:
+	 * - none
+	 * Answer:
+	 * - EOK - request processed without errors
+	 * - ENOTSUP - this indicates invalid USB driver
+	 * Parameters of the answer:
+	 * - devman handle of HC caller is physically connected to
+	 */
+	IPC_M_USB_GET_HOST_CONTROLLER_HANDLE
+} usb_iface_funcs_t;
+
+/** USB device communication interface. */
+typedef struct {
+	int (*get_hc_handle)(device_t *, devman_handle_t *);
+} usb_iface_t;
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief USB interface definition.
+ * @brief USB host controller interface definition.
  */
 
@@ -226,5 +226,5 @@
     usbhc_iface_transfer_in_callback_t, void *);
 
-/** USB devices communication interface. */
+/** USB host controller communication interface. */
 typedef struct {
 	int (*tell_address)(device_t *, devman_handle_t, usb_address_t *);
Index: uspace/lib/usb/include/usb/usbdrv.h
===================================================================
--- uspace/lib/usb/include/usb/usbdrv.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/usb/include/usb/usbdrv.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -41,5 +41,7 @@
 #include <usb/descriptor.h>
 
-int usb_drv_hc_connect(device_t *, unsigned int);
+int usb_drv_find_hc(device_t *, devman_handle_t *);
+int usb_drv_hc_connect(device_t *, devman_handle_t, unsigned int);
+int usb_drv_hc_connect_auto(device_t *, unsigned int);
 
 int usb_drv_reserve_default_address(int);
Index: uspace/lib/usb/src/hcdhubd.c
===================================================================
--- uspace/lib/usb/src/hcdhubd.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/usb/src/hcdhubd.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -36,4 +36,5 @@
 #include <usb/devreq.h>
 #include <usbhc_iface.h>
+#include <usb_iface.h>
 #include <usb/descriptor.h>
 #include <driver.h>
@@ -45,4 +46,33 @@
 #include "hcdhubd_private.h"
 
+
+static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
+{
+	assert(dev);
+	assert(dev->parent != NULL);
+
+	device_t *parent = dev->parent;
+
+	if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
+		usb_iface_t *usb_iface
+		    = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
+		assert(usb_iface != NULL);
+		if (usb_iface->get_hc_handle) {
+			int rc = usb_iface->get_hc_handle(parent, handle);
+			return rc;
+		}
+	}
+
+	return ENOTSUP;
+}
+
+static usb_iface_t usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle
+};
+
+static device_ops_t child_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface
+};
+
 /** Callback when new device is detected and must be handled by this driver.
  *
@@ -129,4 +159,6 @@
 	}
 	child->name = child_info->name;
+	child->parent = child_info->parent;
+	child->ops = &child_ops;
 
 	match_id = create_match_id();
Index: uspace/lib/usb/src/recognise.c
===================================================================
--- uspace/lib/usb/src/recognise.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/usb/src/recognise.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -33,4 +33,5 @@
  * @brief Functions for recognising kind of attached devices.
  */
+#include <usb_iface.h>
 #include <usb/usbdrv.h>
 #include <usb/classes/classes.h>
@@ -38,4 +39,31 @@
 #include <errno.h>
 
+static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
+{
+	assert(dev);
+	assert(dev->parent != NULL);
+
+	device_t *parent = dev->parent;
+
+	if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
+		usb_iface_t *usb_iface
+		    = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
+		assert(usb_iface != NULL);
+		if (usb_iface->get_hc_handle) {
+			int rc = usb_iface->get_hc_handle(parent, handle);
+			return rc;
+		}
+	}
+
+	return ENOTSUP;
+}
+
+static usb_iface_t usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle
+};
+
+static device_ops_t child_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface
+};
 
 #define BCD_INT(a) (((unsigned int)(a)) / 256)
@@ -285,5 +313,7 @@
 		goto failure;
 	}
+	child->parent = parent;
 	child->name = child_name;
+	child->ops = &child_ops;
 	
 	rc = usb_drv_create_device_match_ids(hc, &child->match_ids, address);
Index: uspace/lib/usb/src/usbdrv.c
===================================================================
--- uspace/lib/usb/src/usbdrv.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/lib/usb/src/usbdrv.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -35,4 +35,5 @@
 #include <usb/usbdrv.h>
 #include <usbhc_iface.h>
+#include <usb_iface.h>
 #include <errno.h>
 #include <str_error.h>
@@ -54,4 +55,53 @@
 } transfer_info_t;
 
+/** Find handle of host controller the device is physically attached to.
+ *
+ * @param[in] dev Device looking for its host controller.
+ * @param[out] handle Host controller devman handle.
+ * @return Error code.
+ */
+int usb_drv_find_hc(device_t *dev, devman_handle_t *handle)
+{
+	if (dev == NULL) {
+		return EBADMEM;
+	}
+	if (handle == NULL) {
+		return EBADMEM;
+	}
+
+	int parent_phone = devman_parent_device_connect(dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	devman_handle_t h;
+	int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
+
+	ipc_hangup(parent_phone);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	*handle = h;
+
+	return EOK;
+}
+
+/** Connect to host controller the device is physically attached to.
+ *
+ * @param dev Device asking for connection.
+ * @param hc_handle Devman handle of the host controller.
+ * @param flags Connection flags (blocking connection).
+ * @return Phone to the HC or error code.
+ */
+int usb_drv_hc_connect(device_t *dev, devman_handle_t hc_handle,
+    unsigned int flags)
+{
+	return devman_device_connect(hc_handle, flags);
+}
+
 /** Connect to host controller the device is physically attached to.
  *
@@ -60,24 +110,18 @@
  * @return Phone to corresponding HC or error code.
  */
-int usb_drv_hc_connect(device_t *dev, unsigned int flags)
-{
+int usb_drv_hc_connect_auto(device_t *dev, unsigned int flags)
+{
+	int rc;
+	devman_handle_t hc_handle;
+
 	/*
 	 * Call parent hub to obtain device handle of respective HC.
 	 */
-
-	/*
-	 * FIXME: currently we connect always to virtual host controller.
-	 */
-	int rc;
-	devman_handle_t handle;
-
-	rc = devman_device_get_handle("/virt/usbhc", &handle, flags);
+	rc = usb_drv_find_hc(dev, &hc_handle);
 	if (rc != EOK) {
 		return rc;
 	}
 	
-	int phone = devman_device_connect(handle, flags);
-
-	return phone;
+	return usb_drv_hc_connect(dev, hc_handle, flags);
 }
 
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -65,4 +65,5 @@
 #include <macros.h>
 
+#include "ata_hw.h"
 #include "ata_bd.h"
 
@@ -70,4 +71,7 @@
 #define NAMESPACE  "bd"
 
+/** Number of defined legacy controller base addresses. */
+#define LEGACY_CTLS 4
+
 /** Physical block size. Should be always 512. */
 static const size_t block_size = 512;
@@ -77,7 +81,15 @@
 
 /** I/O base address of the command registers. */
-static uintptr_t cmd_physical = 0x1f0;
+static uintptr_t cmd_physical;
 /** I/O base address of the control registers. */
-static uintptr_t ctl_physical = 0x170;
+static uintptr_t ctl_physical;
+
+/** I/O base addresses for legacy (ISA-compatible) controllers. */
+static ata_base_t legacy_base[LEGACY_CTLS] = {
+	{ 0x1f0, 0x3f0 },
+	{ 0x170, 0x370 },
+	{ 0x1e8, 0x3e8 },
+	{ 0x168, 0x368 }
+};
 
 static ata_cmd_t *cmd;
@@ -87,4 +99,5 @@
 static disk_t disk[MAX_DISKS];
 
+static void print_syntax(void);
 static int ata_bd_init(void);
 static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
@@ -110,9 +123,25 @@
 	int i, rc;
 	int n_disks;
+	unsigned ctl_num;
+	char *eptr;
 
 	printf(NAME ": ATA disk driver\n");
 
-	printf("I/O address %p/%p\n", (void *) ctl_physical,
-	    (void *) cmd_physical);
+	if (argc > 1) {
+		ctl_num = strtoul(argv[1], &eptr, 0);
+		if (*eptr != '\0' || ctl_num == 0 || ctl_num > 4) {
+			printf("Invalid argument.\n");
+			print_syntax();
+			return -1;
+		}
+	} else {
+		ctl_num = 1;
+	}
+
+	cmd_physical = legacy_base[ctl_num - 1].cmd;
+	ctl_physical = legacy_base[ctl_num - 1].ctl;
+
+	printf("I/O address %p/%p\n", (void *) cmd_physical,
+	    (void *) ctl_physical);
 
 	if (ata_bd_init() != EOK)
@@ -139,5 +168,5 @@
 			continue;
 		
-		snprintf(name, 16, "%s/disk%d", NAMESPACE, i);
+		snprintf(name, 16, "%s/ata%udisk%d", NAMESPACE, ctl_num, i);
 		rc = devmap_device_register(name, &disk[i].devmap_handle);
 		if (rc != EOK) {
@@ -160,4 +189,11 @@
 	/* Not reached */
 	return 0;
+}
+
+
+static void print_syntax(void)
+{
+	printf("Syntax: " NAME " <controller_number>\n");
+	printf("Controller number = 1..4\n");
 }
 
Index: uspace/srv/bd/ata_bd/ata_bd.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/bd/ata_bd/ata_bd.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -30,5 +30,5 @@
  * @{
  */
-/** @file
+/** @file ATA driver definitions.
  */
 
@@ -40,102 +40,9 @@
 #include <str.h>
 
-enum {
-	CTL_READ_START  = 0,
-	CTL_WRITE_START = 1,
-};
-
-enum {
-	STATUS_FAILURE = 0
-};
-
-enum {
-	MAX_DISKS	= 2
-};
-
-/** ATA Command Register Block. */
-typedef union {
-	/* Read/Write */
-	struct {
-		uint16_t data_port;
-		uint8_t sector_count;
-		uint8_t sector_number;
-		uint8_t cylinder_low;
-		uint8_t cylinder_high;
-		uint8_t drive_head;
-		uint8_t pad_rw0;		
-	};
-
-	/* Read Only */
-	struct {
-		uint8_t pad_ro0;
-		uint8_t error;
-		uint8_t pad_ro1[5];
-		uint8_t status;
-	};
-
-	/* Write Only */
-	struct {
-		uint8_t pad_wo0;
-		uint8_t features;
-		uint8_t pad_wo1[5];
-		uint8_t command;
-	};
-} ata_cmd_t;
-
-typedef union {
-	/* Read */
-	struct {
-		uint8_t pad0[6];
-		uint8_t alt_status;
-		uint8_t drive_address;
-	};
-
-	/* Write */
-	struct {
-		uint8_t pad1[6];
-		uint8_t device_control;
-		uint8_t pad2;
-	};
-} ata_ctl_t;
-
-enum devctl_bits {
-	DCR_SRST	= 0x04, /**< Software Reset */
-	DCR_nIEN	= 0x02  /**< Interrupt Enable (negated) */
-};
-
-enum status_bits {
-	SR_BSY		= 0x80, /**< Busy */
-	SR_DRDY		= 0x40, /**< Drive Ready */
-	SR_DWF		= 0x20, /**< Drive Write Fault */
-	SR_DSC		= 0x10, /**< Drive Seek Complete */
-	SR_DRQ		= 0x08, /**< Data Request */
-	SR_CORR		= 0x04, /**< Corrected Data */
-	SR_IDX		= 0x02, /**< Index */
-	SR_ERR		= 0x01  /**< Error */
-};
-
-enum drive_head_bits {
-	DHR_LBA		= 0x40,	/**< Use LBA addressing mode */
-	DHR_DRV		= 0x10	/**< Select device 1 */
-};
-
-enum error_bits {
-	ER_BBK		= 0x80, /**< Bad Block Detected */
-	ER_UNC		= 0x40, /**< Uncorrectable Data Error */
-	ER_MC		= 0x20, /**< Media Changed */
-	ER_IDNF		= 0x10, /**< ID Not Found */
-	ER_MCR		= 0x08, /**< Media Change Request */
-	ER_ABRT		= 0x04, /**< Aborted Command */
-	ER_TK0NF	= 0x02, /**< Track 0 Not Found */
-	ER_AMNF		= 0x01  /**< Address Mark Not Found */
-};
-
-enum ata_command {
-	CMD_READ_SECTORS	= 0x20,
-	CMD_READ_SECTORS_EXT	= 0x24,
-	CMD_WRITE_SECTORS	= 0x30,
-	CMD_WRITE_SECTORS_EXT	= 0x34,
-	CMD_IDENTIFY_DRIVE	= 0xEC
-};
+/** Base addresses for ATA I/O blocks. */
+typedef struct {
+	uintptr_t cmd;	/**< Command block base address. */
+	uintptr_t ctl;	/**< Control block base address. */
+} ata_base_t;
 
 /** Timeout definitions. Unit is 10 ms. */
@@ -144,93 +51,4 @@
 	TIMEOUT_BSY	=  100, /*  1 s */
 	TIMEOUT_DRDY	= 1000  /* 10 s */
-};
-
-/** Data returned from @c identify command. */
-typedef struct {
-	uint16_t gen_conf;
-	uint16_t cylinders;
-	uint16_t _res2;
-	uint16_t heads;
-	uint16_t _vs4;
-	uint16_t _vs5;
-	uint16_t sectors;
-	uint16_t _vs7;
-	uint16_t _vs8;
-	uint16_t _vs9;
-
-	uint16_t serial_number[10];
-	uint16_t _vs20;
-	uint16_t _vs21;
-	uint16_t vs_bytes;
-	uint16_t firmware_rev[4];
-	uint16_t model_name[20];
-
-	uint16_t max_rw_multiple;
-	uint16_t _res48;
-	uint16_t caps;
-	uint16_t _res50;
-	uint16_t pio_timing;
-	uint16_t dma_timing;
-
-	uint16_t validity;
-	uint16_t cur_cyl;
-	uint16_t cur_heads;
-	uint16_t cur_sectors;
-	uint16_t cur_capacity0;
-	uint16_t cur_capacity1;
-	uint16_t mss;
-	uint16_t total_lba28_0;
-	uint16_t total_lba28_1;
-	uint16_t sw_dma;
-	uint16_t mw_dma;
-	uint16_t pio_modes;
-	uint16_t min_mw_dma_cycle;
-	uint16_t rec_mw_dma_cycle;
-	uint16_t min_raw_pio_cycle;
-	uint16_t min_iordy_pio_cycle;
-
-	uint16_t _res69;
-	uint16_t _res70;
-	uint16_t _res71;
-	uint16_t _res72;
-	uint16_t _res73;
-	uint16_t _res74;
-
-	uint16_t queue_depth;
-	uint16_t _res76[1 + 79 - 76];
-	uint16_t version_maj;
-	uint16_t version_min;
-	uint16_t cmd_set0;
-	uint16_t cmd_set1;
-	uint16_t csf_sup_ext;
-	uint16_t csf_enabled0;
-	uint16_t csf_enabled1;
-	uint16_t csf_default;
-	uint16_t udma;
-
-	uint16_t _res89[1 + 99 - 89];
-
-	/* Total number of blocks in LBA-48 addressing */
-	uint16_t total_lba48_0;
-	uint16_t total_lba48_1;
-	uint16_t total_lba48_2;
-	uint16_t total_lba48_3;
-
-	/* Note: more fields are defined in ATA/ATAPI-7 */
-	uint16_t _res104[1 + 127 - 104];
-	uint16_t _vs128[1 + 159 - 128];
-	uint16_t _res160[1 + 255 - 160];
-} identify_data_t;
-
-enum ata_caps {
-	cap_iordy	= 0x0800,
-	cap_iordy_cbd	= 0x0400,
-	cap_lba		= 0x0200,
-	cap_dma		= 0x0100
-};
-
-/** Bits of @c identify_data_t.cmd_set1 */
-enum ata_cs1 {
-	cs1_addr48	= 0x0400	/**< 48-bit address feature set */
 };
 
@@ -269,4 +87,5 @@
 } block_coord_t;
 
+/** ATA device state structure. */
 typedef struct {
 	bool present;
Index: uspace/srv/bd/ata_bd/ata_hw.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_hw.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/srv/bd/ata_bd/ata_hw.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup bd
+ * @{
+ */
+/** @file ATA hardware protocol (registers, data structures).
+ */
+
+#ifndef __ATA_HW_H__
+#define __ATA_HW_H__
+
+#include <sys/types.h>
+
+enum {
+	CTL_READ_START  = 0,
+	CTL_WRITE_START = 1,
+};
+
+enum {
+	STATUS_FAILURE = 0
+};
+
+enum {
+	MAX_DISKS	= 2
+};
+
+/** ATA Command Register Block. */
+typedef union {
+	/* Read/Write */
+	struct {
+		uint16_t data_port;
+		uint8_t sector_count;
+		uint8_t sector_number;
+		uint8_t cylinder_low;
+		uint8_t cylinder_high;
+		uint8_t drive_head;
+		uint8_t pad_rw0;
+	};
+
+	/* Read Only */
+	struct {
+		uint8_t pad_ro0;
+		uint8_t error;
+		uint8_t pad_ro1[5];
+		uint8_t status;
+	};
+
+	/* Write Only */
+	struct {
+		uint8_t pad_wo0;
+		uint8_t features;
+		uint8_t pad_wo1[5];
+		uint8_t command;
+	};
+} ata_cmd_t;
+
+typedef union {
+	/* Read */
+	struct {
+		uint8_t pad0[6];
+		uint8_t alt_status;
+		uint8_t drive_address;
+	};
+
+	/* Write */
+	struct {
+		uint8_t pad1[6];
+		uint8_t device_control;
+		uint8_t pad2;
+	};
+} ata_ctl_t;
+
+enum devctl_bits {
+	DCR_SRST	= 0x04, /**< Software Reset */
+	DCR_nIEN	= 0x02  /**< Interrupt Enable (negated) */
+};
+
+enum status_bits {
+	SR_BSY		= 0x80, /**< Busy */
+	SR_DRDY		= 0x40, /**< Drive Ready */
+	SR_DWF		= 0x20, /**< Drive Write Fault */
+	SR_DSC		= 0x10, /**< Drive Seek Complete */
+	SR_DRQ		= 0x08, /**< Data Request */
+	SR_CORR		= 0x04, /**< Corrected Data */
+	SR_IDX		= 0x02, /**< Index */
+	SR_ERR		= 0x01  /**< Error */
+};
+
+enum drive_head_bits {
+	DHR_LBA		= 0x40,	/**< Use LBA addressing mode */
+	DHR_DRV		= 0x10	/**< Select device 1 */
+};
+
+enum error_bits {
+	ER_BBK		= 0x80, /**< Bad Block Detected */
+	ER_UNC		= 0x40, /**< Uncorrectable Data Error */
+	ER_MC		= 0x20, /**< Media Changed */
+	ER_IDNF		= 0x10, /**< ID Not Found */
+	ER_MCR		= 0x08, /**< Media Change Request */
+	ER_ABRT		= 0x04, /**< Aborted Command */
+	ER_TK0NF	= 0x02, /**< Track 0 Not Found */
+	ER_AMNF		= 0x01  /**< Address Mark Not Found */
+};
+
+enum ata_command {
+	CMD_READ_SECTORS	= 0x20,
+	CMD_READ_SECTORS_EXT	= 0x24,
+	CMD_WRITE_SECTORS	= 0x30,
+	CMD_WRITE_SECTORS_EXT	= 0x34,
+	CMD_IDENTIFY_DRIVE	= 0xEC
+};
+
+/** Data returned from @c identify command. */
+typedef struct {
+	uint16_t gen_conf;
+	uint16_t cylinders;
+	uint16_t _res2;
+	uint16_t heads;
+	uint16_t _vs4;
+	uint16_t _vs5;
+	uint16_t sectors;
+	uint16_t _vs7;
+	uint16_t _vs8;
+	uint16_t _vs9;
+
+	uint16_t serial_number[10];
+	uint16_t _vs20;
+	uint16_t _vs21;
+	uint16_t vs_bytes;
+	uint16_t firmware_rev[4];
+	uint16_t model_name[20];
+
+	uint16_t max_rw_multiple;
+	uint16_t _res48;
+	uint16_t caps;
+	uint16_t _res50;
+	uint16_t pio_timing;
+	uint16_t dma_timing;
+
+	uint16_t validity;
+	uint16_t cur_cyl;
+	uint16_t cur_heads;
+	uint16_t cur_sectors;
+	uint16_t cur_capacity0;
+	uint16_t cur_capacity1;
+	uint16_t mss;
+	uint16_t total_lba28_0;
+	uint16_t total_lba28_1;
+	uint16_t sw_dma;
+	uint16_t mw_dma;
+	uint16_t pio_modes;
+	uint16_t min_mw_dma_cycle;
+	uint16_t rec_mw_dma_cycle;
+	uint16_t min_raw_pio_cycle;
+	uint16_t min_iordy_pio_cycle;
+
+	uint16_t _res69;
+	uint16_t _res70;
+	uint16_t _res71;
+	uint16_t _res72;
+	uint16_t _res73;
+	uint16_t _res74;
+
+	uint16_t queue_depth;
+	uint16_t _res76[1 + 79 - 76];
+	uint16_t version_maj;
+	uint16_t version_min;
+	uint16_t cmd_set0;
+	uint16_t cmd_set1;
+	uint16_t csf_sup_ext;
+	uint16_t csf_enabled0;
+	uint16_t csf_enabled1;
+	uint16_t csf_default;
+	uint16_t udma;
+
+	uint16_t _res89[1 + 99 - 89];
+
+	/* Total number of blocks in LBA-48 addressing */
+	uint16_t total_lba48_0;
+	uint16_t total_lba48_1;
+	uint16_t total_lba48_2;
+	uint16_t total_lba48_3;
+
+	/* Note: more fields are defined in ATA/ATAPI-7 */
+	uint16_t _res104[1 + 127 - 104];
+	uint16_t _vs128[1 + 159 - 128];
+	uint16_t _res160[1 + 255 - 160];
+} identify_data_t;
+
+enum ata_caps {
+	cap_iordy	= 0x0800,
+	cap_iordy_cbd	= 0x0400,
+	cap_lba		= 0x0200,
+	cap_dma		= 0x0100
+};
+
+/** Bits of @c identify_data_t.cmd_set1 */
+enum ata_cs1 {
+	cs1_addr48	= 0x0400	/**< 48-bit address feature set */
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/devman/main.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -458,6 +458,7 @@
 	
 	if (driver == NULL) {
-		printf(NAME ": devman_forward error - the device is not in %" PRIun
-		    " usable state.\n", handle);
+		printf(NAME ": devman_forward error - the device %" PRIun \
+		    " (%s) is not in usable state.\n",
+		    handle, dev->pathname);
 		ipc_answer_0(iid, ENOENT);
 		return;
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/hid/console/console.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -741,4 +741,62 @@
 }
 
+/** Try to connect to given keyboard, bypassing provided libc routines.
+ *
+ * @param devmap_path Path to keyboard without /dev prefix.
+ * @return Phone or error code.
+ */
+static int connect_keyboard_bypass(char *devmap_path)
+{
+	int devmap_phone = async_connect_me_to_blocking(PHONE_NS,
+	    SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
+	if (devmap_phone < 0) {
+		return devmap_phone;
+	}
+	ipc_call_t answer;
+	aid_t req = async_send_2(devmap_phone, DEVMAP_DEVICE_GET_HANDLE,
+	    0, 0,  &answer);
+
+	sysarg_t retval = async_data_write_start(devmap_phone,
+	    devmap_path, str_size(devmap_path));
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		ipc_hangup(devmap_phone);
+		return retval;
+	}
+
+	async_wait_for(req, &retval);
+
+	if (retval != EOK) {
+		ipc_hangup(devmap_phone);
+		return retval;
+	}
+
+	devmap_handle_t handle = (devmap_handle_t) IPC_GET_ARG1(answer);
+
+	ipc_hangup(devmap_phone);
+
+	int phone = async_connect_me_to(PHONE_NS,
+	    SERVICE_DEVMAP, DEVMAP_CONNECT_TO_DEVICE, handle);
+	if (phone < 0) {
+		return phone;
+	}
+
+	/* NB: The callback connection is slotted for removal */
+	sysarg_t phonehash;
+	int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, SERVICE_CONSOLE,
+	    0, 0, NULL, NULL, NULL, NULL, &phonehash);
+	if (rc != EOK) {
+		printf(NAME ": Failed to create callback from input device\n");
+		return rc;
+	}
+
+	async_new_connection(phonehash, 0, NULL, keyboard_events);
+
+	printf(NAME ": we got a hit (new keyboard \"/dev/%s\").\n",
+	    devmap_path);
+
+	return phone;
+}
+
 
 static int check_new_keyboards(void *arg)
@@ -751,10 +809,10 @@
 		async_usleep(1 * 500 * 1000);
 		char *path;
-		int rc = asprintf(&path, "/dev/class/%s\\%d", class_name, index);
+		int rc = asprintf(&path, "class/%s\\%d", class_name, index);
 		if (rc < 0) {
 			continue;
 		}
 		rc = 0;
-		rc = connect_keyboard(path);
+		rc = connect_keyboard_bypass(path);
 		if (rc > 0) {
 			/* We do not allow unplug. */
Index: uspace/srv/hw/netif/dp8390/Makefile
===================================================================
--- uspace/srv/hw/netif/dp8390/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/hw/netif/dp8390/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -39,8 +39,4 @@
 -include $(CONFIG_MAKEFILE)
 
-ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
-	LIBS += $(USPACE_PREFIX)/srv/net/nil/eth/libeth.a
-endif
-
 BINARY = dp8390
 
Index: uspace/srv/hw/netif/dp8390/dp8390.c
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/hw/netif/dp8390/dp8390.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -1,17 +1,23 @@
 /*
- * 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
+ * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@@ -20,7 +26,14 @@
  * (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
+ */
+
+/*
+ * This code is based upon the NE2000 driver for MINIX,
+ * distributed according to a BSD-style license.
+ *
+ * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
+ * Copyright (c) 1992, 1994 Philip Homburg
+ * Copyright (c) 1996 G. Falzoni
+ *
  */
 
@@ -36,472 +49,229 @@
 #include <byteorder.h>
 #include <errno.h>
-
 #include <netif_local.h>
 #include <net/packet.h>
+#include <nil_interface.h>
 #include <packet_client.h>
-
 #include "dp8390_drv.h"
 #include "dp8390_port.h"
-
-/*
- * 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.
- *  @return EOK on success.
- *  @return EINVAL 
- */
-int queue_packet(dpeth_t * dep, packet_t *packet);
-
-/** Reads a memory block byte by byte.
+#include "ne2000.h"
+
+/** Read a memory block byte by byte.
+ *
  *  @param[in] port The source address.
  *  @param[out] buf The destination buffer.
  *  @param[in] size The memory block size in bytes.
+ *
  */
 static void outsb(port_t port, void * buf, size_t size);
 
-/** Reads a memory block word by word.
+/** Read a memory block word by word.
+ *
  *  @param[in] port The source address.
  *  @param[out] buf The destination buffer.
  *  @param[in] size The memory block size in bytes.
+ *
  */
 static void outsw(port_t port, void * buf, size_t size);
 
-//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
+/*
+ * 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){
+ * genuine dp8390s.
+ */
+#define CR_EXTRA  CR_STA
+
+static void dp_init(dpeth_t *dep);
+static void dp_reinit(dpeth_t *dep);
+static void dp_reset(dpeth_t *dep);
+static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep);
+static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length);
+static void conf_hw(dpeth_t *dep);
+static void insb(port_t port, void *buf, size_t size);
+static void insw(port_t port, void *buf, size_t size);
+
+int do_probe(dpeth_t *dep)
+{
 	/* This is the default, try to (re)locate the device. */
 	conf_hw(dep);
-	if (dep->de_mode == DEM_DISABLED)
-	{
+	if (!dep->up)
 		/* Probe failed, or the device is configured off. */
-		return EXDEV;//ENXIO;
-	}
-	if (dep->de_mode == DEM_ENABLED)
+		return EXDEV;
+	
+	if (dep->up)
 		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()
+/** Initialize and/or start the network interface.
+ *
+ *  @param[in,out] dep The network interface structure.
+ *
+ *  @return EOK on success.
+ *  @return EXDEV if the network interface is disabled.
+ *
+ */
+int do_init(dpeth_t *dep)
+{
+	if (!dep->up)
+		/* FIXME: Perhaps call do_probe()? */
 		return EXDEV;
-	}
-
-	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;
+	
+	assert(dep->up);
+	assert(dep->enabled);
+	
 	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)){
+void do_stop(dpeth_t *dep)
+{
+	if ((dep->up) && (dep->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;
+		ne_stop(dep);
+		
+		dep->enabled = false;
+		dep->stopped = false;
+		dep->sending = false;
+		dep->send_avail = false;
+	}
+}
+
+static void dp_user2nic(dpeth_t *dep, void *buf, size_t offset, int nic_addr, size_t size)
+{
+	size_t ecount = size & ~1;
+	
+	outb_reg0(dep, DP_ISR, ISR_RDC);
+	
+	if (dep->de_16bit) {
+		outb_reg0(dep, DP_RBCR0, ecount & 0xff);
+		outb_reg0(dep, DP_RBCR1, ecount >> 8);
+	} else {
+		outb_reg0(dep, DP_RBCR0, size & 0xff);
+		outb_reg0(dep, DP_RBCR1, size >> 8);
+	}
+	
+	outb_reg0(dep, DP_RSAR0, nic_addr & 0xff);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+	
+	if (dep->de_16bit) {
+		void *ptr = buf + offset;
+		
+		if (ecount != 0) {
+			outsw(dep->de_data_port, ptr, ecount);
+			size -= ecount;
+			offset += ecount;
+			ptr += ecount;
+		}
+		
+		if (size) {
+			assert(size == 1);
+			
+			uint16_t two_bytes;
+			
+			memcpy(&(((uint8_t *) &two_bytes)[0]), ptr, 1);
+			outw(dep->de_data_port, two_bytes);
+		}
+	} else
+		outsb(dep->de_data_port, buf + offset, size);
+	
+	unsigned int i;
+	for (i = 0; i < 100; i++) {
+		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+			break;
+	}
+	
+	if (i == 100)
+		fprintf(stderr, "Remote DMA failed to complete\n");
+}
+
+int do_pwrite(dpeth_t *dep, packet_t *packet, int from_int)
+{
 	int size;
 	int sendq_head;
-/*	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;
-	}
-*/
+	
+	assert(dep->up);
+	assert(dep->enabled);
+	
+	if (dep->send_avail) {
+		fprintf(stderr, "Send already in progress\n");
+		return EBUSY;
+	}
+	
+	sendq_head = dep->de_sendq_head;
+	if (dep->de_sendq[sendq_head].sq_filled) {
+		if (from_int)
+			fprintf(stderr, "dp8390: should not be sending\n");
+		dep->send_avail = true;
+		dep->sending = false;
+		
+		return EBUSY;
+	}
+	
+	assert(!dep->sending);
+	
+	void *buf = packet_get_data(packet);
 	size = packet_get_data_length(packet);
-	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 = (uintptr_t) NULL;
-
-	if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
-	{
-		panic("", "dp8390: invalid packet size", size);
+	
+	if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) {
+		fprintf(stderr, "dp8390: invalid packet size\n");
 		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)
-	{
+	
+	dp_user2nic(dep, buf, 0, dep->de_sendq[sendq_head].sq_sendpage
+	    * DP_PAGESIZE, size);
+	dep->de_sendq[sendq_head].sq_filled = true;
+	
+	if (dep->de_sendq_tail == sendq_head) {
 		outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
 		outb_reg0(dep, DP_TBCR1, size >> 8);
-		outb_reg0(dep, DP_TBCR0, size &0xff);
-		outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
-	}
-	else
-		dep->de_sendq[sendq_head].sq_size= size;
+		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;
+		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. 
-	 */
+	dep->de_sendq_head = sendq_head;
+	dep->sending = true;
+	
 	if (from_int)
 		return EOK;
-	reply(dep, OK, FALSE);
-
-	assert(dep->de_mode == DEM_ENABLED);
-	assert(dep->de_flags &DEF_ENABLED);
+	
+	dep->sending = false;
+	
 	return EOK;
 }
 
-/*===========================================================================*
- *				dp_init					     *
- *===========================================================================*/
-void dp_init(dep)
-dpeth_t *dep;
+void dp_init(dpeth_t *dep)
 {
 	int dp_rcr_reg;
-	int i;//, r;
-
+	int i;
+	
 	/* 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
+	dep->enabled = false;
+	dep->stopped = false;
+	dep->sending = false;
+	dep->send_avail = false;
+	ne_init(dep);
+	
+	printf("Ethernet address ");
+	for (i = 0; i < 6; i++)
+		printf("%x%c", dep->de_address.ea_addr[i], i < 5 ? ':' : '\n');
+	
+	/*
+	 * Initialization of the dp8390 following the mandatory procedure
 	 * in reference manual ("DP8390D/NS32490D NIC Network Interface
 	 * Controller", National Semiconductor, July 1995, Page 29).
 	 */
+	
 	/* Step 1: */
 	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
+	
 	/* Step 2: */
 	if (dep->de_16bit)
@@ -509,30 +279,32 @@
 	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;
+	dp_rcr_reg = RCR_AB;  /* Enable broadcasts */
+	
 	outb_reg0(dep, DP_RCR, dp_rcr_reg);
+	
 	/* Step 5: */
 	outb_reg0(dep, DP_TCR, TCR_INTERNAL);
+	
 	/* Step 6: */
 	outb_reg0(dep, DP_BNRY, dep->de_startpage);
 	outb_reg0(dep, DP_PSTART, dep->de_startpage);
 	outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
+	
 	/* Step 7: */
 	outb_reg0(dep, DP_ISR, 0xFF);
+	
 	/* Step 8: */
 	outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
-		IMR_OVWE | IMR_CNTE);
+	    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]);
@@ -541,5 +313,5 @@
 	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);
@@ -550,1081 +322,340 @@
 	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_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->enabled = true;
+	for (i = 0; i < dep->de_sendq_nr; i++)
 		dep->de_sendq[i].sq_filled= 0;
-	dep->de_sendq_head= 0;
-	dep->de_sendq_tail= 0;
-	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;
+	
+	dep->de_sendq_head = 0;
+	dep->de_sendq_tail = 0;
+}
+
+static void dp_reinit(dpeth_t *dep)
 {
 	int dp_rcr_reg;
-
+	
 	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
-
-	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;
+	
+	/* Enable broadcasts */
+	dp_rcr_reg = RCR_AB;
+	
 	outb_reg0(dep, DP_RCR, dp_rcr_reg);
 }
 
-/*===========================================================================*
- *				dp_reset				     *
- *===========================================================================*/
-static void dp_reset(dep)
-dpeth_t *dep;
+static void dp_reset(dpeth_t *dep)
 {
 	int i;
-
+	
 	/* Stop chip */
 	outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
 	outb_reg0(dep, DP_RBCR0, 0);
 	outb_reg0(dep, DP_RBCR1, 0);
-	for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RST) == 0); i++)
+	
+	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_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++)
+	
+	/* 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
+	
+	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;
+	dep->de_sendq_head = 0;
+	dep->de_sendq_tail = 0;
+	
+	for (i = 0; i < dep->de_sendq_nr; i++)
+		dep->de_sendq[i].sq_filled = 0;
+	
+	dep->send_avail = false;
+	dep->stopped = false;
+}
+
+static uint8_t isr_acknowledge(dpeth_t *dep)
+{
+	uint8_t isr = inb_reg0(dep, DP_ISR);
+	if (isr != 0)
+		outb_reg0(dep, DP_ISR, isr);
+	
+	return isr;
+}
+
+void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, uint8_t isr)
+{
+	int tsr;
 	int size, sendq_tail;
-
-	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
+	
+	for (; (isr & 0x7f) != 0; isr = isr_acknowledge(dep)) {
+		if (isr & (ISR_PTX | ISR_TXE)) {
+			if (isr & ISR_TXE)
 				dep->de_stat.ets_sendErr++;
+			else {
+				tsr = inb_reg0(dep, DP_TSR);
+				
+				if (tsr & TSR_PTX)
+					dep->de_stat.ets_packetT++;
+				
+				if (tsr & TSR_COL)
+					dep->de_stat.ets_collision++;
+				
+				if (tsr & TSR_ABT)
+					dep->de_stat.ets_transAb++;
+				
+				if (tsr & TSR_CRS)
+					dep->de_stat.ets_carrSense++;
+				
+				if ((tsr & TSR_FU) && (++dep->de_stat.ets_fifoUnder <= 10))
+					printf("FIFO underrun\n");
+				
+				if ((tsr & TSR_CDH) && (++dep->de_stat.ets_CDheartbeat <= 10))
+					printf("CD heart beat failure\n");
+				
+				if (tsr & TSR_OWC)
+					dep->de_stat.ets_OWC++;
 			}
-			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);
+			
+			sendq_tail = dep->de_sendq_tail;
+			
+			if (!(dep->de_sendq[sendq_tail].sq_filled)) {
+				printf("PTX interrupt, but no frame to send\n");
 				continue;
 			}
-			dep->de_sendq[sendq_tail].sq_filled= 0;
+			
+			dep->de_sendq[sendq_tail].sq_filled = false;
+			
 			if (++sendq_tail == dep->de_sendq_nr)
-				sendq_tail= 0;
-			dep->de_sendq_tail= sendq_tail;
-			if (dep->de_sendq[sendq_tail].sq_filled)
-			{
-				size= dep->de_sendq[sendq_tail].sq_size;
+				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);
+				    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_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->send_avail = false;
+		}
+		
+		if (isr & ISR_PRX)
+			dp_recv(nil_phone, device_id, dep);
+		
+		if (isr & ISR_RXE)
+			dep->de_stat.ets_recvErr++;
+		
+		if (isr & ISR_CNT) {
 			dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
 			dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
 			dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
 		}
-		if (isr &ISR_OVW)
-		{
+		
+		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)
-		{
+		
+		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,
+		
+		if (isr & ISR_RST) {
+			/*
+			 * This means we got an interrupt but the ethernet
+			 * chip is shutdown. We set the flag 'stopped'
 			 * and continue processing arrived packets. When the
 			 * receive buffer is empty, we reset the dp8390.
 			 */
-#if 0
-			 {printW(); printf(
-				"%s: NIC stopped\n", dep->de_name);}
-#endif
-			dep->de_flags |= DEF_STOPPED;
+			dep->stopped = true;
 			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.
+	}
+	
+	if (dep->stopped) {
+		/*
+		 * The chip is stopped, and all arrived
+		 * frames are delivered.
 		 */
 		dp_reset(dep);
 	}
-}
-
-/*===========================================================================*
- *				dp_recv					     *
- *===========================================================================*/
-static void dp_recv(dep)
-dpeth_t *dep;
+	
+	dep->sending = false;
+}
+
+static void dp_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst)
+{
+	offset = page * DP_PAGESIZE + offset;
+	
+	outb_reg0(dep, DP_RBCR0, size & 0xff);
+	outb_reg0(dep, DP_RBCR1, size >> 8);
+	outb_reg0(dep, DP_RSAR0, offset & 0xff);
+	outb_reg0(dep, DP_RSAR1, offset >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+	
+	if (dep->de_16bit) {
+		assert((size % 2) == 0);
+		insw(dep->de_data_port, dst, size);
+	} else
+		insb(dep->de_data_port, dst, size);
+}
+
+static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep)
 {
 	dp_rcvhdr_t header;
-	//unsigned pageno, curr, next;
 	int pageno, curr, next;
-	vir_bytes length;
+	size_t length;
 	int packet_processed, r;
-	u16_t eth_type;
-
-	packet_processed = FALSE;
+	uint16_t eth_type;
+	
+	packet_processed = false;
 	pageno = inb_reg0(dep, DP_BNRY) + 1;
-	if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
-
-	do
-	{
+	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);
+		
+		if (curr == pageno)
+			break;
+		
+		dp_getblock(dep, pageno, (size_t) 0, sizeof(header), &header);
+		dp_getblock(dep, pageno, sizeof(header) +
+		    2 * sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
+		
+		length = (header.dr_rbcl | (header.dr_rbch << 8)) - sizeof(dp_rcvhdr_t);
 		next = header.dr_next;
-		if (length < ETH_MIN_PACK_SIZE ||
-			length > ETH_MAX_PACK_SIZE_TAGGED)
-		{
-			printf("%s: packet with strange length arrived: %d\n",
-				dep->de_name, (int) length);
+		if ((length < ETH_MIN_PACK_SIZE) || (length > ETH_MAX_PACK_SIZE_TAGGED)) {
+			printf("Packet with strange length arrived: %zu\n", length);
 			next= curr;
-		}
-		else if (next < dep->de_startpage || next >= dep->de_stoppage)
-		{
-			printf("%s: strange next page\n", dep->de_name);
+		} else if ((next < dep->de_startpage) || (next >= dep->de_stoppage)) {
+			printf("Strange next page\n");
 			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.)
+		} else if (header.dr_status & RSR_FO) {
+			/*
+			 * This is very serious, so we issue a warning and
+			 * reset the buffers
 			 */
-/*			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);
+			printf("FIFO overrun, resetting receive buffer\n");
 			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)
+		} else if ((header.dr_status & RSR_PRX) && (dep->enabled)) {
+			r = dp_pkt2user(nil_phone, device_id, dep, pageno, length);
+			if (r != EOK)
 				return;
-
-			packet_processed = TRUE;
+			
+			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);
+	} while (!packet_processed);
+}
+
+static void dp_nic2user(dpeth_t *dep, int nic_addr, void *buf, size_t offset, size_t size)
+{
+	size_t ecount = size & ~1;
+	
+	if (dep->de_16bit) {
+		outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
+		outb_reg0(dep, DP_RBCR1, ecount >> 8);
+	} else {
+		outb_reg0(dep, DP_RBCR0, size & 0xff);
+		outb_reg0(dep, DP_RBCR1, size >> 8);
+	}
+	
+	outb_reg0(dep, DP_RSAR0, nic_addr & 0xff);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
 	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-
-	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;
+	
+	if (dep->de_16bit) {
+		void *ptr = buf + offset;
+		
+		if (ecount != 0) {
+			insw(dep->de_data_port, ptr, ecount);
+			size -= ecount;
+			offset += ecount;
+			ptr += ecount;
+		}
+		
+		if (size) {
+			assert(size == 1);
+			
+			uint16_t two_bytes = inw(dep->de_data_port);
+			memcpy(ptr, &(((uint8_t *) &two_bytes)[0]), 1);
+		}
+	} else
+		insb(dep->de_data_port, buf + offset, size);
+}
+
+static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length)
 {
 	int last, count;
 	packet_t *packet;
-
-//	if (!(dep->de_flags &DEF_READING))
-//		return EGENERIC;
-
+	
 	packet = netif_packet_get_1(length);
-	if(! packet){
+	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 = (uintptr_t) NULL;
-
+	
+	void *buf = packet_suffix(packet, length);
+	
 	last = page + (length - 1) / DP_PAGESIZE;
-	if (last >= dep->de_stoppage)
-	{
-		count = (dep->de_stoppage - page) * DP_PAGESIZE -
-			sizeof(dp_rcvhdr_t);
-
-		/* 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 %#lx\n",
-		    dep->de_name, dep->de_base_port);
-		dep->de_mode= DEM_DISABLED;
+	if (last >= dep->de_stoppage) {
+		count = (dep->de_stoppage - page) * DP_PAGESIZE - sizeof(dp_rcvhdr_t);
+		
+		dp_nic2user(dep, page * DP_PAGESIZE + sizeof(dp_rcvhdr_t),
+		    buf, 0, count);
+		dp_nic2user(dep, dep->de_startpage * DP_PAGESIZE,
+		    buf, count, length - count);
+	} else {
+		dp_nic2user(dep, page * DP_PAGESIZE + sizeof(dp_rcvhdr_t),
+		    buf, 0, length);
+	}
+	
+	nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE);
+	
+	return EOK;
+}
+
+static void conf_hw(dpeth_t *dep)
+{
+	if (!ne_probe(dep)) {
+		printf("No ethernet card found at %#lx\n", dep->de_base_port);
+		dep->up = false;
 		return;
 	}
-
-/* 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);
+	
+	dep->up = true;
+	dep->enabled = false;
+	dep->stopped = false;
+	dep->sending = false;
+	dep->send_avail = false;
 }
 
@@ -1632,8 +663,7 @@
 {
 	size_t i;
-
-	for(i = 0; i < size; ++ i){
+	
+	for (i = 0; i < size; i++)
 		*((uint8_t *) buf + i) = inb(port);
-	}
 }
 
@@ -1641,8 +671,7 @@
 {
 	size_t i;
-
-	for(i = 0; i * 2 < size; ++ i){
+	
+	for (i = 0; i * 2 < size; i++)
 		*((uint16_t *) buf + i) = inw(port);
-	}
 }
 
@@ -1650,8 +679,7 @@
 {
 	size_t i;
-
-	for(i = 0; i < size; ++ i){
+	
+	for (i = 0; i < size; i++)
 		outb(port, *((uint8_t *) buf + i));
-	}
 }
 
@@ -1659,13 +687,8 @@
 {
 	size_t i;
-
-	for(i = 0; i * 2 < size; ++ 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 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/hw/netif/dp8390/dp8390.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -1,17 +1,23 @@
 /*
- * 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
+ * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@@ -20,7 +26,14 @@
  * (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
+ */
+
+/*
+ * This code is based upon the NE2000 driver for MINIX,
+ * distributed according to a BSD-style license.
+ *
+ * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
+ * Copyright (c) 1992, 1994 Philip Homburg
+ * Copyright (c) 1996 G. Falzoni
+ *
  */
 
@@ -37,73 +50,58 @@
 
 #include <net/packet.h>
-
 #include "dp8390_port.h"
-#include "local.h"
-
-/** Input/output size.
- */
-#define DP8390_IO_SIZE	0x020
-
-/*
-dp8390.h
-
-Created:	before Dec 28, 1992 by Philip Homburg
-*/
+
+/** Input/output size */
+#define DP8390_IO_SIZE  0x0020
 
 /* 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      */
+/** Page 0, for reading */
+#define DP_CR     0x00  /**< Command Register */
+#define DP_CLDA0  0x01  /**< Current Local DMA Address 0 */
+#define DP_CLDA1  0x02  /**< Current Local DMA Address 1 */
+#define DP_BNRY   0x03  /**< Boundary Pointer */
+#define DP_TSR    0x04  /**< Transmit Status Register */
+#define DP_NCR    0x05  /**< Number of Collisions Register */
+#define DP_FIFO   0x06  /**< FIFO */
+#define DP_ISR    0x07  /**< Interrupt Status Register */
+#define DP_CRDA0  0x08  /**< Current Remote DMA Address 0 */
+#define DP_CRDA1  0x09  /**< Current Remote DMA Address 1 */
+#define DP_RSR    0x0c  /**< Receive Status Register */
+#define DP_CNTR0  0x0d  /**< Tally Counter 0 */
+#define DP_CNTR1  0x0e  /**< Tally Counter 1 */
+#define DP_CNTR2  0x0f  /**< Tally Counter 2 */
+
+/** Page 0, for writing */
+#define DP_PSTART  0x01  /**< Page Start Register*/
+#define DP_PSTOP   0x02  /**< Page Stop Register */
+#define DP_TPSR    0x04  /**< Transmit Page Start Register */
+#define DP_TBCR0   0x05  /**< Transmit Byte Count Register 0 */
+#define DP_TBCR1   0x06  /**< Transmit Byte Count Register 1 */
+#define DP_RSAR0   0x08  /**< Remote Start Address Register 0 */
+#define DP_RSAR1   0x09  /**< Remote Start Address Register 1 */
+#define DP_RBCR0   0x0a  /**< Remote Byte Count Register 0 */
+#define DP_RBCR1   0x0b  /**< Remote Byte Count Register 1 */
+#define DP_RCR     0x0c  /**< Receive Configuration Register */
+#define DP_TCR     0x0d  /**< Transmit Configuration Register */
+#define DP_DCR     0x0e  /**< Data Configuration Register */
+#define DP_IMR     0x0f  /**< Interrupt Mask Register */
+
+/** Page 1, read/write */
+#define DP_PAR0  0x01  /**< Physical Address Register 0 */
+#define DP_PAR1  0x02  /**< Physical Address Register 1 */
+#define DP_PAR2  0x03  /**< Physical Address Register 2 */
+#define DP_PAR3  0x04  /**< Physical Address Register 3 */
+#define DP_PAR4  0x05  /**< Physical Address Register 4 */
+#define DP_PAR5  0x06  /**< Physical Address Register 5 */
+#define DP_CURR  0x07  /**< Current Page Register */
+#define DP_MAR0  0x08  /**< Multicast Address Register 0 */
+#define DP_MAR1  0x09  /**< Multicast Address Register 1 */
+#define DP_MAR2  0x0a  /**< Multicast Address Register 2 */
+#define DP_MAR3  0x0b  /**< Multicast Address Register 3 */
+#define DP_MAR4  0x0c  /**< Multicast Address Register 4 */
+#define DP_MAR5  0x0d  /**< Multicast Address Register 5 */
+#define DP_MAR6  0x0e  /**< Multicast Address Register 6 */
+#define DP_MAR7  0x0f  /**< Multicast Address Register 7 */
 
 /* Bits in dp_cr */
@@ -199,154 +197,65 @@
 #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;
+/** Type definition of the receive header
+ *
+ */
+typedef struct dp_rcvhdr {
+	/** Copy of rsr */
+	uint8_t dr_status;
+	
+	/** Pointer to next packet */
+	uint8_t dr_next;
+	
+	/** Receive Byte Count Low */
+	uint8_t dr_rbcl;
+	
+	/** Receive Byte Count High */
+	uint8_t dr_rbch;
 } dp_rcvhdr_t;
 
-/** Page size.
- */
-#define DP_PAGESIZE	256
-
-/* Some macros to simplify accessing the dp8390 */
-/** Reads 1 byte from the zero page register.
+/** Page size */
+#define DP_PAGESIZE  256
+
+/** Read 1 byte from the zero page register.
  *  @param[in] dep The network interface structure.
  *  @param[in] reg The register offset.
  *  @returns The read value.
  */
-#define inb_reg0(dep, reg)		(inb(dep->de_dp8390_port+reg))
-
-/** Writes 1 byte zero page register.
+#define inb_reg0(dep, reg)  (inb(dep->de_dp8390_port + reg))
+
+/** Write 1 byte zero page register.
  *  @param[in] dep The network interface structure.
  *  @param[in] reg The register offset.
  *  @param[in] data The value to be written.
  */
-#define outb_reg0(dep, reg, data)	(outb(dep->de_dp8390_port+reg, data))
-
-/** Reads 1 byte from the first page register.
+#define outb_reg0(dep, reg, data)  (outb(dep->de_dp8390_port + reg, data))
+
+/** Read 1 byte from the first page register.
  *  @param[in] dep The network interface structure.
  *  @param[in] reg The register offset.
  *  @returns The read value.
  */
-#define inb_reg1(dep, reg)		(inb(dep->de_dp8390_port+reg))
-
-/** Writes 1 byte first page register.
+#define inb_reg1(dep, reg)  (inb(dep->de_dp8390_port + reg))
+
+/** Write 1 byte first page register.
  *  @param[in] dep The network interface structure.
  *  @param[in] reg The register offset.
  *  @param[in] data The value to be written.
  */
-#define outb_reg1(dep, reg, data)	(outb(dep->de_dp8390_port+reg, data))
-
-/* 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
+#define outb_reg1(dep, reg, data)  (outb(dep->de_dp8390_port + reg, data))
+
+#define SENDQ_NR     2  /* Maximum size of the send queue */
+#define SENDQ_PAGES  6  /* 6 * DP_PAGESIZE >= 1514 bytes */
+
+typedef struct dpeth {
+	/*
+	 * The de_base_port field is the starting point of the probe.
+	 * The conf routine also fills de_irq. If the probe
 	 * routine knows the irq and/or memory address because they are
 	 * hardwired in the board, the probe should modify these fields.
-	 * 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;
@@ -357,75 +266,29 @@
 	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;	
+	
+	/* Do it yourself send queue */
+	struct sendq {
+		int sq_filled;    /* this buffer contains a packet */
+		int sq_size;      /* with this size */
+		int sq_sendpage;  /* starting page of the buffer */
+	} de_sendq[SENDQ_NR];
+	
+	int de_sendq_nr;
+	int de_sendq_head;  /* Enqueue at the head */
+	int de_sendq_tail;  /* Dequeue at the tail */
+	
+	/* Fields for internal use by the dp8390 driver. */
+	eth_stat_t de_stat;
+	
+	/* Driver flags */
+	bool up;
+	bool enabled;
+	bool stopped;
+	bool sending;
+	bool send_avail;
+} dpeth_t;
+
 #endif
 
-	/* 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 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/hw/netif/dp8390/dp8390_drv.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -40,11 +40,5 @@
 #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);
+int do_init(dpeth_t *dep);
 
 /** Stops the network interface.
@@ -55,7 +49,6 @@
 /** 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);
+void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, uint8_t isr);
 
 /** Probes and initializes the network interface.
@@ -70,12 +63,7 @@
  *  @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 
+ *  @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 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/hw/netif/dp8390/dp8390_module.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -43,5 +43,4 @@
 #include <ipc/ipc.h>
 #include <ipc/services.h>
-
 #include <net/modules.h>
 #include <packet_client.h>
@@ -51,5 +50,4 @@
 #include <netif_interface.h>
 #include <netif_local.h>
-
 #include "dp8390.h"
 #include "dp8390_drv.h"
@@ -60,27 +58,43 @@
 #define NAME  "dp8390"
 
-/** Returns the device from the interrupt call.
+/** Return the device from the interrupt call.
+ *
  *  @param[in] call The interrupt call.
- */
-#define IRQ_GET_DEVICE(call)			(device_id_t) IPC_GET_IMETHOD(*call)
-
-/** Returns the interrupt status register from the interrupt call.
+ *
+ */
+#define IRQ_GET_DEVICE(call)  ((device_id_t) IPC_GET_IMETHOD(call))
+
+/** Return the ISR from the interrupt call.
+ *
  *  @param[in] call The interrupt call.
- */
-#define IPC_GET_ISR(call)				(int) IPC_GET_ARG2(*call)
+ *
+ */
+#define IRQ_GET_ISR(call)  ((int) IPC_GET_ARG2(call))
 
 /** DP8390 kernel interrupt command sequence.
  */
-static irq_cmd_t	dp8390_cmds[] = {
-	{	.cmd = CMD_PIO_READ_8,
+static irq_cmd_t dp8390_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
 		.addr = NULL,
 		.dstarg = 2
 	},
 	{
+		.cmd = CMD_BTEST,
+		.value = 0x7f,
+		.srcarg = 2,
+		.dstarg = 3,
+	},
+	{
 		.cmd = CMD_PREDICATE,
-		.value = 1,
-		.srcarg = 2
+		.value = 2,
+		.srcarg = 3
 	},
 	{
+		.cmd = CMD_PIO_WRITE_A_8,
+		.addr = NULL,
+		.srcarg = 3
+	},
+	{
 		.cmd = CMD_ACCEPT
 	}
@@ -89,5 +103,5 @@
 /** DP8390 kernel interrupt code.
  */
-static irq_code_t	dp8390_code = {
+static irq_code_t dp8390_code = {
 	sizeof(dp8390_cmds) / sizeof(irq_cmd_t),
 	dp8390_cmds
@@ -99,37 +113,25 @@
  *  @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);
+static void irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	device_id_t device_id = IRQ_GET_DEVICE(*call);
+	netif_device_t *device;
+	int nil_phone;
+	dpeth_t *dep;
+	
 	fibril_rwlock_write_lock(&netif_globals.lock);
-	if(find_device(device_id, &device) != EOK){
-		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, SERVICE_NONE);
-	}else{
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-	}
-	ipc_answer_0(iid, EOK);
+	
+	if (find_device(device_id, &device) == EOK) {
+		nil_phone = device->nil_phone;
+		dep = (dpeth_t *) device->specific;
+	} else
+		dep = NULL;
+	
+	fibril_rwlock_write_unlock(&netif_globals.lock);
+	
+	if ((dep != NULL) && (dep->up)) {
+		assert(dep->enabled);
+		dp_check_ints(nil_phone, device_id, dep, IRQ_GET_ISR(*call));
+	}
 }
 
@@ -139,5 +141,5 @@
  *  @returns The new state.
  */
-static int change_state(netif_device_t * device, device_state_t state)
+static int change_state(netif_device_t *device, device_state_t state)
 {
 	if (device->state != state) {
@@ -153,5 +155,7 @@
 }
 
-int netif_specific_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
+int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, int *answer_count)
+{
 	return ENOTSUP;
 }
@@ -162,12 +166,14 @@
 	eth_stat_t * de_stat;
 	int rc;
-
-	if(! stats){
+	
+	if (!stats)
 		return EBADMEM;
-	}
+	
 	rc = find_device(device_id, &device);
 	if (rc != EOK)
 		return rc;
+	
 	de_stat = &((dpeth_t *) device->specific)->de_stat;
+	
 	null_device_stats(stats);
 	stats->receive_errors = de_stat->ets_recvErr;
@@ -183,17 +189,20 @@
 	stats->send_heartbeat_errors = de_stat->ets_CDheartbeat;
 	stats->send_window_errors = de_stat->ets_OWC;
-	return EOK;
-}
-
-int netif_get_addr_message(device_id_t device_id, measured_string_t *address){
-	netif_device_t * device;
-	int rc;
-
-	if(! address){
+	
+	return EOK;
+}
+
+int netif_get_addr_message(device_id_t device_id, measured_string_t *address)
+{
+	netif_device_t *device;
+	int rc;
+	
+	if (!address)
 		return EBADMEM;
-	}
+	
 	rc = find_device(device_id, &device);
 	if (rc != EOK)
 		return rc;
+	
 	address->value = (char *) (&((dpeth_t *) device->specific)->de_address);
 	address->length = sizeof(ether_addr_t);
@@ -201,20 +210,20 @@
 }
 
-
-
-int netif_probe_message(device_id_t device_id, int irq, uintptr_t io){
-	netif_device_t * device;
-	dpeth_t * dep;
-	int rc;
-
+int netif_probe_message(device_id_t device_id, int irq, uintptr_t io)
+{
+	netif_device_t *device;
+	dpeth_t *dep;
+	int rc;
+	
 	device = (netif_device_t *) malloc(sizeof(netif_device_t));
-	if(! device){
+	if (!device)
 		return ENOMEM;
-	}
+	
 	dep = (dpeth_t *) malloc(sizeof(dpeth_t));
-	if(! dep){
+	if (!dep) {
 		free(device);
 		return ENOMEM;
 	}
+	
 	bzero(device, sizeof(netif_device_t));
 	bzero(dep, sizeof(dpeth_t));
@@ -224,5 +233,6 @@
 	device->state = NETIF_STOPPED;
 	dep->de_irq = irq;
-	dep->de_mode = DEM_DISABLED;
+	dep->up = false;
+	
 	//TODO address?
 	rc = pio_enable((void *) io, DP8390_IO_SIZE, (void **) &dep->de_base_port);
@@ -231,5 +241,6 @@
 		free(device);
 		return rc;
-	}	
+	}
+	
 	rc = do_probe(dep);
 	if (rc != EOK) {
@@ -238,63 +249,78 @@
 		return rc;
 	}
+	
 	rc = netif_device_map_add(&netif_globals.device_map, device->device_id, device);
-	if (rc != EOK){
+	if (rc != EOK) {
 		free(dep);
 		free(device);
 		return rc;
 	}
-	return EOK;
-}
-
-int netif_send_message(device_id_t device_id, packet_t *packet, services_t sender){
-	netif_device_t * device;
-	dpeth_t * dep;
+	
+	return EOK;
+}
+
+int netif_send_message(device_id_t device_id, packet_t *packet,
+    services_t sender)
+{
+	netif_device_t *device;
+	dpeth_t *dep;
 	packet_t *next;
 	int rc;
-
+	
 	rc = find_device(device_id, &device);
 	if (rc != EOK)
 		return rc;
-	if(device->state != NETIF_ACTIVE){
+	
+	if (device->state != NETIF_ACTIVE){
 		netif_pq_release(packet_get_id(packet));
 		return EFORWARD;
 	}
+	
 	dep = (dpeth_t *) device->specific;
-	// process packet queue
-	do{
+	
+	/* Process packet queue */
+	do {
 		next = pq_detach(packet);
-		if(do_pwrite(dep, packet, FALSE) != EBUSY){
+		
+		if (do_pwrite(dep, packet, false) != EBUSY)
 			netif_pq_release(packet_get_id(packet));
-		}
+		
 		packet = next;
-	}while(packet);
-	return EOK;
-}
-
-int netif_start_message(netif_device_t * device){
-	dpeth_t * dep;
-	int rc;
-
-	if(device->state != NETIF_ACTIVE){
+	} while (packet);
+	
+	return EOK;
+}
+
+int netif_start_message(netif_device_t * device)
+{
+	dpeth_t *dep;
+	int rc;
+	
+	if (device->state != NETIF_ACTIVE) {
 		dep = (dpeth_t *) device->specific;
 		dp8390_cmds[0].addr = (void *) (uintptr_t) (dep->de_dp8390_port + DP_ISR);
-		dp8390_cmds[2].addr = dp8390_cmds[0].addr;
+		dp8390_cmds[3].addr = dp8390_cmds[0].addr;
+		
 		rc = ipc_register_irq(dep->de_irq, device->device_id, device->device_id, &dp8390_code);
 		if (rc != EOK)
 			return rc;
-		rc = do_init(dep, DL_BROAD_REQ);
+		
+		rc = do_init(dep);
 		if (rc != EOK) {
 			ipc_unregister_irq(dep->de_irq, device->device_id);
 			return rc;
 		}
+		
 		return change_state(device, NETIF_ACTIVE);
 	}
-	return EOK;
-}
-
-int netif_stop_message(netif_device_t * device){
-	dpeth_t * dep;
-
-	if(device->state != NETIF_STOPPED){
+	
+	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);
@@ -302,12 +328,12 @@
 		return change_state(device, NETIF_STOPPED);
 	}
-	return EOK;
-}
-
-int netif_initialize(void){
+	
+	return EOK;
+}
+
+int netif_initialize(void)
+{
 	sysarg_t phonehash;
-
 	async_set_interrupt_received(irq_handler);
-
 	return ipc_connect_to_me(PHONE_NS, SERVICE_DP8390, 0, 0, &phonehash);
 }
@@ -319,5 +345,5 @@
  *
  */
-static void netif_client_connection(ipc_callid_t iid, ipc_call_t * icall)
+static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall)
 {
 	/*
@@ -327,5 +353,5 @@
 	ipc_answer_0(iid, EOK);
 	
-	while(true) {
+	while (true) {
 		ipc_call_t answer;
 		int answer_count;
@@ -351,5 +377,5 @@
 }
 
-/** Starts the module.
+/** Start the module.
  *
  *  @param argc The count of the command line arguments. Ignored parameter.
@@ -362,9 +388,6 @@
 int main(int argc, char *argv[])
 {
-	int rc;
-	
 	/* Start the module */
-	rc = netif_module_start(netif_client_connection);
-	return rc;
+	return netif_module_start(netif_client_connection);
 }
 
Index: uspace/srv/hw/netif/dp8390/dp8390_port.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_port.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/hw/netif/dp8390/dp8390_port.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -44,22 +44,4 @@
 #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.
@@ -70,5 +52,5 @@
  *  @returns 1 if the second is greater than the first.
  */
-#define memcmp(first, second, size)	bcmp((char *) (first), (char *) (second), (size))
+#define memcmp(first, second, size)  bcmp((char *) (first), (char *) (second), (size))
 
 /** Reads 1 byte.
@@ -76,5 +58,5 @@
  *  @returns The read value.
  */
-#define inb(port)	pio_read_8((ioport8_t *) (port))
+#define inb(port)  pio_read_8((ioport8_t *) (port))
 
 /** Reads 1 word (2 bytes).
@@ -82,5 +64,5 @@
  *  @returns The read value.
  */
-#define inw(port)	pio_read_16((ioport16_t *) (port))
+#define inw(port)  pio_read_16((ioport16_t *) (port))
 
 /** Writes 1 byte.
@@ -88,5 +70,5 @@
  *  @param[in] value The value to be written.
  */
-#define outb(port, value)	pio_write_8((ioport8_t *) (port), (value))
+#define outb(port, value)  pio_write_8((ioport8_t *) (port), (value))
 
 /** Writes 1 word (2 bytes).
@@ -94,86 +76,13 @@
  *  @param[in] value The value to be written.
  */
-#define outw(port, value)	pio_write_16((ioport16_t *) (port), (value))
+#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
-{
+typedef struct eth_stat {
 	/** Number of receive errors.
 	 */
@@ -226,46 +135,19 @@
 } eth_stat_t;
 
-/* errno.h */
-/** Generic error.
- */
-#define EGENERIC     EINVAL
-
-/* ether.h */
 /** Minimum Ethernet packet size in bytes.
  */
-#define ETH_MIN_PACK_SIZE		  60
+#define ETH_MIN_PACK_SIZE  60
 
 /** Maximum Ethernet packet size in bytes.
  */
-#define ETH_MAX_PACK_SIZE_TAGGED	1518
+#define ETH_MAX_PACK_SIZE_TAGGED  1518
 
 /** Ethernet address type definition.
  */
-typedef struct ether_addr
-{
+typedef struct ether_addr {
 	/** Address data.
 	 */
-	u8_t ea_addr[6];
+	uint8_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: pace/srv/hw/netif/dp8390/local.h
===================================================================
--- uspace/srv/hw/netif/dp8390/local.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ 	(revision )
@@ -1,99 +1,0 @@
-/*
- * 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 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/hw/netif/dp8390/ne2000.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -1,17 +1,23 @@
 /*
- * 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
+ * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@@ -20,7 +26,14 @@
  * (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
+ */
+
+/*
+ * This code is based upon the NE2000 driver for MINIX,
+ * distributed according to a BSD-style license.
+ *
+ * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
+ * Copyright (c) 1992, 1994 Philip Homburg
+ * Copyright (c) 1996 G. Falzoni
+ *
  */
 
@@ -35,60 +48,18 @@
 #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};
+/** Number of bytes to transfer */
+#define N  100
+
+typedef int (*testf_t)(dpeth_t *dep, int pos, uint8_t *pat);
+
+/** Data patterns */
+uint8_t pat0[] = {0x00, 0x00, 0x00, 0x00};
+uint8_t pat1[] = {0xFF, 0xFF, 0xFF, 0xFF};
+uint8_t pat2[] = {0xA5, 0x5A, 0x69, 0x96};
+uint8_t pat3[] = {0x96, 0x69, 0x5A, 0xA5};
 
 /** Tests 8 bit NE2000 network interface.
@@ -97,7 +68,7 @@
  *  @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);
+ *  @returns false otherwise.
+ */
+static int test_8(dpeth_t *dep, int pos, uint8_t *pat);
 
 /** Tests 16 bit NE2000 network interface.
@@ -106,24 +77,9 @@
  *  @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;
+ *  @returns false otherwise.
+ */
+static int test_16(dpeth_t *dep, int pos, uint8_t *pat);
+
+int ne_probe(dpeth_t *dep)
 {
 	int byte;
@@ -131,85 +87,73 @@
 	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
+	
+	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++)
-	{
+	
+	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);
+		usleep(2000);
 		outb_ne(dep, NE_RESET, byte);
-		milli_delay(2);
-
+		usleep(2000);
+		
 		/* Reset the dp8390 */
 		outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
-		for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RST) == 0); i++)
+		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))
-		{
+		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)
-		{
+		if (dep->de_16bit) {
 			outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
-				DCR_BMS);
+			    DCR_BMS);
+		} else {
+			outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | 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 (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;
+		
+		if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
+		    f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
+		    f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
+		    f(dep, loc2, pat2) && f(dep, loc2, pat3)) {
 			return 1;
 		}
 	}
+	
 	return 0;
 }
 
-/*===========================================================================*
- *				ne_init					     *
- *===========================================================================*/
-void ne_init(dep)
-dpeth_t *dep;
+/** Initializes the NE2000 network interface.
+ *
+ *  @param[in,out] dep The network interface structure.
+ *
+ */
+void ne_init(dpeth_t *dep)
 {
 	int i;
 	int word, sendq_nr;
-
+	
 	/* Setup a transfer to get the ethernet address. */
 	if (dep->de_16bit)
@@ -217,199 +161,138 @@
 	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
-		{
+	
+	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;
-	}
-
+	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;
+	sendq_nr = dep->de_ramsize / 0x2000;
+	
 	if (sendq_nr < 1)
-		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 %#lx:%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 "
-		    "%#lx, memory size %#lx, 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);
-
+		sendq_nr = SENDQ_NR;
+	
+	dep->de_sendq_nr = sendq_nr;
+	for (i = 0; i < sendq_nr; i++)
+		dep->de_sendq[i].sq_sendpage = dep->de_offset_page + i * SENDQ_PAGES;
+	
+	dep->de_startpage = dep->de_offset_page + i * SENDQ_PAGES;
+	dep->de_stoppage = dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
+	
+	printf("Novell NE%d000 ethernet card at I/O address "
+	    "%#lx, memory size %#lx, irq %d\n",
+	    dep->de_16bit ? 2 : 1, dep->de_base_port, dep->de_ramsize,
+	    dep->de_irq);
+}
+
+static int test_8(dpeth_t *dep, int pos, uint8_t *pat)
+{
+	uint8_t buf[4];
+	int i;
+	
+	outb_reg0(dep, DP_ISR, 0xff);
+	
 	/* Setup a transfer to put the pattern. */
 	outb_reg0(dep, DP_RBCR0, 4);
 	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, pos &0xFF);
+	outb_reg0(dep, DP_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++)
+	
+	for (i = 0; i < 4; i++)
 		outb_ne(dep, NE_DATA, pat[i]);
-
-	for (i= 0; i<N; i++)
-	{
+	
+	for (i = 0; i < N; i++) {
+		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+			break;
+	}
+	
+	if (i == N) {
+		printf("NE1000 remote DMA test failed\n");
+		return 0;
+	}
+	
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos & 0xff);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+	
+	for (i = 0; i < 4; i++)
+		buf[i] = inb_ne(dep, NE_DATA);
+	
+	return (memcmp(buf, pat, 4) == 0);
+}
+
+static int test_16(dpeth_t *dep, int pos, uint8_t *pat)
+{
+	uint8_t buf[4];
+	int i;
+	
+	outb_reg0(dep, DP_ISR, 0xff);
+	
+	/* Setup a transfer to put the pattern. */
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos & 0xff);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+	
+	for (i = 0; i < 4; i += 2)
+		outw_ne(dep, NE_DATA, *(uint16_t *)(pat + i));
+	
+	for (i = 0; i < N; i++) {
 		if (inb_reg0(dep, DP_ISR) &ISR_RDC)
 			break;
 	}
-	if (i == N)
-	{
-		if (debug)
-		{
-			printf("%s: NE1000 remote DMA test failed\n",
-				dep->de_name);
-		}
+	
+	if (i == N) {
+		printf("NE2000 remote DMA test failed\n");
 		return 0;
 	}
-
-	outb_reg0(dep, DP_RBCR0, 4);
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, pos &0xFF);
+	
+	outb_reg0(dep, DP_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;
-
+	
+	for (i = 0; i < 4; i += 2)
+		*(uint16_t *)(buf + i) = inw_ne(dep, NE_DATA);
+	
+	return (memcmp(buf, pat, 4) == 0);
+}
+
+/** Stop the NE2000 network interface.
+ *
+ *  @param[in,out] dep The network interface structure.
+ *
+ */
+void ne_stop(dpeth_t *dep)
+{
 	/* Reset the ethernet card */
-	byte= inb_ne(dep, NE_RESET);
-	milli_delay(2);
+	int byte = inb_ne(dep, NE_RESET);
+	usleep(2000);
 	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 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/hw/netif/dp8390/ne2000.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -1,17 +1,23 @@
 /*
- * 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:
+ * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
  *
- * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must 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
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
  *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
  *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED 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,
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@@ -20,14 +26,15 @@
  * (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>
-*/
+ * This code is based upon the NE2000 driver for MINIX,
+ * distributed according to a BSD-style license.
+ *
+ * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
+ * Copyright (c) 1992, 1994 Philip Homburg
+ * Copyright (c) 1996 G. Falzoni
+ *
+ */
 
 /** @addtogroup ne2k
@@ -43,34 +50,33 @@
 
 #include <libarch/ddi.h>
-
 #include "dp8390_port.h"
 
 /** DP8390 register offset.
  */
-#define NE_DP8390	0x00
+#define NE_DP8390  0x00
 
 /** Data register.
  */
-#define NE_DATA		0x10
+#define NE_DATA  0x10
 
 /** Reset register.
  */
-#define NE_RESET	0x1F
+#define NE_RESET  0x1f
 
 /** NE1000 data start.
  */
-#define NE1000_START	0x2000
+#define NE1000_START  0x2000
 
 /** NE1000 data size.
  */
-#define NE1000_SIZE	0x2000
+#define NE1000_SIZE  0x2000
 
 /** NE2000 data start.
  */
-#define NE2000_START	0x4000
+#define NE2000_START  0x4000
 
 /** NE2000 data size.
  */
-#define NE2000_SIZE	0x4000
+#define NE2000_SIZE  0x4000
 
 /** Reads 1 byte register.
@@ -79,5 +85,5 @@
  *  @returns The read value.
  */
-#define inb_ne(dep, reg)	(inb(dep->de_base_port+reg))
+#define inb_ne(dep, reg)  (inb(dep->de_base_port + reg))
 
 /** Writes 1 byte register.
@@ -86,5 +92,5 @@
  *  @param[in] data The value to be written.
  */
-#define outb_ne(dep, reg, data)	(outb(dep->de_base_port+reg, data))
+#define outb_ne(dep, reg, data)  (outb(dep->de_base_port + reg, data))
 
 /** Reads 1 word (2 bytes) register.
@@ -93,5 +99,5 @@
  *  @returns The read value.
  */
-#define inw_ne(dep, reg)	(inw(dep->de_base_port+reg))
+#define inw_ne(dep, reg)  (inw(dep->de_base_port + reg))
 
 /** Writes 1 word (2 bytes) register.
@@ -100,11 +106,13 @@
  *  @param[in] data The value to be written.
  */
-#define outw_ne(dep, reg, data)	(outw(dep->de_base_port+reg, data))
+#define outw_ne(dep, reg, data)  (outw(dep->de_base_port + reg, data))
 
-#endif /* __NET_NETIF_NE2000_H__ */
+struct dpeth;
 
-/*
- * $PchId: ne2000.h,v 1.4 2004/08/03 12:03:20 philip Exp $
- */
+extern int ne_probe(struct dpeth *);
+extern void ne_init(struct dpeth *);
+extern void ne_stop(struct dpeth *);
+
+#endif
 
 /** @}
Index: pace/srv/net/cfg/Makefile
===================================================================
--- uspace/srv/net/cfg/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ 	(revision )
@@ -1,60 +1,0 @@
-#
-# Copyright (c) 2010 Martin Decky
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-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/lo
===================================================================
--- uspace/srv/net/cfg/lo	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/srv/net/cfg/lo	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -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: pace/srv/net/cfg/lo.netif_nil_bundle
===================================================================
--- uspace/srv/net/cfg/lo.netif_nil_bundle	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ 	(revision )
@@ -1,13 +1,0 @@
-# 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: pace/srv/net/cfg/lo.netif_standalone
===================================================================
--- uspace/srv/net/cfg/lo.netif_standalone	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ 	(revision )
@@ -1,13 +1,0 @@
-# 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
===================================================================
--- uspace/srv/net/cfg/ne2k	(revision 43c39376c1674a5906c1c9910d76824431740846)
+++ uspace/srv/net/cfg/ne2k	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -0,0 +1,24 @@
+# DP8390 (NE2k) configuration
+
+NAME=ne2k
+
+NETIF=dp8390
+NIL=eth
+IL=ip
+
+IRQ=5
+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: pace/srv/net/cfg/ne2k.netif_nil_bundle
===================================================================
--- uspace/srv/net/cfg/ne2k.netif_nil_bundle	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ 	(revision )
@@ -1,24 +1,0 @@
-# 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: pace/srv/net/cfg/ne2k.netif_standalone
===================================================================
--- uspace/srv/net/cfg/ne2k.netif_standalone	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ 	(revision )
@@ -1,24 +1,0 @@
-# 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/netif/lo/Makefile
===================================================================
--- uspace/srv/net/netif/lo/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/net/netif/lo/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -39,8 +39,4 @@
 -include $(CONFIG_MAKEFILE)
 
-ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
-	LIBS += $(USPACE_PREFIX)/srv/net/nil/nildummy/libnildummy.a
-endif
-
 BINARY = lo
 
Index: uspace/srv/net/nil/eth/Makefile
===================================================================
--- uspace/srv/net/nil/eth/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/net/nil/eth/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -39,9 +39,5 @@
 -include $(CONFIG_MAKEFILE)
 
-ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
-	LIBRARY = libeth
-else
-	BINARY = eth
-endif
+BINARY = eth
 
 SOURCES = \
Index: uspace/srv/net/nil/nildummy/Makefile
===================================================================
--- uspace/srv/net/nil/nildummy/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/net/nil/nildummy/Makefile	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -39,9 +39,5 @@
 -include $(CONFIG_MAKEFILE)
 
-ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
-	LIBRARY = libnildummy
-else
-	BINARY = nildummy
-endif
+BINARY = nildummy
 
 SOURCES = \
Index: uspace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/net/tl/icmp/icmp.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -529,5 +529,5 @@
 	icmp_code_t code;
 	int rc;
-
+	
 	switch (error) {
 	case SERVICE_NONE:
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -205,4 +205,5 @@
 static int tcp_queue_received_packet(socket_core_t *, tcp_socket_data_t *,
     packet_t *, int, size_t);
+static void tcp_queue_received_end_of_data(socket_core_t *socket);
 
 static int tcp_received_msg(device_id_t, packet_t *, services_t, services_t);
@@ -453,5 +454,5 @@
 
 has_error_service:
-	fibril_rwlock_read_unlock(&tcp_globals.lock);
+	fibril_rwlock_write_unlock(&tcp_globals.lock);
 
 	/* TODO error reporting/handling */
@@ -504,4 +505,5 @@
 	size_t offset;
 	uint32_t new_sequence_number;
+	bool forced_ack;
 	int rc;
 
@@ -512,9 +514,13 @@
 	assert(packet);
 
+	forced_ack = false;
+
 	new_sequence_number = ntohl(header->sequence_number);
 	old_incoming = socket_data->next_incoming;
 
-	if (header->finalize)
-		socket_data->fin_incoming = new_sequence_number;
+	if (header->finalize) {
+		socket_data->fin_incoming = new_sequence_number +
+		    total_length - TCP_HEADER_LENGTH(header);
+	}
 
 	/* Trim begining if containing expected data */
@@ -760,9 +766,13 @@
 		/* 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)) {
+		forced_ack = true;
+	}
+
+	/* If next in sequence is an incoming FIN */
+	if (socket_data->next_incoming == socket_data->fin_incoming) {
+		/* Advance sequence number */
+		socket_data->next_incoming += 1;
+
+		/* Handle FIN */
 		switch (socket_data->state) {
 		case TCP_SOCKET_FIN_WAIT_1:
@@ -771,5 +781,9 @@
 			socket_data->state = TCP_SOCKET_CLOSING;
 			break;
-		/*case TCP_ESTABLISHED:*/
+		case TCP_SOCKET_ESTABLISHED:
+			/* Queue end-of-data marker on the socket. */
+			tcp_queue_received_end_of_data(socket);
+			socket_data->state = TCP_SOCKET_CLOSE_WAIT;
+			break;
 		default:
 			socket_data->state = TCP_SOCKET_CLOSE_WAIT;
@@ -779,5 +793,5 @@
 
 	packet = tcp_get_packets_to_send(socket, socket_data);
-	if (!packet) {
+	if (!packet && (socket_data->next_incoming != old_incoming || forced_ack)) {
 		/* Create the notification packet */
 		rc = tcp_create_notification_packet(&packet, socket,
@@ -835,4 +849,22 @@
 
 	return EOK;
+}
+
+/** Queue end-of-data marker on the socket.
+ *
+ * Next element in the sequence space is FIN. Queue end-of-data marker
+ * on the socket.
+ *
+ * @param socket	Socket
+ */
+static void tcp_queue_received_end_of_data(socket_core_t *socket)
+{
+	assert(socket != NULL);
+
+	/* Notify the destination socket */
+	async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
+	    (sysarg_t) socket->socket_id,
+	    0, 0, 0,
+	    (sysarg_t) 0 /* 0 fragments == no more data */);
 }
 
@@ -1803,4 +1835,6 @@
 			fibril_rwlock_write_unlock(socket_data->local_lock);
 
+			socket_data->state = TCP_SOCKET_SYN_SENT;
+
 			/* Send the packet */
 			printf("connecting %d\n", packet_get_id(packet));
@@ -2210,5 +2244,5 @@
 
 		tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
-		rc = tcp_queue_packet(socket, socket_data, packet, 0);
+		rc = tcp_queue_packet(socket, socket_data, packet, total_length);
 		if (rc != EOK)
 			return rc;
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/vfs/vfs.h	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -34,4 +34,5 @@
 #define VFS_VFS_H_
 
+#include <async.h>
 #include <ipc/ipc.h>
 #include <adt/list.h>
@@ -53,6 +54,5 @@
 	vfs_info_t vfs_info;
 	fs_handle_t fs_handle;
-	fibril_mutex_t phone_lock;
-	sysarg_t phone;
+	async_sess_t session;
 } fs_info_t;
 
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/srv/vfs/vfs_register.c	(revision 43c39376c1674a5906c1c9910d76824431740846)
@@ -39,5 +39,4 @@
 #include <ipc/services.h>
 #include <async.h>
-#include <async_rel.h>
 #include <fibril.h>
 #include <fibril_synch.h>
@@ -111,4 +110,6 @@
 void vfs_register(ipc_callid_t rid, ipc_call_t *request)
 {
+	int phone;
+	
 	dprintf("Processing VFS_REGISTER request received from %p.\n",
 	    request->in_phone_hash);
@@ -136,5 +137,4 @@
 	
 	link_initialize(&fs_info->fs_link);
-	fibril_mutex_initialize(&fs_info->phone_lock);
 	fs_info->vfs_info = *vfs_info;
 	free(vfs_info);
@@ -186,5 +186,7 @@
 		return;
 	}
-	fs_info->phone = IPC_GET_ARG5(call);
+	
+	phone = IPC_GET_ARG5(call);
+	async_session_create(&fs_info->session, phone);
 	ipc_answer_0(callid, EOK);
 	
@@ -200,5 +202,6 @@
 		list_remove(&fs_info->fs_link);
 		fibril_mutex_unlock(&fs_head_lock);
-		ipc_hangup(fs_info->phone);
+		async_session_destroy(&fs_info->session);
+		ipc_hangup(phone);
 		free(fs_info);
 		ipc_answer_0(callid, EINVAL);
@@ -214,5 +217,6 @@
 		list_remove(&fs_info->fs_link);
 		fibril_mutex_unlock(&fs_head_lock);
-		ipc_hangup(fs_info->phone);
+		async_session_destroy(&fs_info->session);
+		ipc_hangup(phone);
 		free(fs_info);
 		ipc_answer_0(callid, EINVAL);
@@ -269,7 +273,5 @@
 		if (fs->fs_handle == handle) {
 			fibril_mutex_unlock(&fs_head_lock);
-			fibril_mutex_lock(&fs->phone_lock);
-			phone = async_relation_create(fs->phone);
-			fibril_mutex_unlock(&fs->phone_lock);
+			phone = async_exchange_begin(&fs->session);
 
 			assert(phone > 0);
@@ -295,7 +297,5 @@
 		if (fs->fs_handle == handle) {
 			fibril_mutex_unlock(&fs_head_lock);
-			fibril_mutex_lock(&fs->phone_lock);
-			async_relation_destroy(fs->phone, phone);
-			fibril_mutex_unlock(&fs->phone_lock);
+			async_exchange_end(&fs->session, phone);
 			return;
 		}
