Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/bd/ata_bd/ata_bd.h	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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 b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
+++ uspace/srv/bd/ata_bd/ata_hw.h	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/devman/devman.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -62,4 +62,14 @@
 }
 
+static int devmap_devices_class_compare(unsigned long key[], hash_count_t keys,
+    link_t *item)
+{
+	dev_class_info_t *class_info
+	    = hash_table_get_instance(item, dev_class_info_t, devmap_link);
+	assert(class_info != NULL);
+
+	return (class_info->devmap_handle == (devmap_handle_t) key[0]);
+}
+
 static void devices_remove_callback(link_t *item)
 {
@@ -75,4 +85,10 @@
 	.hash = devices_hash,
 	.compare = devmap_devices_compare,
+	.remove_callback = devices_remove_callback
+};
+
+static hash_table_operations_t devmap_devices_class_ops = {
+	.hash = devices_hash,
+	.compare = devmap_devices_class_compare,
 	.remove_callback = devices_remove_callback
 };
@@ -376,4 +392,5 @@
 	printf(NAME ": create_root_node\n");
 
+	fibril_rwlock_write_lock(&tree->rwlock);
 	node = create_dev_node();
 	if (node != NULL) {
@@ -385,4 +402,5 @@
 		tree->root_node = node;
 	}
+	fibril_rwlock_write_unlock(&tree->rwlock);
 
 	return node != NULL;
@@ -447,6 +465,4 @@
 /** Start a driver
  *
- * The driver's mutex is assumed to be locked.
- *
  * @param drv		The driver's structure.
  * @return		True if the driver's task is successfully spawned, false
@@ -457,4 +473,6 @@
 	int rc;
 
+	assert(fibril_mutex_is_locked(&drv->driver_mutex));
+	
 	printf(NAME ": start_driver '%s'\n", drv->name);
 	
@@ -678,5 +696,6 @@
 	}
 	
-	devmap_device_register(devmap_pathname, &node->devmap_handle);
+	devmap_device_register_with_iface(devmap_pathname,
+	    &node->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
 	
 	tree_add_devmap_device(tree, node);
@@ -850,6 +869,4 @@
 /** Find the device node structure of the device witch has the specified handle.
  *
- * Device tree's rwlock should be held at least for reading.
- *
  * @param tree		The device tree where we look for the device node.
  * @param handle	The handle of the device.
@@ -859,5 +876,9 @@
 {
 	unsigned long key = handle;
-	link_t *link = hash_table_find(&tree->devman_devices, &key);
+	link_t *link;
+	
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+	
+	link = hash_table_find(&tree->devman_devices, &key);
 	return hash_table_get_instance(link, node_t, devman_link);
 }
@@ -915,7 +936,4 @@
 /** Insert new device into device tree.
  *
- * The device tree's rwlock should be already held exclusively when calling this
- * function.
- *
  * @param tree		The device tree.
  * @param node		The newly added device node. 
@@ -932,4 +950,5 @@
 	assert(tree != NULL);
 	assert(dev_name != NULL);
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
 	
 	node->name = dev_name;
@@ -1050,6 +1069,10 @@
 	
 	info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t));
-	if (info != NULL)
+	if (info != NULL) {
 		memset(info, 0, sizeof(dev_class_info_t));
+		list_initialize(&info->dev_classes);
+		list_initialize(&info->devmap_link);
+		list_initialize(&info->link);
+	}
 	
 	return info;
@@ -1175,5 +1198,5 @@
 	fibril_rwlock_initialize(&class_list->rwlock);
 	hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1,
-	    &devmap_devices_ops);
+	    &devmap_devices_class_ops);
 }
 
@@ -1223,4 +1246,6 @@
 	hash_table_insert(&class_list->devmap_devices, &key, &cli->devmap_link);
 	fibril_rwlock_write_unlock(&class_list->rwlock);
+
+	assert(find_devmap_class_device(class_list, cli->devmap_handle) != NULL);
 }
 
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/devman/main.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -281,5 +281,6 @@
 	 * handle.
 	 */
-	devmap_device_register(devmap_pathname, &cli->devmap_handle);
+	devmap_device_register_with_iface(devmap_pathname,
+	    &cli->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
 	
 	/*
@@ -457,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;
@@ -486,5 +488,5 @@
 static void devman_connection_devmapper(ipc_callid_t iid, ipc_call_t *icall)
 {
-	devmap_handle_t devmap_handle = IPC_GET_IMETHOD(*icall);
+	devmap_handle_t devmap_handle = IPC_GET_ARG2(*icall);
 	node_t *dev;
 
@@ -503,8 +505,8 @@
 	}
 	
-	printf(NAME ": devman_connection_devmapper: forward connection to "
-	    "device %s to driver %s.\n", dev->pathname, dev->drv->name);
 	ipc_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, dev->handle, 0,
 	    IPC_FF_NONE);
+	printf(NAME ": devman_connection_devmapper: forwarded connection to "
+	    "device %s to driver %s.\n", dev->pathname, dev->drv->name);
 }
 
@@ -512,22 +514,4 @@
 static void devman_connection(ipc_callid_t iid, ipc_call_t *icall)
 {
-	/*
-	 * Silly hack to enable the device manager to register as a driver by
-	 * the device mapper. If the ipc method is not IPC_M_CONNECT_ME_TO, this
-	 * is not the forwarded connection from naming service, so it must be a
-	 * connection from the devmapper which thinks this is a devmapper-style
-	 * driver. So pretend this is a devmapper-style driver. (This does not
-	 * work for device with handle == IPC_M_CONNECT_ME_TO, because devmapper
-	 * passes device handle to the driver as an ipc method.)
-	 */
-	if (IPC_GET_IMETHOD(*icall) != IPC_M_CONNECT_ME_TO)
-		devman_connection_devmapper(iid, icall);
-
-	/*
-	 * ipc method is IPC_M_CONNECT_ME_TO, so this is forwarded connection
-	 * from naming service by which we registered as device manager, so be
-	 * device manager.
-	 */
-	
 	/* Select interface. */
 	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
@@ -542,4 +526,8 @@
 		devman_forward(iid, icall, false);
 		break;
+	case DEVMAN_CONNECT_FROM_DEVMAP:
+		/* Someone connected through devmap node. */
+		devman_connection_devmapper(iid, icall);
+		break;
 	case DEVMAN_CONNECT_TO_PARENTS_DEVICE:
 		/* Connect client to selected device. */
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/devmap/devmap.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -46,4 +46,5 @@
 #include <str.h>
 #include <ipc/devmap.h>
+#include <assert.h>
 
 #define NAME          "devmap"
@@ -99,4 +100,6 @@
 	/** Device driver handling this device */
 	devmap_driver_t *driver;
+	/** Use this interface when forwarding to driver. */
+	sysarg_t forward_interface;
 } devmap_device_t;
 
@@ -206,13 +209,11 @@
 }
 
-/** Find namespace with given name.
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Find namespace with given name. */
 static devmap_namespace_t *devmap_namespace_find_name(const char *name)
 {
 	link_t *item;
+	
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+	
 	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
 		devmap_namespace_t *namespace =
@@ -227,7 +228,4 @@
 /** Find namespace with given handle.
  *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
  * @todo: use hash table
  *
@@ -236,4 +234,7 @@
 {
 	link_t *item;
+	
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+	
 	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
 		devmap_namespace_t *namespace =
@@ -246,14 +247,12 @@
 }
 
-/** Find device with given name.
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Find device with given name. */
 static devmap_device_t *devmap_device_find_name(const char *ns_name,
     const char *name)
 {
 	link_t *item;
+	
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+	
 	for (item = devices_list.next; item != &devices_list; item = item->next) {
 		devmap_device_t *device =
@@ -269,7 +268,4 @@
 /** Find device with given handle.
  *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
  * @todo: use hash table
  *
@@ -278,4 +274,7 @@
 {
 	link_t *item;
+	
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+	
 	for (item = devices_list.next; item != &devices_list; item = item->next) {
 		devmap_device_t *device =
@@ -288,13 +287,12 @@
 }
 
-/** Create a namespace (if not already present)
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Create a namespace (if not already present). */
 static devmap_namespace_t *devmap_namespace_create(const char *ns_name)
 {
-	devmap_namespace_t *namespace = devmap_namespace_find_name(ns_name);
+	devmap_namespace_t *namespace;
+	
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+	
+	namespace = devmap_namespace_find_name(ns_name);
 	if (namespace != NULL)
 		return namespace;
@@ -321,12 +319,9 @@
 }
 
-/** Destroy a namespace (if it is no longer needed)
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Destroy a namespace (if it is no longer needed). */
 static void devmap_namespace_destroy(devmap_namespace_t *namespace)
 {
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+
 	if (namespace->refcnt == 0) {
 		list_remove(&(namespace->namespaces));
@@ -337,37 +332,28 @@
 }
 
-/** Increase namespace reference count by including device
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Increase namespace reference count by including device. */
 static void devmap_namespace_addref(devmap_namespace_t *namespace,
     devmap_device_t *device)
 {
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+
 	device->namespace = namespace;
 	namespace->refcnt++;
 }
 
-/** Decrease namespace reference count
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Decrease namespace reference count. */
 static void devmap_namespace_delref(devmap_namespace_t *namespace)
 {
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+
 	namespace->refcnt--;
 	devmap_namespace_destroy(namespace);
 }
 
-/** Unregister device and free it
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Unregister device and free it. */
 static void devmap_device_unregister_core(devmap_device_t *device)
 {
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+
 	devmap_namespace_delref(device->namespace);
 	list_remove(&(device->devices));
@@ -517,4 +503,7 @@
 	}
 	
+	/* Set the interface, if any. */
+	device->forward_interface = IPC_GET_ARG1(*icall);
+
 	/* Get fqdn */
 	char *fqdn;
@@ -566,5 +555,5 @@
 	/* Get unique device handle */
 	device->handle = devmap_create_handle();
-	
+
 	devmap_namespace_addref(namespace, device);
 	device->driver = driver;
@@ -617,6 +606,13 @@
 	}
 	
-	ipc_forward_fast(callid, dev->driver->phone, dev->handle,
-	    IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
+	if (dev->forward_interface == 0) {
+		ipc_forward_fast(callid, dev->driver->phone,
+		    dev->handle, 0, 0,
+		    IPC_FF_NONE);
+	} else {
+		ipc_forward_fast(callid, dev->driver->phone,
+		    dev->forward_interface, dev->handle, 0,
+		    IPC_FF_NONE);
+	}
 	
 	fibril_mutex_unlock(&devices_list_mutex);
Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -60,7 +60,8 @@
 typedef struct {
 	devmap_handle_t handle;
-	int phone;
+	int phone;		/**< When < 0, the structure is incomplete. */
 	size_t refcount;
 	link_t link;
+	fibril_condvar_t cv;	/**< Broadcast when completed. */
 } device_t;
 
@@ -227,7 +228,9 @@
 			[DEVICES_KEY_HANDLE] = (unsigned long) node->handle
 		};
-		
+		link_t *lnk;
+
 		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
+restart:
+		lnk = hash_table_find(&devices, key);
 		if (lnk == NULL) {
 			device_t *dev = (device_t *) malloc(sizeof(device_t));
@@ -237,18 +240,60 @@
 			}
 			
+			dev->handle = node->handle;
+			dev->phone = -1;	/* mark as incomplete */
+			dev->refcount = 1;
+			fibril_condvar_initialize(&dev->cv);
+
+			/*
+			 * Insert the incomplete device structure so that other
+			 * fibrils will not race with us when we drop the mutex
+			 * below.
+			 */
+			hash_table_insert(&devices, key, &dev->link);
+
+			/*
+			 * Drop the mutex to allow recursive devfs requests.
+			 */
+			fibril_mutex_unlock(&devices_mutex);
+
 			int phone = devmap_device_connect(node->handle, 0);
+
+			fibril_mutex_lock(&devices_mutex);
+
+			/*
+			 * Notify possible waiters about this device structure
+			 * being completed (or destroyed).
+			 */
+			fibril_condvar_broadcast(&dev->cv);
+
 			if (phone < 0) {
+				/*
+				 * Connecting failed, need to remove the
+				 * entry and free the device structure.
+				 */
+				hash_table_remove(&devices, key, DEVICES_KEYS);
 				fibril_mutex_unlock(&devices_mutex);
+
 				free(dev);
 				return ENOENT;
 			}
 			
-			dev->handle = node->handle;
+			/* Set the correct phone. */
 			dev->phone = phone;
-			dev->refcount = 1;
-			
-			hash_table_insert(&devices, key, &dev->link);
 		} else {
 			device_t *dev = hash_table_get_instance(lnk, device_t, link);
+
+			if (dev->phone < 0) {
+				/*
+				 * Wait until the device structure is completed
+				 * and start from the beginning as the device
+				 * structure might have entirely disappeared
+				 * while we were not holding the mutex in
+				 * fibril_condvar_wait().
+				 */
+				fibril_condvar_wait(&dev->cv, &devices_mutex);
+				goto restart;
+			}
+
 			dev->refcount++;
 		}
@@ -564,4 +609,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		
 		ipc_callid_t callid;
@@ -627,4 +673,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		
 		ipc_callid_t callid;
@@ -696,4 +743,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		dev->refcount--;
 		
@@ -743,4 +791,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		
 		/* Make a request at the driver */
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/hid/console/console.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -317,6 +317,7 @@
 static void change_console(console_t *cons)
 {
-	if (cons == active_console)
+	if (cons == active_console) {
 		return;
+	}
 	
 	fb_pending_flush();
@@ -458,6 +459,7 @@
 			if (IPC_GET_ARG1(call) == 1) {
 				int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
-				if (newcon != -1)
+				if (newcon != -1) {
 					change_console(&consoles[newcon]);
+				}
 			}
 			retval = 0;
@@ -710,28 +712,139 @@
 }
 
-static bool console_init(char *input)
-{
-	/* Connect to input device */
-	int input_fd = open(input, O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": Failed opening %s\n", input);
-		return false;
-	}
-	
-	kbd_phone = fd_phone(input_fd);
-	if (kbd_phone < 0) {
+static int connect_keyboard(char *path)
+{
+	int fd = open(path, O_RDONLY);
+	if (fd < 0) {
+		return fd;
+	}
+	
+	int phone = fd_phone(fd);
+	if (phone < 0) {
 		printf(NAME ": Failed to connect to input device\n");
-		return false;
+		return phone;
 	}
 	
 	/* NB: The callback connection is slotted for removal */
 	sysarg_t phonehash;
-	if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
+	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 \"%s\").\n", path);
+
+	return phone;
+}
+
+/** 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)
+{
+	char *class_name = (char *) arg;
+
+	int index = 1;
+
+	while (true) {
+		async_usleep(1 * 500 * 1000);
+		char *path;
+		int rc = asprintf(&path, "class/%s\\%d", class_name, index);
+		if (rc < 0) {
+			continue;
+		}
+		rc = 0;
+		rc = connect_keyboard_bypass(path);
+		if (rc > 0) {
+			/* We do not allow unplug. */
+			index++;
+		}
+
+		free(path);
+	}
+
+	return EOK;
+}
+
+
+/** Start a fibril monitoring hot-plugged keyboards.
+ */
+static void check_new_keyboards_in_background()
+{
+	fid_t fid = fibril_create(check_new_keyboards, (void *)"keyboard");
+	if (!fid) {
+		printf(NAME ": failed to create hot-plug-watch fibril.\n");
+		return;
+	}
+	fibril_add_ready(fid);
+}
+
+static bool console_init(char *input)
+{
+	/* Connect to input device */
+	kbd_phone = connect_keyboard(input);
+	if (kbd_phone < 0) {
 		return false;
 	}
-	
-	async_new_connection(phonehash, 0, NULL, keyboard_events);
-	
+
 	/* Connect to mouse device */
 	mouse_phone = -1;
@@ -749,4 +862,5 @@
 	}
 	
+	sysarg_t phonehash;
 	if (ipc_connect_to_me(mouse_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
 		printf(NAME ": Failed to create callback from mouse device\n");
@@ -841,4 +955,7 @@
 	async_set_interrupt_received(interrupt_received);
 	
+	/* Start fibril for checking on hot-plugged keyboards. */
+	check_new_keyboards_in_background();
+
 	return true;
 }
@@ -860,5 +977,5 @@
 	if (!console_init(argv[1]))
 		return -1;
-	
+
 	printf(NAME ": Accepting connections\n");
 	async_manager();
Index: uspace/srv/hw/netif/dp8390/Makefile
===================================================================
--- uspace/srv/hw/netif/dp8390/Makefile	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/hw/netif/dp8390/Makefile	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/hw/netif/dp8390/dp8390.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/hw/netif/dp8390/dp8390.h	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/hw/netif/dp8390/dp8390_drv.h	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/hw/netif/dp8390/dp8390_module.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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,38 +189,41 @@
 	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 = CONVERT_SIZE(ether_addr_t, char, 1);
-	return EOK;
-}
-
-
-
-int netif_probe_message(device_id_t device_id, int irq, uintptr_t io){
-	netif_device_t * device;
-	dpeth_t * dep;
-	int rc;
-
+	address->length = sizeof(ether_addr_t);
+	return EOK;
+}
+
+int netif_probe_message(device_id_t device_id, int irq, uintptr_t io)
+{
+	netif_device_t *device;
+	dpeth_t *dep;
+	int rc;
+	
 	device = (netif_device_t *) malloc(sizeof(netif_device_t));
-	if(! device){
+	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,13 +328,13 @@
 		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 REGISTER_ME(SERVICE_DP8390, &phonehash);
+	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 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/hw/netif/dp8390/dp8390_port.h	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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: uspace/srv/hw/netif/dp8390/local.h
===================================================================
--- uspace/srv/hw/netif/dp8390/local.h	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ 	(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 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/hw/netif/dp8390/ne2000.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/hw/netif/dp8390/ne2000.h	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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: uspace/srv/net/cfg/Makefile
===================================================================
--- uspace/srv/net/cfg/Makefile	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ 	(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 b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
+++ uspace/srv/net/cfg/lo	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -0,0 +1,13 @@
+# loopback configuration
+
+NAME=lo
+
+NETIF=lo
+NIL=nildummy
+IL=ip
+
+IP_CONFIG=static
+IP_ADDR=127.0.0.1
+IP_NETMASK=255.0.0.0
+
+MTU=15535
Index: uspace/srv/net/cfg/lo.netif_nil_bundle
===================================================================
--- uspace/srv/net/cfg/lo.netif_nil_bundle	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ 	(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: uspace/srv/net/cfg/lo.netif_standalone
===================================================================
--- uspace/srv/net/cfg/lo.netif_standalone	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ 	(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 b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
+++ uspace/srv/net/cfg/ne2k	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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: uspace/srv/net/cfg/ne2k.netif_nil_bundle
===================================================================
--- uspace/srv/net/cfg/ne2k.netif_nil_bundle	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ 	(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: uspace/srv/net/cfg/ne2k.netif_standalone
===================================================================
--- uspace/srv/net/cfg/ne2k.netif_standalone	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ 	(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/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/il/arp/arp.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -483,18 +483,14 @@
 	des_proto = des_hw + header->hardware_length;
 	trans = arp_addr_find(&proto->addresses, (char *) src_proto,
-	    CONVERT_SIZE(uint8_t, char, header->protocol_length));
+	    header->protocol_length);
 	/* Exists? */
 	if (trans && trans->hw_addr) {
-		if (trans->hw_addr->length != CONVERT_SIZE(uint8_t, char,
-		    header->hardware_length)) {
+		if (trans->hw_addr->length != header->hardware_length)
 			return EINVAL;
-		}
 		memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
 	}
 	/* Is my protocol address? */
-	if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
-	    header->protocol_length)) {
+	if (proto->addr->length != header->protocol_length)
 		return EINVAL;
-	}
 	if (!str_lcmp(proto->addr->value, (char *) des_proto,
 	    proto->addr->length)) {
@@ -507,6 +503,5 @@
 			fibril_condvar_initialize(&trans->cv);
 			rc = arp_addr_add(&proto->addresses, (char *) src_proto,
-			    CONVERT_SIZE(uint8_t, char, header->protocol_length),
-			    trans);
+			    header->protocol_length, trans);
 			if (rc != EOK) {
 				/* The generic char map has already freed trans! */
@@ -516,6 +511,5 @@
 		if (!trans->hw_addr) {
 			trans->hw_addr = measured_string_create_bulk(
-			    (char *) src_hw, CONVERT_SIZE(uint8_t, char,
-			    header->hardware_length));
+			    (char *) src_hw, header->hardware_length);
 			if (!trans->hw_addr)
 				return ENOMEM;
@@ -606,6 +600,5 @@
 
 	/* ARP packet content size = header + (address + translation) * 2 */
-	length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) +
-	    CONVERT_SIZE(char, uint8_t, device->addr->length));
+	length = 8 + 2 * (proto->addr->length + device->addr->length);
 	if (length > device->packet_dimension.content)
 		return ELIMIT;
@@ -640,6 +633,5 @@
 
 	rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
-	    (uint8_t *) device->broadcast_addr->value,
-	    CONVERT_SIZE(char, uint8_t, device->addr->length));
+	    (uint8_t *) device->broadcast_addr->value, device->addr->length);
 	if (rc != EOK) {
 		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
Index: uspace/srv/net/il/arp/arp_module.c
===================================================================
--- uspace/srv/net/il/arp/arp_module.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/il/arp/arp_module.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -79,5 +79,5 @@
 		goto out;
 	
-	rc = REGISTER_ME(SERVICE_ARP, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_ARP, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/il/ip/ip.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -442,5 +442,5 @@
 		if (route) {
 			address.value = (char *) &route->address.s_addr;
-			address.length = CONVERT_SIZE(in_addr_t, char, 1);
+			address.length = sizeof(in_addr_t);
 			
 			rc = arp_device_req(ip_netif->arp->phone,
@@ -639,5 +639,5 @@
 	if (destination) {
 		rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,
-		    CONVERT_SIZE(char, uint8_t, destination->length));
+		    destination->length);
 	} else {
 		rc = packet_set_addr(packet, NULL, NULL, 0);
@@ -687,6 +687,5 @@
 				rc = packet_set_addr(next, NULL,
 				    (uint8_t *) destination->value,
-				    CONVERT_SIZE(char, uint8_t,
-				    destination->length));
+				    destination->length);
 				if (rc != EOK) {
 				    	free(last_header);
@@ -718,5 +717,5 @@
 			rc = packet_set_addr(next, NULL,
 			    (uint8_t *) destination->value,
-			    CONVERT_SIZE(char, uint8_t, destination->length));
+			    destination->length);
 			if (rc != EOK) {
 				free(last_header);
@@ -1006,5 +1005,5 @@
 		destination.value = route->gateway.s_addr ?
 		    (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
-		destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
+		destination.length = sizeof(dest.s_addr);
 
 		rc = arp_translate_req(netif->arp->phone, netif->device_id,
@@ -1758,6 +1757,5 @@
 			// clear the ARP mapping if any
 			address.value = (char *) &header->destination_address;
-			address.length = CONVERT_SIZE(uint8_t, char,
-			    sizeof(header->destination_address));
+			address.length = sizeof(header->destination_address);
 			arp_clear_address_req(netif->arp->phone,
 			    netif->device_id, SERVICE_IP, &address);
@@ -1951,5 +1949,6 @@
 
 	case NET_IP_GET_ROUTE:
-		rc = data_receive((void **) &addr, &addrlen);
+		rc = async_data_write_accept((void **) &addr, false, 0, 0, 0,
+		    &addrlen);
 		if (rc != EOK)
 			return rc;
Index: uspace/srv/net/il/ip/ip_module.c
===================================================================
--- uspace/srv/net/il/ip/ip_module.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/il/ip/ip_module.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -80,5 +80,5 @@
 		goto out;
 	
-	rc = REGISTER_ME(SERVICE_IP, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_IP, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/net/net.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -335,5 +335,5 @@
 		goto out;
 	
-	rc = REGISTER_ME(SERVICE_NETWORKING, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_NETWORKING, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/netif/lo/Makefile
===================================================================
--- uspace/srv/net/netif/lo/Makefile	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/netif/lo/Makefile	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/netif/lo/lo.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -166,5 +166,5 @@
 	sysarg_t phonehash;
 
-	return REGISTER_ME(SERVICE_LO, &phonehash);
+	return ipc_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, &phonehash);
 }
 
Index: uspace/srv/net/nil/eth/Makefile
===================================================================
--- uspace/srv/net/nil/eth/Makefile	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/nil/eth/Makefile	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/nil/eth/eth.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -201,6 +201,5 @@
 
 	eth_globals.broadcast_addr =
-	    measured_string_create_bulk("\xFF\xFF\xFF\xFF\xFF\xFF",
-	    CONVERT_SIZE(uint8_t, char, ETH_ADDR));
+	    measured_string_create_bulk("\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ADDR);
 	if (!eth_globals.broadcast_addr) {
 		rc = ENOMEM;
Index: uspace/srv/net/nil/eth/eth_module.c
===================================================================
--- uspace/srv/net/nil/eth/eth_module.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/nil/eth/eth_module.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -66,5 +66,5 @@
 		goto out;
 
-	rc = REGISTER_ME(SERVICE_ETHERNET, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_ETHERNET, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/nil/nildummy/Makefile
===================================================================
--- uspace/srv/net/nil/nildummy/Makefile	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/nil/nildummy/Makefile	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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/nil/nildummy/nildummy_module.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy_module.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/nil/nildummy/nildummy_module.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -67,5 +67,5 @@
 		goto out;
 	
-	rc = REGISTER_ME(SERVICE_NILDUMMY, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_NILDUMMY, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/tl/icmp/icmp.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -529,5 +529,5 @@
 	icmp_code_t code;
 	int rc;
-
+	
 	switch (error) {
 	case SERVICE_NONE:
Index: uspace/srv/net/tl/icmp/icmp_module.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp_module.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/tl/icmp/icmp_module.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -74,5 +74,5 @@
 		goto out;
 
-	rc = REGISTER_ME(SERVICE_ICMP, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_ICMP, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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 */);
 }
 
@@ -1365,5 +1397,6 @@
 
 		case NET_SOCKET_BIND:
-			res = data_receive((void **) &addr, &addrlen);
+			res = async_data_write_accept((void **) &addr, false,
+			    0, 0, 0, &addrlen);
 			if (res != EOK)
 				break;
@@ -1402,5 +1435,6 @@
 
 		case NET_SOCKET_CONNECT:
-			res = data_receive((void **) &addr, &addrlen);
+			res = async_data_write_accept((void **) &addr, false,
+			    0, 0, 0, &addrlen);
 			if (res != EOK)
 				break;
@@ -1453,5 +1487,6 @@
 
 		case NET_SOCKET_SENDTO:
-			res = data_receive((void **) &addr, &addrlen);
+			res = async_data_write_accept((void **) &addr, false,
+			    0, 0, 0, &addrlen);
 			if (res != EOK)
 				break;
@@ -1800,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));
@@ -2082,6 +2119,7 @@
 	if (!fibril) {
 		free(operation_timeout);
-		return EPARTY;	/* FIXME: use another EC */
-	}
+		return ENOMEM;
+	}
+
 //      fibril_mutex_lock(&socket_data->operation.mutex);
 	/* Start the timeout fibril */
@@ -2206,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/net/tl/tcp/tcp_module.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp_module.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/tl/tcp/tcp_module.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -75,5 +75,5 @@
 		goto out;
 
-	rc = REGISTER_ME(SERVICE_TCP, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_TCP, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/tl/udp/udp.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -771,5 +771,6 @@
 
 		case NET_SOCKET_BIND:
-			res = data_receive((void **) &addr, &addrlen);
+			res = async_data_write_accept((void **) &addr, false,
+			    0, 0, 0, &addrlen);
 			if (res != EOK)
 				break;
@@ -784,5 +785,6 @@
 
 		case NET_SOCKET_SENDTO:
-			res = data_receive((void **) &addr, &addrlen);
+			res = async_data_write_accept((void **) &addr, false,
+			    0, 0, 0, &addrlen);
 			if (res != EOK)
 				break;
Index: uspace/srv/net/tl/udp/udp_module.c
===================================================================
--- uspace/srv/net/tl/udp/udp_module.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/net/tl/udp/udp_module.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -75,5 +75,5 @@
 		goto out;
 	
-	rc = REGISTER_ME(SERVICE_UDP, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_UDP, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/vfs/vfs.h	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/vfs/vfs_lookup.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -179,6 +179,9 @@
 	fibril_mutex_unlock(&plb_mutex);
 	
-	if (((int) rc < EOK) || (!result))
+	if ((int) rc < EOK)
 		return (int) rc;
+
+	if (!result)
+		return EOK;
 	
 	result->triplet.fs_handle = (fs_handle_t) rc;
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 1f383dde20a2b1e39baa81fbc44a73c126e508e4)
+++ uspace/srv/vfs/vfs_register.c	(revision b2a6fcfe62e491c8d0a4c86810869e9bcff954a5)
@@ -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;
 		}
