Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ boot/Makefile.common	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -107,6 +107,4 @@
 	$(USPACE_PATH)/srv/fs/ext2fs/ext2fs \
 	$(USPACE_PATH)/srv/taskmon/taskmon \
-	$(USPACE_PATH)/srv/hw/netif/ne2000/ne2000 \
-	$(USPACE_PATH)/srv/net/netif/lo/lo \
 	$(USPACE_PATH)/srv/net/nil/eth/eth \
 	$(USPACE_PATH)/srv/net/nil/nildummy/nildummy \
@@ -202,6 +200,6 @@
 NET_CFG = \
 	$(USPACE_PATH)/srv/net/cfg/general \
-	$(USPACE_PATH)/srv/net/cfg/lo \
-	$(USPACE_PATH)/srv/net/cfg/ne2k
+	$(USPACE_PATH)/srv/net/cfg/lo.nic \
+	$(USPACE_PATH)/srv/net/cfg/ne2k.nic
 endif
 
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/Makefile	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -94,6 +94,4 @@
 	srv/hw/char/i8042 \
 	srv/hw/char/s3c24xx_uart \
-	srv/hw/netif/ne2000 \
-	srv/net/netif/lo \
 	srv/net/il/arp \
 	srv/net/il/ip \
@@ -101,4 +99,6 @@
 	srv/net/tl/udp \
 	srv/net/tl/tcp \
+	srv/net/nil/eth \
+	srv/net/nil/nildummy \
 	srv/net/net \
 	drv/infrastructure/root \
@@ -132,11 +132,4 @@
 endif
 
-## Networking
-#
-
-DIRS += \
-	srv/net/nil/eth \
-	srv/net/nil/nildummy
-
 ## Platform-specific hardware support
 #
@@ -186,5 +179,4 @@
 	lib/softfloat \
 	lib/drv \
-	lib/packet \
 	lib/fb \
 	lib/net \
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/Makefile.common	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -123,5 +123,4 @@
 
 LIBDRV_PREFIX = $(LIB_PREFIX)/drv
-LIBPACKET_PREFIX = $(LIB_PREFIX)/packet
 LIBNET_PREFIX = $(LIB_PREFIX)/net
 LIBMINIX_PREFIX = $(LIB_PREFIX)/minix
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/Makefile	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -68,4 +68,5 @@
 	generic/device/hw_res.c \
 	generic/device/char_dev.c \
+	generic/device/nic.c \
 	generic/elf/elf_load.c \
 	generic/event.c \
Index: uspace/lib/c/generic/device/nic.c
===================================================================
--- uspace/lib/c/generic/device/nic.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
+++ uspace/lib/c/generic/device/nic.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -0,0 +1,1271 @@
+/*
+ * Copyright (c) 2011 Radim Vansa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/**
+ * @file
+ * @brief Client-side RPC stubs for DDF NIC
+ */
+
+#include <ipc/dev_iface.h>
+#include <assert.h>
+#include <device/nic.h>
+#include <errno.h>
+#include <async.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <ipc/services.h>
+
+/** Send a packet through the device
+ *
+ * @param[in] dev_sess
+ * @param[in] packet_id Id of the sent packet
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_send_message(async_sess_t *dev_sess, packet_id_t packet_id)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_SEND_MESSAGE, packet_id);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Connect the driver to the NET and NIL services
+ *
+ * @param[in] dev_sess
+ * @param[in] nil_service Service identifier for the NIL service
+ * @param[in] device_id
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_connect_to_nil(async_sess_t *dev_sess, services_t nil_service,
+    nic_device_id_t device_id)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_3_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_CONNECT_TO_NIL, nil_service, device_id);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Get the current state of the device
+ *
+ * @param[in]  dev_sess
+ * @param[out] state    Current state
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_get_state(async_sess_t *dev_sess, nic_device_state_t *state)
+{
+	assert(state);
+	
+	sysarg_t _state;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_GET_STATE, &_state);
+	async_exchange_end(exch);
+	
+	*state = (nic_device_state_t) _state;
+	
+	return rc;
+}
+
+/** Request the device to change its state
+ *
+ * @param[in] dev_sess
+ * @param[in] state    New state
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_set_state(async_sess_t *dev_sess, nic_device_state_t state)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_SET_STATE, state);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Request the MAC address of the device
+ *
+ * @param[in]  dev_sess
+ * @param[out] address  Structure with buffer for the address
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_get_address(async_sess_t *dev_sess, nic_address_t *address)
+{
+	assert(address);
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_GET_ADDRESS);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	rc = async_data_read_start(exch, address, sizeof(nic_address_t));
+	
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Set the address of the device (e.g. MAC on Ethernet)
+ *
+ * @param[in] dev_sess
+ * @param[in] address  Pointer to the address
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_set_address(async_sess_t *dev_sess, const nic_address_t *address)
+{
+	assert(address);
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	aid_t message_id = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_SET_ADDRESS, NULL);
+	int rc = async_data_write_start(exch, address, sizeof(nic_address_t));
+	async_exchange_end(exch);
+	
+	sysarg_t res;
+	async_wait_for(message_id, &res);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return (int) res;
+}
+
+/** Request statistic data about NIC operation.
+ *
+ * @param[in]  dev_sess
+ * @param[out] stats    Structure with the statistics
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_get_stats(async_sess_t *dev_sess, nic_device_stats_t *stats)
+{
+	assert(stats);
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_GET_STATS);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	rc = async_data_read_start(exch, stats, sizeof(nic_device_stats_t));
+	
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Request information about the device.
+ *
+ * @see nic_device_info_t
+ *
+ * @param[in]  dev_sess
+ * @param[out] device_info Information about the device
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_get_device_info(async_sess_t *dev_sess, nic_device_info_t *device_info)
+{
+	assert(device_info);
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_GET_DEVICE_INFO);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	rc = async_data_read_start(exch, device_info, sizeof(nic_device_info_t));
+	
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Request status of the cable (plugged/unplugged)
+ *
+ * @param[in]  dev_sess
+ * @param[out] cable_state Current cable state
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_get_cable_state(async_sess_t *dev_sess, nic_cable_state_t *cable_state)
+{
+	assert(cable_state);
+	
+	sysarg_t _cable_state;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_GET_CABLE_STATE, &_cable_state);
+	async_exchange_end(exch);
+	
+	*cable_state = (nic_cable_state_t) _cable_state;
+	
+	return rc;
+}
+
+/** Request current operation mode.
+ *
+ * @param[in]  dev_sess
+ * @param[out] speed    Current operation speed in Mbps. Can be NULL.
+ * @param[out] duplex   Full duplex/half duplex. Can be NULL.
+ * @param[out] role     Master/slave/auto. Can be NULL.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_get_operation_mode(async_sess_t *dev_sess, int *speed,
+   nic_channel_mode_t *duplex, nic_role_t *role)
+{
+	sysarg_t _speed;
+	sysarg_t _duplex;
+	sysarg_t _role;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_GET_OPERATION_MODE, &_speed, &_duplex, &_role);
+	async_exchange_end(exch);
+	
+	if (speed)
+		*speed = (int) _speed;
+	
+	if (duplex)
+		*duplex = (nic_channel_mode_t) _duplex;
+	
+	if (role)
+		*role = (nic_role_t) _role;
+	
+	return rc;
+}
+
+/** Set current operation mode.
+ *
+ * If the NIC has auto-negotiation enabled, this command
+ * disables auto-negotiation and sets the operation mode.
+ *
+ * @param[in] dev_sess
+ * @param[in] speed    Operation speed in Mbps
+ * @param[in] duplex   Full duplex/half duplex
+ * @param[in] role     Master/slave/auto (e.g. in Gbit Ethernet]
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_set_operation_mode(async_sess_t *dev_sess, int speed,
+    nic_channel_mode_t duplex, nic_role_t role)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_SET_OPERATION_MODE, (sysarg_t) speed, (sysarg_t) duplex,
+	    (sysarg_t) role);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Enable auto-negotiation.
+ *
+ * The advertisement argument can only limit some modes,
+ * it can never force the NIC to advertise unsupported modes.
+ *
+ * The allowed modes are defined in "net/eth_phys.h" in the C library.
+ *
+ * @param[in] dev_sess
+ * @param[in] advertisement Allowed advertised modes. Use 0 for all modes.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_autoneg_enable(async_sess_t *dev_sess, uint32_t advertisement)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_AUTONEG_ENABLE, (sysarg_t) advertisement);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Disable auto-negotiation.
+ *
+ * @param[in] dev_sess
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_autoneg_disable(async_sess_t *dev_sess)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_AUTONEG_DISABLE);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Probe current state of auto-negotiation.
+ *
+ * Modes are defined in the "net/eth_phys.h" in the C library.
+ *
+ * @param[in]  dev_sess
+ * @param[out] our_advertisement   Modes advertised by this NIC.
+ *                                 Can be NULL.
+ * @param[out] their_advertisement Modes advertised by the other side.
+ *                                 Can be NULL.
+ * @param[out] result              General state of auto-negotiation.
+ *                                 Can be NULL.
+ * @param[out]  their_result       State of other side auto-negotiation.
+ *                                 Can be NULL.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_autoneg_probe(async_sess_t *dev_sess, uint32_t *our_advertisement,
+    uint32_t *their_advertisement, nic_result_t *result,
+    nic_result_t *their_result)
+{
+	sysarg_t _our_advertisement;
+	sysarg_t _their_advertisement;
+	sysarg_t _result;
+	sysarg_t _their_result;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_4(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_AUTONEG_PROBE, &_our_advertisement, &_their_advertisement,
+	    &_result, &_their_result);
+	async_exchange_end(exch);
+	
+	if (our_advertisement)
+		*our_advertisement = (uint32_t) _our_advertisement;
+	
+	if (*their_advertisement)
+		*their_advertisement = (uint32_t) _their_advertisement;
+	
+	if (result)
+		*result = (nic_result_t) _result;
+	
+	if (their_result)
+		*their_result = (nic_result_t) _their_result;
+	
+	return rc;
+}
+
+/** Restart the auto-negotiation process.
+ *
+ * @param[in] dev_sess
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_autoneg_restart(async_sess_t *dev_sess)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_AUTONEG_RESTART);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Query party's sending and reception of the PAUSE frame.
+ *
+ * @param[in]  dev_sess
+ * @param[out] we_send    This NIC sends the PAUSE frame (true/false)
+ * @param[out] we_receive This NIC receives the PAUSE frame (true/false)
+ * @param[out] pause      The time set to transmitted PAUSE frames.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_get_pause(async_sess_t *dev_sess, nic_result_t *we_send,
+    nic_result_t *we_receive, uint16_t *pause)
+{
+	sysarg_t _we_send;
+	sysarg_t _we_receive;
+	sysarg_t _pause;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_GET_PAUSE, &_we_send, &_we_receive, &_pause);
+	async_exchange_end(exch);
+	
+	if (we_send)
+		*we_send = _we_send;
+	
+	if (we_receive)
+		*we_receive = _we_receive;
+	
+	if (pause)
+		*pause = _pause;
+	
+	return rc;
+}
+
+/** Control sending and reception of the PAUSE frame.
+ *
+ * @param[in] dev_sess
+ * @param[in] allow_send    Allow sending the PAUSE frame (true/false)
+ * @param[in] allow_receive Allow reception of the PAUSE frame (true/false)
+ * @param[in] pause         Pause length in 512 bit units written
+ *                          to transmitted frames. The value 0 means
+ *                          auto value (the best). If the requested
+ *                          time cannot be set the driver is allowed
+ *                          to set the nearest supported value.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_set_pause(async_sess_t *dev_sess, int allow_send, int allow_receive,
+    uint16_t pause)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_SET_PAUSE, allow_send, allow_receive, pause);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Retrieve current settings of unicast frames reception.
+ *
+ * Note: In case of mode != NIC_UNICAST_LIST the contents of
+ * address_list and address_count are undefined.
+ *
+ * @param[in]   dev_sess
+ * @param[out]  mode          Current operation mode
+ * @param[in]   max_count     Maximal number of addresses that could
+ *                            be written into the list buffer.
+ * @param[out]  address_list  Buffer for the list (array). Can be NULL.
+ * @param[out]  address_count Number of addresses in the list before
+ *                            possible truncation due to the max_count.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_unicast_get_mode(async_sess_t *dev_sess, nic_unicast_mode_t *mode,
+    size_t max_count, nic_address_t *address_list, size_t *address_count)
+{
+	assert(mode);
+	
+	sysarg_t _mode;
+	sysarg_t _address_count;
+	
+	if (!address_list)
+		max_count = 0;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_UNICAST_GET_MODE, max_count, &_mode, &_address_count);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	*mode = (nic_unicast_mode_t) _mode;
+	if (address_count)
+		*address_count = (size_t) _address_count;
+	
+	if ((max_count) && (_address_count))
+		rc = async_data_read_start(exch, address_list,
+		    max_count * sizeof(nic_address_t));
+	
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Set which unicast frames are received.
+ *
+ * @param[in] dev_sess
+ * @param[in] mode          Current operation mode
+ * @param[in] address_list  The list of addresses. Can be NULL.
+ * @param[in] address_count Number of addresses in the list.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_unicast_set_mode(async_sess_t *dev_sess, nic_unicast_mode_t mode,
+    const nic_address_t *address_list, size_t address_count)
+{
+	if (address_list == NULL)
+		address_count = 0;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_UNICAST_SET_MODE, (sysarg_t) mode, address_count, NULL);
+	
+	int rc;
+	if (address_count)
+		rc = async_data_write_start(exch, address_list,
+		    address_count * sizeof(nic_address_t));
+	else
+		rc = EOK;
+	
+	async_exchange_end(exch);
+	
+	sysarg_t res;
+	async_wait_for(message_id, &res);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return (int) res;
+}
+
+/** Retrieve current settings of multicast frames reception.
+ *
+ * Note: In case of mode != NIC_MULTICAST_LIST the contents of
+ * address_list and address_count are undefined.
+ *
+ * @param[in]  dev_sess
+ * @param[out] mode          Current operation mode
+ * @param[in]  max_count     Maximal number of addresses that could
+ *                           be written into the list buffer.
+ * @param[out] address_list  Buffer for the list (array). Can be NULL.
+ * @param[out] address_count Number of addresses in the list before
+ *                           possible truncation due to the max_count.
+ *                           Can be NULL.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_multicast_get_mode(async_sess_t *dev_sess, nic_multicast_mode_t *mode,
+    size_t max_count, nic_address_t *address_list, size_t *address_count)
+{
+	assert(mode);
+	
+	sysarg_t _mode;
+	
+	if (!address_list)
+		max_count = 0;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	sysarg_t ac;
+	int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_MULTICAST_GET_MODE, max_count, &_mode, &ac);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	*mode = (nic_multicast_mode_t) _mode;
+	if (address_count)
+		*address_count = (size_t) ac;
+	
+	if ((max_count) && (ac))
+		rc = async_data_read_start(exch, address_list,
+		    max_count * sizeof(nic_address_t));
+	
+	async_exchange_end(exch);
+	return rc;
+}
+
+/** Set which multicast frames are received.
+ *
+ * @param[in] dev_sess
+ * @param[in] mode          Current operation mode
+ * @param[in] address_list  The list of addresses. Can be NULL.
+ * @param[in] address_count Number of addresses in the list.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_multicast_set_mode(async_sess_t *dev_sess, nic_multicast_mode_t mode,
+    const nic_address_t *address_list, size_t address_count)
+{
+	if (address_list == NULL)
+		address_count = 0;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_MULTICAST_SET_MODE, (sysarg_t) mode, address_count, NULL);
+	
+	int rc;
+	if (address_count)
+		rc = async_data_write_start(exch, address_list,
+		    address_count * sizeof(nic_address_t));
+	else
+		rc = EOK;
+	
+	async_exchange_end(exch);
+	
+	sysarg_t res;
+	async_wait_for(message_id, &res);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return (int) res;
+}
+
+/** Determine if broadcast packets are received.
+ *
+ * @param[in]  dev_sess
+ * @param[out] mode     Current operation mode
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_broadcast_get_mode(async_sess_t *dev_sess, nic_broadcast_mode_t *mode)
+{
+	assert(mode);
+	
+	sysarg_t _mode;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_BROADCAST_GET_MODE, &_mode);
+	async_exchange_end(exch);
+	
+	*mode = (nic_broadcast_mode_t) _mode;
+	
+	return rc;
+}
+
+/** Set whether broadcast packets are received.
+ *
+ * @param[in] dev_sess
+ * @param[in] mode     Current operation mode
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_broadcast_set_mode(async_sess_t *dev_sess, nic_broadcast_mode_t mode)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_BROADCAST_SET_MODE, mode);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Determine if defective (erroneous) packets are received.
+ *
+ * @param[in]  dev_sess
+ * @param[out] mode     Bitmask specifying allowed errors
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_defective_get_mode(async_sess_t *dev_sess, uint32_t *mode)
+{
+	assert(mode);
+	
+	sysarg_t _mode;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_DEFECTIVE_GET_MODE, &_mode);
+	async_exchange_end(exch);
+	
+	*mode = (uint32_t) _mode;
+	
+	return rc;
+}
+
+/** Set whether defective (erroneous) packets are received.
+ *
+ * @param[in]  dev_sess
+ * @param[out] mode     Bitmask specifying allowed errors
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_defective_set_mode(async_sess_t *dev_sess, uint32_t mode)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_DEFECTIVE_SET_MODE, mode);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Retrieve the currently blocked source MAC addresses.
+ *
+ * @param[in]  dev_sess
+ * @param[in]  max_count     Maximal number of addresses that could
+ *                           be written into the list buffer.
+ * @param[out] address_list  Buffer for the list (array). Can be NULL.
+ * @param[out] address_count Number of addresses in the list before
+ *                           possible truncation due to the max_count.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_blocked_sources_get(async_sess_t *dev_sess, size_t max_count,
+    nic_address_t *address_list, size_t *address_count)
+{
+	if (!address_list)
+		max_count = 0;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	sysarg_t ac;
+	int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_BLOCKED_SOURCES_GET, max_count, &ac);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	if (address_count)
+		*address_count = (size_t) ac;
+	
+	if ((max_count) && (ac))
+		rc = async_data_read_start(exch, address_list,
+		    max_count * sizeof(nic_address_t));
+	
+	async_exchange_end(exch);
+	return rc;
+}
+
+/** Set which source MACs are blocked
+ *
+ * @param[in] dev_sess
+ * @param[in] address_list  The list of addresses. Can be NULL.
+ * @param[in] address_count Number of addresses in the list.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_blocked_sources_set(async_sess_t *dev_sess,
+    const nic_address_t *address_list, size_t address_count)
+{
+	if (address_list == NULL)
+		address_count = 0;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_BLOCKED_SOURCES_SET, address_count, NULL);
+	
+	int rc;
+	if (address_count)
+		rc = async_data_write_start(exch, address_list,
+			address_count * sizeof(nic_address_t));
+	else
+		rc = EOK;
+	
+	async_exchange_end(exch);
+	
+	sysarg_t res;
+	async_wait_for(message_id, &res);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return (int) res;
+}
+
+/** Request current VLAN filtering mask.
+ *
+ * @param[in]  dev_sess
+ * @param[out] stats    Structure with the statistics
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_vlan_get_mask(async_sess_t *dev_sess, nic_vlan_mask_t *mask)
+{
+	assert(mask);
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_VLAN_GET_MASK);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	rc = async_data_read_start(exch, mask, sizeof(nic_vlan_mask_t));
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Set the mask used for VLAN filtering.
+ *
+ * If NULL, VLAN filtering is disabled.
+ *
+ * @param[in] dev_sess
+ * @param[in] mask     Pointer to mask structure or NULL to disable.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_vlan_set_mask(async_sess_t *dev_sess, const nic_vlan_mask_t *mask)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_VLAN_SET_MASK, mask != NULL, NULL);
+	
+	int rc;
+	if (mask != NULL)
+		rc = async_data_write_start(exch, mask, sizeof(nic_vlan_mask_t));
+	else
+		rc = EOK;
+	
+	async_exchange_end(exch);
+	
+	sysarg_t res;
+	async_wait_for(message_id, &res);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return (int) res;
+}
+
+/** Set VLAN (802.1q) tag.
+ *
+ * Set whether the tag is to be signaled in offload info and
+ * if the tag should be stripped from received frames and added
+ * to sent frames automatically. Not every combination of add
+ * and strip must be supported.
+ *
+ * @param[in] dev_sess
+ * @param[in] tag      VLAN priority (top 3 bits) and
+ *                     the VLAN tag (bottom 12 bits)
+ * @param[in] add      Add the VLAN tag automatically (boolean)
+ * @param[in] strip    Strip the VLAN tag automatically (boolean)
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_vlan_set_tag(async_sess_t *dev_sess, uint16_t tag, int add, int strip)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_VLAN_SET_TAG, (sysarg_t) tag, (sysarg_t) add, (sysarg_t) strip);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Add new Wake-On-LAN virtue.
+ *
+ * @param[in]  dev_sess
+ * @param[in]  type     Type of the virtue
+ * @param[in]  data     Data required for this virtue
+ *                      (depends on type)
+ * @param[in]  length   Length of the data
+ * @param[out] id       Identifier of the new virtue
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_wol_virtue_add(async_sess_t *dev_sess, nic_wv_type_t type,
+    const void *data, size_t length, nic_wv_id_t *id)
+{
+	assert(id);
+	
+	bool send_data = ((data != NULL) && (length != 0));
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	ipc_call_t result;
+	aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_WOL_VIRTUE_ADD, (sysarg_t) type, send_data, &result);
+	
+	sysarg_t res;
+	if (send_data) {
+		int rc = async_data_write_start(exch, data, length);
+		if (rc != EOK) {
+			async_exchange_end(exch);
+			async_wait_for(message_id, &res);
+			return rc;
+		}
+	}
+	
+	async_exchange_end(exch);
+	async_wait_for(message_id, &res);
+	
+	*id = IPC_GET_ARG1(result);
+	return (int) res;
+}
+
+/** Remove Wake-On-LAN virtue.
+ *
+ * @param[in] dev_sess
+ * @param[in] id       Virtue identifier
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_wol_virtue_remove(async_sess_t *dev_sess, nic_wv_id_t id)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_WOL_VIRTUE_REMOVE, (sysarg_t) id);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Get information about virtue.
+ *
+ * @param[in]  dev_sess
+ * @param[in]  id         Virtue identifier
+ * @param[out] type       Type of the filter. Can be NULL.
+ * @param[out] max_length Size of the data buffer.
+ * @param[out] data       Buffer for data used when the
+ *                        virtue was created. Can be NULL.
+ * @param[out] length     Length of the data. Can be NULL.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_wol_virtue_probe(async_sess_t *dev_sess, nic_wv_id_t id,
+    nic_wv_type_t *type, size_t max_length, void *data, size_t *length)
+{
+	sysarg_t _type;
+	sysarg_t _length;
+	
+	if (data == NULL)
+		max_length = 0;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	int rc = async_req_3_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_WOL_VIRTUE_PROBE, (sysarg_t) id, max_length,
+	    &_type, &_length);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	if (type)
+		*type = _type;
+	
+	if (length)
+		*length = _length;
+	
+	if ((max_length) && (_length != 0))
+		rc = async_data_read_start(exch, data, max_length);
+	
+	async_exchange_end(exch);
+	return rc;
+}
+
+/** Get a list of all virtues of the specified type.
+ *
+ * When NIC_WV_NONE is specified as the virtue type the function
+ * lists virtues of all types.
+ *
+ * @param[in]  dev_sess
+ * @param[in]  type      Type of the virtues
+ * @param[in]  max_count Maximum number of ids that can be
+ *                       written into the list buffer.
+ * @param[out] id_list   Buffer for to the list of virtue ids.
+ *                       Can be NULL.
+ * @param[out] id_count  Number of virtue identifiers in the list
+ *                       before possible truncation due to the
+ *                       max_count. Can be NULL.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_wol_virtue_list(async_sess_t *dev_sess, nic_wv_type_t type,
+    size_t max_count, nic_wv_id_t *id_list, size_t *id_count)
+{
+	if (id_list == NULL)
+		max_count = 0;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	sysarg_t count;
+	int rc = async_req_3_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_WOL_VIRTUE_LIST, (sysarg_t) type, max_count, &count);
+	
+	if (id_count)
+		*id_count = (size_t) count;
+	
+	if ((rc != EOK) || (!max_count)) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	rc = async_data_read_start(exch, id_list,
+	    max_count * sizeof(nic_wv_id_t));
+	
+	async_exchange_end(exch);
+	return rc;
+}
+
+/** Get number of virtues that can be enabled yet.
+ *
+ * Count: < 0 => Virtue of this type can be never used
+ *        = 0 => No more virtues can be enabled
+ *        > 0 => #count virtues can be enabled yet
+ *
+ * @param[in]  dev_sess
+ * @param[in]  type     Virtue type
+ * @param[out] count    Number of virtues
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_wol_virtue_get_caps(async_sess_t *dev_sess, nic_wv_type_t type,
+    int *count)
+{
+	assert(count);
+	
+	sysarg_t _count;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_WOL_VIRTUE_GET_CAPS, (sysarg_t) type, &_count);
+	async_exchange_end(exch);
+	
+	*count = (int) _count;
+	return rc;
+}
+
+/** Load the frame that issued the wakeup.
+ *
+ * The NIC can support only matched_type,  only part of the frame
+ * can be available or not at all. Sometimes even the type can be
+ * uncertain -- in this case the matched_type contains NIC_WV_NONE.
+ *
+ * Frame_length can be greater than max_length, but at most max_length
+ * bytes will be copied into the frame buffer.
+ *
+ * Note: Only the type of the filter can be detected, not the concrete
+ * filter, because the driver is probably not running when the wakeup
+ * is issued.
+ *
+ * @param[in]  dev_sess
+ * @param[out] matched_type Type of the filter that issued wakeup.
+ * @param[in]  max_length   Size of the buffer
+ * @param[out] frame        Buffer for the frame. Can be NULL.
+ * @param[out] frame_length Length of the stored frame. Can be NULL.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_wol_load_info(async_sess_t *dev_sess, nic_wv_type_t *matched_type,
+    size_t max_length, uint8_t *frame, size_t *frame_length)
+{
+	assert(matched_type);
+	
+	sysarg_t _matched_type;
+	sysarg_t _frame_length;
+	
+	if (frame == NULL)
+		max_length = 0;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_WOL_LOAD_INFO, max_length, &_matched_type, &_frame_length);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	*matched_type = (nic_wv_type_t) _matched_type;
+	if (frame_length)
+		*frame_length = (size_t) _frame_length;
+	
+	if ((max_length != 0) && (_frame_length != 0))
+		rc = async_data_read_start(exch, frame, max_length);
+	
+	async_exchange_end(exch);
+	return rc;
+}
+
+/** Probe supported options and current setting of offload computations
+ *
+ * @param[in]  dev_sess
+ * @param[out] supported Supported offload options
+ * @param[out] active    Currently active offload options
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_offload_probe(async_sess_t *dev_sess, uint32_t *supported,
+    uint32_t *active)
+{
+	assert(supported);
+	assert(active);
+	
+	sysarg_t _supported;
+	sysarg_t _active;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_OFFLOAD_PROBE, &_supported, &_active);
+	async_exchange_end(exch);
+	
+	*supported = (uint32_t) _supported;
+	*active = (uint32_t) _active;
+	return rc;
+}
+
+/** Set which offload computations can be performed on the NIC.
+ *
+ * @param[in] dev_sess
+ * @param[in] mask     Mask for the options (only those set here will be set)
+ * @param[in] active   Which options should be enabled and which disabled
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_offload_set(async_sess_t *dev_sess, uint32_t mask, uint32_t active)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_3_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_AUTONEG_RESTART, (sysarg_t) mask, (sysarg_t) active);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Query the current interrupt/poll mode of the NIC
+ *
+ * @param[in]  dev_sess
+ * @param[out] mode     Current poll mode
+ * @param[out] period   Period used in periodic polling.
+ *                      Can be NULL.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_poll_get_mode(async_sess_t *dev_sess, nic_poll_mode_t *mode,
+    struct timeval *period)
+{
+	assert(mode);
+	
+	sysarg_t _mode;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_POLL_GET_MODE, period != NULL, &_mode);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	*mode = (nic_poll_mode_t) _mode;
+	
+	if (period != NULL)
+		rc = async_data_read_start(exch, period, sizeof(struct timeval));
+	
+	async_exchange_end(exch);
+	return rc;
+}
+
+/** Set the interrupt/poll mode of the NIC.
+ *
+ * @param[in] dev_sess
+ * @param[in] mode     New poll mode
+ * @param[in] period   Period used in periodic polling. Can be NULL.
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_poll_set_mode(async_sess_t *dev_sess, nic_poll_mode_t mode,
+    const struct timeval *period)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_POLL_SET_MODE, (sysarg_t) mode, period != NULL, NULL);
+	
+	int rc;
+	if (period)
+		rc = async_data_write_start(exch, period, sizeof(struct timeval));
+	else
+		rc = EOK;
+	
+	async_exchange_end(exch);
+	
+	sysarg_t res;
+	async_wait_for(message_id, &res);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return (int) res;
+}
+
+/** Request the driver to poll the NIC.
+ *
+ * @param[in] dev_sess
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_poll_now(async_sess_t *dev_sess)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_POLL_NOW);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/net/packet.c
===================================================================
--- uspace/lib/c/generic/net/packet.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/generic/net/packet.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -36,4 +36,5 @@
  */
 
+#include <assert.h>
 #include <malloc.h>
 #include <mem.h>
@@ -44,29 +45,10 @@
 #include <sys/mman.h>
 
-#include <adt/generic_field.h>
+#include <adt/hash_table.h>
 #include <net/packet.h>
 #include <net/packet_header.h>
 
-/** Packet map page size. */
-#define PACKET_MAP_SIZE	100
-
-/** Returns the packet map page index.
- * @param[in] packet_id The packet identifier.
- */
-#define PACKET_MAP_PAGE(packet_id)	(((packet_id) - 1) / PACKET_MAP_SIZE)
-
-/** Returns the packet index in the corresponding packet map page.
- *  @param[in] packet_id The packet identifier.
- */
-#define PACKET_MAP_INDEX(packet_id)	(((packet_id) - 1) % PACKET_MAP_SIZE)
-
-/** Type definition of the packet map page. */
-typedef packet_t *packet_map_t[PACKET_MAP_SIZE];
-
-/** Packet map.
- * Maps packet identifiers to the packet references.
- * @see generic_field.h
- */
-GENERIC_FIELD_DECLARE(gpm, packet_map_t);
+/** Packet hash table size. */
+#define PACKET_HASH_TABLE_SIZE  128
 
 /** Packet map global data. */
@@ -75,8 +57,49 @@
 	fibril_rwlock_t lock;
 	/** Packet map. */
-	gpm_t packet_map;
+	hash_table_t packet_map;
+	/** Packet map operations */
+	hash_table_operations_t operations;
 } pm_globals;
 
-GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t);
+typedef struct {
+	link_t link;
+	packet_t *packet;
+} pm_entry_t;
+
+/**
+ * Hash function for the packet mapping hash table
+ */
+static hash_index_t pm_hash(unsigned long key[])
+{
+	return (hash_index_t) key[0] % PACKET_HASH_TABLE_SIZE;
+}
+
+/**
+ * Key compare function for the packet mapping hash table
+ */
+static int pm_compare(unsigned long key[], hash_count_t keys, link_t *link)
+{
+	pm_entry_t *entry = list_get_instance(link, pm_entry_t, link);
+	return entry->packet->packet_id == key[0];
+}
+
+/**
+ * Remove callback for the packet mapping hash table
+ */
+static void pm_remove_callback(link_t *link)
+{
+	pm_entry_t *entry = list_get_instance(link, pm_entry_t, link);
+	free(entry);
+}
+
+/**
+ * Wrapper used when destroying the whole table
+ */
+static void pm_free_wrapper(link_t *link, void *ignored)
+{
+	pm_entry_t *entry = list_get_instance(link, pm_entry_t, link);
+	free(entry);
+}
+
 
 /** Initializes the packet map.
@@ -87,10 +110,18 @@
 int pm_init(void)
 {
-	int rc;
+	int rc = EOK;
 
 	fibril_rwlock_initialize(&pm_globals.lock);
 	
 	fibril_rwlock_write_lock(&pm_globals.lock);
-	rc = gpm_initialize(&pm_globals.packet_map);
+	
+	pm_globals.operations.hash = pm_hash;
+	pm_globals.operations.compare = pm_compare;
+	pm_globals.operations.remove_callback = pm_remove_callback;
+
+	if (!hash_table_create(&pm_globals.packet_map, PACKET_HASH_TABLE_SIZE, 1,
+	    &pm_globals.operations))
+		rc = ENOMEM;
+	
 	fibril_rwlock_write_unlock(&pm_globals.lock);
 	
@@ -100,27 +131,26 @@
 /** Finds the packet mapping.
  *
- * @param[in] packet_id	The packet identifier to be found.
- * @return		The found packet reference.
- * @return		NULL if the mapping does not exist.
+ * @param[in] packet_id Packet identifier to be found.
+ *
+ * @return The found packet reference.
+ * @return NULL if the mapping does not exist.
+ *
  */
 packet_t *pm_find(packet_id_t packet_id)
 {
-	packet_map_t *map;
 	packet_t *packet;
-
 	if (!packet_id)
 		return NULL;
 
 	fibril_rwlock_read_lock(&pm_globals.lock);
-	if (packet_id > PACKET_MAP_SIZE * gpm_count(&pm_globals.packet_map)) {
-		fibril_rwlock_read_unlock(&pm_globals.lock);
-		return NULL;
-	}
-	map = gpm_get_index(&pm_globals.packet_map, PACKET_MAP_PAGE(packet_id));
-	if (!map) {
-		fibril_rwlock_read_unlock(&pm_globals.lock);
-		return NULL;
-	}
-	packet = (*map) [PACKET_MAP_INDEX(packet_id)];
+	link_t *link =
+	    hash_table_find(&pm_globals.packet_map, &packet_id);
+	if (link != NULL) {
+		pm_entry_t *entry =
+		    hash_table_get_instance(link, pm_entry_t, link);
+		packet = entry->packet;
+	} else
+		packet = NULL;
+	
 	fibril_rwlock_read_unlock(&pm_globals.lock);
 	return packet;
@@ -129,67 +159,51 @@
 /** Adds the packet mapping.
  *
- * @param[in] packet	The packet to be remembered.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		EINVAL if the packet map is not initialized.
- * @return		ENOMEM if there is not enough memory left.
+ * @param[in] packet Packet to be remembered.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the packet is not valid.
+ * @return ENOMEM if there is not enough memory left.
+ *
  */
 int pm_add(packet_t *packet)
 {
-	packet_map_t *map;
-	int rc;
-
 	if (!packet_is_valid(packet))
 		return EINVAL;
-
+	
 	fibril_rwlock_write_lock(&pm_globals.lock);
-
-	if (PACKET_MAP_PAGE(packet->packet_id) <
-	    gpm_count(&pm_globals.packet_map)) {
-		map = gpm_get_index(&pm_globals.packet_map,
-		    PACKET_MAP_PAGE(packet->packet_id));
-	} else {
-		do {
-			map = (packet_map_t *) malloc(sizeof(packet_map_t));
-			if (!map) {
-				fibril_rwlock_write_unlock(&pm_globals.lock);
-				return ENOMEM;
-			}
-			bzero(map, sizeof(packet_map_t));
-			rc = gpm_add(&pm_globals.packet_map, map);
-			if (rc < 0) {
-				fibril_rwlock_write_unlock(&pm_globals.lock);
-				free(map);
-				return rc;
-			}
-		} while (PACKET_MAP_PAGE(packet->packet_id) >=
-		    gpm_count(&pm_globals.packet_map));
+	pm_entry_t *entry = malloc(sizeof (pm_entry_t));
+	if (entry == NULL) {
+		fibril_rwlock_write_unlock(&pm_globals.lock);
+		return ENOMEM;
 	}
-
-	(*map) [PACKET_MAP_INDEX(packet->packet_id)] = packet;
+	
+	entry->packet = packet;
+	hash_table_insert(&pm_globals.packet_map, &packet->packet_id,
+	    &entry->link);
 	fibril_rwlock_write_unlock(&pm_globals.lock);
 	return EOK;
 }
 
-/** Releases the packet map. */
+/** Remove the packet mapping
+ *
+ * @param[in] packet The packet to be removed
+ *
+ */
+void pm_remove(packet_t *packet)
+{
+	assert(packet_is_valid(packet));
+	
+	fibril_rwlock_write_lock(&pm_globals.lock);
+	hash_table_remove(&pm_globals.packet_map, &packet->packet_id, 1);
+	fibril_rwlock_write_unlock(&pm_globals.lock);
+}
+
+/** Release the packet map. */
 void pm_destroy(void)
 {
-	int count;
-	int index;
-	packet_map_t *map;
-	packet_t *packet;
-
 	fibril_rwlock_write_lock(&pm_globals.lock);
-	count = gpm_count(&pm_globals.packet_map);
-	while (count > 0) {
-		map = gpm_get_index(&pm_globals.packet_map, count - 1);
-		for (index = PACKET_MAP_SIZE - 1; index >= 0; --index) {
-			packet = (*map)[index];
-			if (packet_is_valid(packet))
-				munmap(packet, packet->length);
-		}
-	}
-	gpm_destroy(&pm_globals.packet_map, free);
-	/* leave locked */
+	hash_table_apply(&pm_globals.packet_map, pm_free_wrapper, NULL);
+	hash_table_destroy(&pm_globals.packet_map);
+	/* Leave locked */
 }
 
@@ -199,46 +213,52 @@
  * The packet is inserted right before the packets of the same order value.
  *
- * @param[in,out] first	The first packet of the queue. Sets the first packet of
- *			the queue. The original first packet may be shifted by
- *			the new packet.
- * @param[in] packet	The packet to be added.
- * @param[in] order	The packet order value.
- * @param[in] metric	The metric value of the packet.
- * @return		EOK on success.
- * @return		EINVAL if the first parameter is NULL.
- * @return		EINVAL if the packet is not valid.
+ * @param[in,out] first First packet of the queue. Sets the first
+ *                      packet of the queue. The original first packet
+ *                      may be shifted by the new packet.
+ * @param[in] packet    Packet to be added.
+ * @param[in] order     Packet order value.
+ * @param[in] metric    Metric value of the packet.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the first parameter is NULL.
+ * @return EINVAL if the packet is not valid.
+ *
  */
 int pq_add(packet_t **first, packet_t *packet, size_t order, size_t metric)
 {
-	packet_t *item;
-
-	if (!first || !packet_is_valid(packet))
+	if ((!first) || (!packet_is_valid(packet)))
 		return EINVAL;
-
+	
 	pq_set_order(packet, order, metric);
 	if (packet_is_valid(*first)) {
-		item = * first;
+		packet_t *cur = *first;
+		
 		do {
-			if (item->order < order) {
-				if (item->next) {
-					item = pm_find(item->next);
-				} else {
-					item->next = packet->packet_id;
-					packet->previous = item->packet_id;
+			if (cur->order < order) {
+				if (cur->next)
+					cur = pm_find(cur->next);
+				else {
+					cur->next = packet->packet_id;
+					packet->previous = cur->packet_id;
+					
 					return EOK;
 				}
 			} else {
-				packet->previous = item->previous;
-				packet->next = item->packet_id;
-				item->previous = packet->packet_id;
-				item = pm_find(packet->previous);
-				if (item)
-					item->next = packet->packet_id;
+				packet->previous = cur->previous;
+				packet->next = cur->packet_id;
+				
+				cur->previous = packet->packet_id;
+				cur = pm_find(packet->previous);
+				
+				if (cur)
+					cur->next = packet->packet_id;
 				else
 					*first = packet;
+				
 				return EOK;
 			}
-		} while (packet_is_valid(item));
+		} while (packet_is_valid(cur));
 	}
+	
 	*first = packet;
 	return EOK;
@@ -312,10 +332,11 @@
 
 	next = pm_find(packet->next);
-	if (next) {
+	if (next)
 		next->previous = packet->previous;
-		previous = pm_find(next->previous);
-		if (previous)
-			previous->next = next->packet_id;
-	}
+	
+	previous = pm_find(packet->previous);
+	if (previous)
+		previous->next = packet->next ;
+	
 	packet->previous = 0;
 	packet->next = 0;
Index: uspace/lib/c/include/device/nic.h
===================================================================
--- uspace/lib/c/include/device/nic.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
+++ uspace/lib/c/include/device/nic.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2010 Radim Vansa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_DEVICE_NIC_H_
+#define LIBC_DEVICE_NIC_H_
+
+#include <async.h>
+#include <net/device.h>
+#include <net/packet.h>
+#include <ipc/services.h>
+
+typedef enum {
+	NIC_SEND_MESSAGE = 0,
+	NIC_CONNECT_TO_NIL,
+	NIC_GET_STATE,
+	NIC_SET_STATE,
+	NIC_GET_ADDRESS,
+	NIC_SET_ADDRESS,
+	NIC_GET_STATS,
+	NIC_GET_DEVICE_INFO,
+	NIC_GET_CABLE_STATE,
+	NIC_GET_OPERATION_MODE,
+	NIC_SET_OPERATION_MODE,
+	NIC_AUTONEG_ENABLE,
+	NIC_AUTONEG_DISABLE,
+	NIC_AUTONEG_PROBE,
+	NIC_AUTONEG_RESTART,
+	NIC_GET_PAUSE,
+	NIC_SET_PAUSE,
+	NIC_UNICAST_GET_MODE,
+	NIC_UNICAST_SET_MODE,
+	NIC_MULTICAST_GET_MODE,
+	NIC_MULTICAST_SET_MODE,
+	NIC_BROADCAST_GET_MODE,
+	NIC_BROADCAST_SET_MODE,
+	NIC_DEFECTIVE_GET_MODE,
+	NIC_DEFECTIVE_SET_MODE,
+	NIC_BLOCKED_SOURCES_GET,
+	NIC_BLOCKED_SOURCES_SET,
+	NIC_VLAN_GET_MASK,
+	NIC_VLAN_SET_MASK,
+	NIC_VLAN_SET_TAG,
+	NIC_WOL_VIRTUE_ADD,
+	NIC_WOL_VIRTUE_REMOVE,
+	NIC_WOL_VIRTUE_PROBE,
+	NIC_WOL_VIRTUE_LIST,
+	NIC_WOL_VIRTUE_GET_CAPS,
+	NIC_WOL_LOAD_INFO,
+	NIC_OFFLOAD_PROBE,
+	NIC_OFFLOAD_SET,
+	NIC_POLL_GET_MODE,
+	NIC_POLL_SET_MODE,
+	NIC_POLL_NOW
+} nic_funcs_t;
+
+extern int nic_send_message(async_sess_t *, packet_id_t);
+extern int nic_connect_to_nil(async_sess_t *, services_t, nic_device_id_t);
+extern int nic_get_state(async_sess_t *, nic_device_state_t *);
+extern int nic_set_state(async_sess_t *, nic_device_state_t);
+extern int nic_get_address(async_sess_t *, nic_address_t *);
+extern int nic_set_address(async_sess_t *, const nic_address_t *);
+extern int nic_get_stats(async_sess_t *, nic_device_stats_t *);
+extern int nic_get_device_info(async_sess_t *, nic_device_info_t *);
+extern int nic_get_cable_state(async_sess_t *, nic_cable_state_t *);
+
+extern int nic_get_operation_mode(async_sess_t *, int *, nic_channel_mode_t *,
+    nic_role_t *);
+extern int nic_set_operation_mode(async_sess_t *, int, nic_channel_mode_t,
+    nic_role_t);
+extern int nic_autoneg_enable(async_sess_t *, uint32_t);
+extern int nic_autoneg_disable(async_sess_t *);
+extern int nic_autoneg_probe(async_sess_t *, uint32_t *, uint32_t *,
+    nic_result_t *, nic_result_t *);
+extern int nic_autoneg_restart(async_sess_t *);
+extern int nic_get_pause(async_sess_t *, nic_result_t *, nic_result_t *,
+    uint16_t *);
+extern int nic_set_pause(async_sess_t *, int, int, uint16_t);
+
+extern int nic_unicast_get_mode(async_sess_t *, nic_unicast_mode_t *, size_t,
+    nic_address_t *, size_t *);
+extern int nic_unicast_set_mode(async_sess_t *, nic_unicast_mode_t,
+    const nic_address_t *, size_t);
+extern int nic_multicast_get_mode(async_sess_t *, nic_multicast_mode_t *,
+    size_t, nic_address_t *, size_t *);
+extern int nic_multicast_set_mode(async_sess_t *, nic_multicast_mode_t,
+    const nic_address_t *, size_t);
+extern int nic_broadcast_get_mode(async_sess_t *, nic_broadcast_mode_t *);
+extern int nic_broadcast_set_mode(async_sess_t *, nic_broadcast_mode_t);
+extern int nic_defective_get_mode(async_sess_t *, uint32_t *);
+extern int nic_defective_set_mode(async_sess_t *, uint32_t);
+extern int nic_blocked_sources_get(async_sess_t *, size_t, nic_address_t *,
+    size_t *);
+extern int nic_blocked_sources_set(async_sess_t *, const nic_address_t *,
+    size_t);
+
+extern int nic_vlan_get_mask(async_sess_t *, nic_vlan_mask_t *);
+extern int nic_vlan_set_mask(async_sess_t *, const nic_vlan_mask_t *);
+extern int nic_vlan_set_tag(async_sess_t *, uint16_t, int, int);
+
+extern int nic_wol_virtue_add(async_sess_t *, nic_wv_type_t, const void *,
+    size_t, nic_wv_id_t *);
+extern int nic_wol_virtue_remove(async_sess_t *, nic_wv_id_t);
+extern int nic_wol_virtue_probe(async_sess_t *, nic_wv_id_t, nic_wv_type_t *,
+    size_t, void *, size_t *);
+extern int nic_wol_virtue_list(async_sess_t *, nic_wv_type_t, size_t,
+    nic_wv_id_t *, size_t *);
+extern int nic_wol_virtue_get_caps(async_sess_t *, nic_wv_type_t, int *);
+extern int nic_wol_load_info(async_sess_t *, nic_wv_type_t *, size_t, uint8_t *,
+    size_t *);
+
+extern int nic_offload_probe(async_sess_t *, uint32_t *, uint32_t *);
+extern int nic_offload_set(async_sess_t *, uint32_t, uint32_t);
+
+extern int nic_poll_get_mode(async_sess_t *, nic_poll_mode_t *,
+    struct timeval *);
+extern int nic_poll_set_mode(async_sess_t *, nic_poll_mode_t,
+    const struct timeval *);
+extern int nic_poll_now(async_sess_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -36,6 +36,10 @@
 typedef enum {
 	HW_RES_DEV_IFACE = 0,
+	/** Character device interface */
 	CHAR_DEV_IFACE,
-
+	
+	/** Network interface controller interface */
+	NIC_DEV_IFACE,
+	
 	/** Interface provided by any PCI device. */
 	PCI_DEV_IFACE,
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/include/ipc/devman.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -146,4 +146,5 @@
 typedef enum {
 	DRIVER_DEV_ADD = IPC_FIRST_USER_METHOD,
+	DRIVER_DEV_ADDED,
 	DRIVER_DEV_REMOVE,
 	DRIVER_DEV_GONE,
Index: uspace/lib/c/include/ipc/il.h
===================================================================
--- uspace/lib/c/include/ipc/il.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/include/ipc/il.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -54,4 +54,10 @@
 	NET_IL_MTU_CHANGED,
 	
+	/**
+	 * Device address changed message
+	 * @see il_addr_changed_msg()
+	 */
+	NET_IL_ADDR_CHANGED,
+
 	/** Packet received message.
 	 * @see il_received_msg()
Index: uspace/lib/c/include/ipc/net.h
===================================================================
--- uspace/lib/c/include/ipc/net.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/include/ipc/net.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -277,5 +277,5 @@
  *
  */
-#define IPC_GET_DEVICE(call)  ((device_id_t) IPC_GET_ARG1(call))
+#define IPC_GET_DEVICE(call)  ((nic_device_id_t) IPC_GET_ARG1(call))
 
 /** Return the packet identifier message argument.
@@ -298,5 +298,33 @@
  *
  */
-#define IPC_GET_STATE(call)  ((device_state_t) IPC_GET_ARG2(call))
+#define IPC_GET_STATE(call)  ((nic_device_state_t) IPC_GET_ARG2(call))
+
+/** Return the device handle argument
+ *
+ * @param[in] call Message call structure
+ *
+ */
+#define IPC_GET_DEVICE_HANDLE(call) ((devman_handle_t) IPC_GET_ARG2(call))
+
+/** Return the device driver service message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_SERVICE(call)  ((services_t) IPC_GET_ARG3(call))
+
+/** Return the target service message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_TARGET(call)  ((services_t) IPC_GET_ARG3(call))
+
+/** Return the sender service message argument.
+ *
+ * @param[in] call Message call structure.
+ *
+ */
+#define IPC_GET_SENDER(call)  ((services_t) IPC_GET_ARG3(call))
 
 /** Return the maximum transmission unit message argument.
@@ -305,26 +333,5 @@
  *
  */
-#define IPC_GET_MTU(call)  ((size_t) IPC_GET_ARG2(call))
-
-/** Return the device driver service message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_SERVICE(call)  ((services_t) IPC_GET_ARG3(call))
-
-/** Return the target service message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_TARGET(call)  ((services_t) IPC_GET_ARG3(call))
-
-/** Return the sender service message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_SENDER(call)  ((services_t) IPC_GET_ARG3(call))
+#define IPC_GET_MTU(call)  ((size_t) IPC_GET_ARG3(call))
 
 /** Return the error service message argument.
Index: uspace/lib/c/include/ipc/net_net.h
===================================================================
--- uspace/lib/c/include/ipc/net_net.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/include/ipc/net_net.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -43,14 +43,18 @@
 /** Networking subsystem central module messages. */
 typedef enum {
-	/** Returns the general configuration
+	/** Return general configuration
 	 * @see net_get_conf_req()
 	 */
 	NET_NET_GET_CONF = NET_FIRST,
-	/** Returns the device specific configuration
+	/** Return device specific configuration
 	 * @see net_get_device_conf_req()
 	 */
 	NET_NET_GET_DEVICE_CONF,
-	/** Starts the networking stack. */
-	NET_NET_STARTUP,
+	/** Return number of mastered devices */
+	NET_NET_GET_DEVICES_COUNT,
+	/** Return names and device IDs of all devices */
+	NET_NET_GET_DEVICES,
+	/** Notify the networking service about a ready device */
+	NET_NET_DRIVER_READY
 } net_messages;
 
Index: uspace/lib/c/include/ipc/nil.h
===================================================================
--- uspace/lib/c/include/ipc/nil.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/include/ipc/nil.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -70,4 +70,8 @@
 	 */
 	NET_NIL_BROADCAST_ADDR,
+	/** Device has changed address
+	 * @see nil_addr_changed_msg()
+	 */
+	NET_NIL_ADDR_CHANGED
 } nil_messages;
 
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/include/ipc/services.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -49,6 +49,4 @@
 	SERVICE_CLIPBOARD  = FOURCC('c', 'l', 'i', 'p'),
 	SERVICE_NETWORKING = FOURCC('n', 'e', 't', ' '),
-	SERVICE_LO         = FOURCC('l', 'o', ' ', ' '),
-	SERVICE_NE2000     = FOURCC('n', 'e', '2', 'k'),
 	SERVICE_ETHERNET   = FOURCC('e', 't', 'h', ' '),
 	SERVICE_NILDUMMY   = FOURCC('n', 'i', 'l', 'd'),
Index: uspace/lib/c/include/net/device.h
===================================================================
--- uspace/lib/c/include/net/device.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/include/net/device.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Radim Vansa
  * All rights reserved.
  *
@@ -39,44 +40,125 @@
 
 #include <adt/int_map.h>
+#include <net/eth_phys.h>
+
+/** Ethernet address length. */
+#define ETH_ADDR  6
+
+/** MAC printing format */
+#define PRIMAC  "%02x:%02x:%02x:%02x:%02x:%02x"
+
+/** MAC arguments */
+#define ARGSMAC(__a) \
+	(__a)[0], (__a)[1], (__a)[2], (__a)[3], (__a)[4], (__a)[5]
 
 /** Device identifier to generic type map declaration. */
-#define DEVICE_MAP_DECLARE	INT_MAP_DECLARE
+#define DEVICE_MAP_DECLARE  INT_MAP_DECLARE
 
 /** Device identifier to generic type map implementation. */
-#define DEVICE_MAP_IMPLEMENT	INT_MAP_IMPLEMENT
+#define DEVICE_MAP_IMPLEMENT  INT_MAP_IMPLEMENT
+
+/** Max length of any hw nic address (currently only eth) */
+#define NIC_MAX_ADDRESS_LENGTH  16
 
 /** Invalid device identifier. */
-#define DEVICE_INVALID_ID	(-1)
+#define NIC_DEVICE_INVALID_ID  (-1)
+
+#define NIC_VENDOR_MAX_LENGTH         64
+#define NIC_MODEL_MAX_LENGTH          64
+#define NIC_PART_NUMBER_MAX_LENGTH    64
+#define NIC_SERIAL_NUMBER_MAX_LENGTH  64
+
+/**
+ * The bitmap uses single bit for each of the 2^12 = 4096 possible VLAN tags.
+ * This means its size is 4096/8 = 512 bytes.
+ */
+#define NIC_VLAN_BITMAP_SIZE  512
+
+#define NIC_DEVICE_PRINT_FMT  "%x"
 
 /** Device identifier type. */
-typedef int device_id_t;
-
-/** Device state type. */
-typedef enum device_state device_state_t;
-
-/** Type definition of the device usage statistics.
- * @see device_stats
- */
-typedef struct device_stats device_stats_t;
+typedef int nic_device_id_t;
+
+/**
+ * Structure covering the MAC address.
+ */
+typedef struct nic_address {
+	uint8_t address[ETH_ADDR];
+} nic_address_t;
 
 /** Device state. */
-enum device_state {
-	/** Device not present or not initialized. */
-	NETIF_NULL = 0,
-	/** Device present and stopped. */
-	NETIF_STOPPED,
-	/** Device present and active. */
-	NETIF_ACTIVE,
-	/** Device present but unable to transmit. */
-	NETIF_CARRIER_LOST
-};
+typedef enum nic_device_state {
+	/**
+	 * Device present and stopped. Moving device to this state means to discard
+	 * all settings and WOL virtues, rebooting the NIC to state as if the
+	 * computer just booted (or the NIC was just inserted in case of removable
+	 * NIC).
+	 */
+	NIC_STATE_STOPPED,
+	/**
+	 * If the NIC is in this state no packets (frames) are transmitted nor
+	 * received. However, the settings are not restarted. You can use this state
+	 * to temporarily disable transmition/reception or atomically (with respect
+	 * to incoming/outcoming packets) change frames acceptance etc.
+	 */
+	NIC_STATE_DOWN,
+	/** Device is normally operating. */
+	NIC_STATE_ACTIVE,
+	/** Just a constant to limit the state numbers */
+	NIC_STATE_MAX,
+} nic_device_state_t;
+
+/**
+ * Channel operating mode used on the medium.
+ */
+typedef enum {
+	NIC_CM_UNKNOWN,
+	NIC_CM_FULL_DUPLEX,
+	NIC_CM_HALF_DUPLEX,
+	NIC_CM_SIMPLEX
+} nic_channel_mode_t;
+
+/**
+ * Role for the device (used e.g. for 1000Gb ethernet)
+ */
+typedef enum {
+	NIC_ROLE_UNKNOWN,
+	NIC_ROLE_AUTO,
+	NIC_ROLE_MASTER,
+	NIC_ROLE_SLAVE
+} nic_role_t;
+
+/**
+ * Current state of the cable in the device
+ */
+typedef enum {
+	NIC_CS_UNKNOWN,
+	NIC_CS_PLUGGED,
+	NIC_CS_UNPLUGGED
+} nic_cable_state_t;
+
+/**
+ * Result of the requested operation
+ */
+typedef enum {
+	/** Successfully disabled */
+	NIC_RESULT_DISABLED,
+	/** Successfully enabled */
+	NIC_RESULT_ENABLED,
+	/** Not supported at all */
+	NIC_RESULT_NOT_SUPPORTED,
+	/** Temporarily not available */
+	NIC_RESULT_NOT_AVAILABLE,
+	/** Result extensions */
+	NIC_RESULT_FIRST_EXTENSION
+} nic_result_t;
 
 /** Device usage statistics. */
-struct device_stats {
-	/** Total packets received. */
+typedef struct nic_device_stats {
+	/** Total packets received (accepted). */
 	unsigned long receive_packets;
 	/** Total packets transmitted. */
 	unsigned long send_packets;
-	/** Total bytes received. */
+	/** Total bytes received (accepted). */
 	unsigned long receive_bytes;
 	/** Total bytes transmitted. */
@@ -86,12 +168,20 @@
 	/** Packet transmition problems counter. */
 	unsigned long send_errors;
-	/** No space in buffers counter. */
+	/** Number of frames dropped due to insufficient space in RX buffers */
 	unsigned long receive_dropped;
-	/** No space available counter. */
+	/** Number of frames dropped due to insufficient space in TX buffers */
 	unsigned long send_dropped;
-	/** Total multicast packets received. */
-	unsigned long multicast;
+	/** Total multicast packets received (accepted). */
+	unsigned long receive_multicast;
+	/** Total broadcast packets received (accepted). */
+	unsigned long receive_broadcast;
 	/** The number of collisions due to congestion on the medium. */
 	unsigned long collisions;
+	/** Unicast packets received but not accepted (filtered) */
+	unsigned long receive_filtered_unicast;
+	/** Multicast packets received but not accepted (filtered) */
+	unsigned long receive_filtered_multicast;
+	/** Broadcast packets received but not accepted (filtered) */
+	unsigned long receive_filtered_broadcast;
 
 	/* detailed receive_errors */
@@ -129,5 +219,175 @@
 	/** Total compressed packet transmitted. */
 	unsigned long send_compressed;
-};
+} nic_device_stats_t;
+
+/**
+ * Information about the NIC that never changes - name, vendor, model,
+ * capabilites and so on.
+ */
+typedef struct nic_device_info {
+	/* Device identification */
+	char vendor_name[NIC_VENDOR_MAX_LENGTH];
+	char model_name[NIC_MODEL_MAX_LENGTH];
+	char part_number[NIC_PART_NUMBER_MAX_LENGTH];
+	char serial_number[NIC_SERIAL_NUMBER_MAX_LENGTH];
+	uint16_t vendor_id;
+	uint16_t device_id;
+	uint16_t subsystem_vendor_id;
+	uint16_t subsystem_id;
+	/* Device capabilities */
+	uint16_t ethernet_support[ETH_PHYS_LAYERS];
+
+	/** The mask of all modes which the device can advertise
+	 *
+	 *  see ETH_AUTONEG_ macros in net/eth_phys.h of libc
+	 */
+	uint32_t autoneg_support;
+} nic_device_info_t;
+
+/**
+ * Specifies which unicast frames is the NIC receiving.
+ */
+typedef enum nic_unicast_mode {
+	NIC_UNICAST_UNKNOWN,
+	/** No unicast frames are received */
+	NIC_UNICAST_BLOCKED,
+	/** Only the frames with this NIC's MAC as destination are received */
+	NIC_UNICAST_DEFAULT,
+	/**
+	 * Both frames with this NIC's MAC and those specified in the list are
+	 * received
+	 */
+	NIC_UNICAST_LIST,
+	/** All unicast frames are received */
+	NIC_UNICAST_PROMISC
+} nic_unicast_mode_t;
+
+typedef enum nic_multicast_mode {
+	NIC_MULTICAST_UNKNOWN,
+	/** No multicast frames are received */
+	NIC_MULTICAST_BLOCKED,
+	/** Frames with multicast addresses specified in this list are received */
+	NIC_MULTICAST_LIST,
+	/** All multicast frames are received */
+	NIC_MULTICAST_PROMISC
+} nic_multicast_mode_t;
+
+typedef enum nic_broadcast_mode {
+	NIC_BROADCAST_UNKNOWN,
+	/** Broadcast frames are dropped */
+	NIC_BROADCAST_BLOCKED,
+	/** Broadcast frames are received */
+	NIC_BROADCAST_ACCEPTED
+} nic_broadcast_mode_t;
+
+/**
+ * Structure covering the bitmap with VLAN tags.
+ */
+typedef struct nic_vlan_mask {
+	uint8_t bitmap[NIC_VLAN_BITMAP_SIZE];
+} nic_vlan_mask_t;
+
+/* WOL virtue identifier */
+typedef unsigned int nic_wv_id_t;
+
+/**
+ * WOL virtue types defining the interpretation of data passed to the virtue.
+ * Those tagged with S can have only single virtue active at one moment, those
+ * tagged with M can have multiple ones.
+ */
+typedef enum nic_wv_type {
+	/**
+	 * Used for deletion of the virtue - in this case the mask, data and length
+	 * arguments are ignored.
+	 */
+	NIC_WV_NONE,
+	/** S
+	 * Enabled <=> wakeup upon link change
+	 */
+	NIC_WV_LINK_CHANGE,
+	/** S
+	 * If this virtue is set up, wakeup can be issued by a magic packet frame.
+	 * If the data argument is not NULL, it must contain
+	 * nic_wv_magic_packet_data structure with the SecureOn password.
+	 */
+	NIC_WV_MAGIC_PACKET,
+	/** M
+	 * If the virtue is set up, wakeup can be issued by a frame targeted to
+	 * device with MAC address specified in data. The data must contain
+	 * nic_address_t structure.
+	 */
+	NIC_WV_DESTINATION,
+	/** S
+	 * Enabled <=> wakeup upon receiving broadcast frame
+	 */
+	NIC_WV_BROADCAST,
+	/** S
+	 * Enabled <=> wakeup upon receiving ARP Request
+	 */
+	NIC_WV_ARP_REQUEST,
+	/** M
+	 * If enabled, the wakeup is issued upon receiving frame with an IPv4 packet
+	 * with IPv4 address specified in data. The data must contain
+	 * nic_wv_ipv4_data structure.
+	 */
+	NIC_WV_DIRECTED_IPV4,
+	/** M
+	 * If enabled, the wakeup is issued upon receiving frame with an IPv4 packet
+	 * with IPv6 address specified in data. The data must contain
+	 * nic_wv_ipv6_data structure.
+	 */
+	NIC_WV_DIRECTED_IPV6,
+	/** M
+	 * First length/2 bytes in the argument are interpreted as mask, second
+	 * length/2 bytes are interpreted as content.
+	 * If enabled, the wakeup is issued upon receiving frame where the bytes
+	 * with non-zero value in the mask equal to those in the content.
+	 */
+	NIC_WV_FULL_MATCH,
+	/**
+	 * Dummy value, do not use.
+	 */
+	NIC_WV_MAX
+} nic_wv_type_t;
+
+/**
+ * Specifies the interrupt/polling mode used by the driver and NIC
+ */
+typedef enum nic_poll_mode {
+	/**
+	 * NIC issues interrupts upon events.
+	 */
+	NIC_POLL_IMMEDIATE,
+	/**
+	 * Some uspace app calls nic_poll_now(...) in order to check the NIC state
+	 * - no interrupts are received from the NIC.
+	 */
+	NIC_POLL_ON_DEMAND,
+	/**
+	 * The driver itself issues a poll request in a periodic manner. It is
+	 * allowed to use hardware timer if the NIC supports it.
+	 */
+	NIC_POLL_PERIODIC,
+	/**
+	 * The driver itself issued a poll request in a periodic manner. The driver
+	 * must create software timer, internal hardware timer of NIC must not be
+	 * used even if the NIC supports it.
+	 */
+	NIC_POLL_SOFTWARE_PERIODIC
+} nic_poll_mode_t;
+
+static inline const char *nic_device_state_to_string(nic_device_state_t state)
+{
+	switch (state) {
+	case NIC_STATE_STOPPED:
+		return "stopped";
+	case NIC_STATE_DOWN:
+		return "down";
+	case NIC_STATE_ACTIVE:
+		return "active";
+	default:
+		return "undefined";
+	}
+}
 
 #endif
Index: uspace/lib/c/include/net/eth_phys.h
===================================================================
--- uspace/lib/c/include/net/eth_phys.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
+++ uspace/lib/c/include/net/eth_phys.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2011 Radim Vansa
+ * Copyright (c) 2011 Jiri Michalec
+ * 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.
+ */
+
+#ifndef LIBC_NET_ETH_PHYS_H_
+#define LIBC_NET_ETH_PHYS_H_
+
+#include <sys/types.h>
+
+/*****************************************************/
+/* Definitions of possible supported physical layers */
+/*****************************************************/
+
+/* Ethernet physical layers */
+#define ETH_OLD          0
+#define ETH_10M          1
+#define ETH_100M         2
+#define ETH_1000M        3
+#define ETH_10G          4
+#define ETH_40G_100G     5
+/* 6, 7 reserved for future use */
+#define ETH_PHYS_LAYERS  8
+
+/* < 10Mbs ethernets */
+#define ETH_EXPERIMENTAL     0x0001
+#define ETH_1BASE5           0x0002
+/* 10Mbs ethernets */
+#define ETH_10BASE5          0x0001
+#define ETH_10BASE2          0x0002
+#define ETH_10BROAD36        0x0004
+#define ETH_STARLAN_10       0x0008
+#define ETH_LATTISNET        0x0010
+#define ETH_10BASE_T         0x0020
+#define ETH_FOIRL            0x0040
+#define ETH_10BASE_FL        0x0080
+#define ETH_10BASE_FB        0x0100
+#define ETH_10BASE_FP        0x0200
+/* 100Mbs (fast) ethernets */
+#define ETH_100BASE_TX       0x0001
+#define ETH_100BASE_T4       0x0002
+#define ETH_100BASE_T2       0x0004
+#define ETH_100BASE_FX       0x0008
+#define ETH_100BASE_SX       0x0010
+#define ETH_100BASE_BX10     0x0020
+#define ETH_100BASE_LX10     0x0040
+#define ETH_100BASE_VG       0x0080
+/* 1000Mbs (gigabit) ethernets */
+#define ETH_1000BASE_T       0x0001
+#define ETH_1000BASE_TX      0x0002
+#define ETH_1000BASE_SX      0x0004
+#define ETH_1000BASE_LX      0x0008
+#define ETH_1000BASE_LH      0x0010
+#define ETH_1000BASE_CX      0x0020
+#define ETH_1000BASE_BX10    0x0040
+#define ETH_1000BASE_LX10    0x0080
+#define ETH_1000BASE_PX10_D  0x0100
+#define ETH_1000BASE_PX10_U  0x0200
+#define ETH_1000BASE_PX20_D  0x0400
+#define ETH_1000BASE_PX20_U  0x0800
+#define ETH_1000BASE_ZX      0x1000
+#define ETH_1000BASE_KX      0x2000
+/* 10Gbs ethernets */
+#define ETH_10GBASE_SR       0x0001
+#define ETH_10GBASE_LX4      0x0002
+#define ETH_10GBASE_LR       0x0004
+#define ETH_10GBASE_ER       0x0008
+#define ETH_10GBASE_SW       0x0010
+#define ETH_10GBASE_LW       0x0020
+#define ETH_10GBASE_EW       0x0040
+#define ETH_10GBASE_CX4      0x0080
+#define ETH_10GBASE_T        0x0100
+#define ETH_10GBASE_LRM      0x0200
+#define ETH_10GBASE_KX4      0x0400
+#define ETH_10GBASE_KR       0x0800
+/* 40Gbs and 100Gbs ethernets */
+#define ETH_40GBASE_SR4      0x0001
+#define ETH_40GBASE_LR4      0x0002
+#define ETH_40GBASE_CR4      0x0004
+#define ETH_40GBASE_KR4      0x0008
+#define ETH_100GBASE_SR10    0x0010
+#define ETH_100GBASE_LR4     0x0020
+#define ETH_100GBASE_ER4     0x0040
+#define ETH_100GBASE_CR10    0x0080
+
+/******************************************/
+/* Auto-negotiation advertisement options */
+/******************************************/
+
+#define ETH_AUTONEG_10BASE_T_HALF    UINT32_C(0x00000001)
+#define ETH_AUTONEG_10BASE_T_FULL    UINT32_C(0x00000002)
+#define ETH_AUTONEG_100BASE_TX_HALF  UINT32_C(0x00000004)
+#define ETH_AUTONEG_100BASE_T4_HALF  UINT32_C(0x00000008)
+#define ETH_AUTONEG_100BASE_T2_HALF  UINT32_C(0x00000010)
+#define ETH_AUTONEG_100BASE_TX_FULL  UINT32_C(0x00000020)
+#define ETH_AUTONEG_100BASE_T2_FULL  UINT32_C(0x00000040)
+#define ETH_AUTONEG_1000BASE_T_HALF  UINT32_C(0x00000080)
+#define ETH_AUTONEG_1000BASE_T_FULL  UINT32_C(0x00000100)
+
+/** Symetric pause packet (802.3x standard) */
+#define ETH_AUTONEG_PAUSE_SYMETRIC   UINT32_C(0x10000000)
+/** Asymetric pause packet (802.3z standard, gigabit ethernet) */
+#define ETH_AUTONEG_PAUSE_ASYMETRIC  UINT32_C(0x20000000)
+
+#define ETH_AUTONEG_MODE_MASK      UINT32_C(0x0FFFFFFF)
+#define ETH_AUTONEG_FEATURES_MASK  UINT32_C(~(ETH_AUTONEG_MODE_MASK))
+
+#define ETH_AUTONEG_MODES  9
+
+struct eth_autoneg_map {
+	uint32_t value;
+	const char *name;
+};
+
+extern const char *ethernet_names[8][17];
+extern const struct eth_autoneg_map ethernet_autoneg_mapping[ETH_AUTONEG_MODES];
+
+#endif
Index: uspace/lib/c/include/net/packet.h
===================================================================
--- uspace/lib/c/include/net/packet.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/include/net/packet.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -41,5 +41,5 @@
  * Value zero is used as an invalid identifier.
  */
-typedef int packet_id_t;
+typedef unsigned long packet_id_t;
 
 /** Type definition of the packet.
@@ -71,4 +71,5 @@
 extern packet_t *pm_find(packet_id_t);
 extern int pm_add(packet_t *);
+extern void pm_remove(packet_t *);
 extern int pm_init(void);
 extern void pm_destroy(void);
Index: uspace/lib/c/include/net/packet_header.h
===================================================================
--- uspace/lib/c/include/net/packet_header.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/c/include/net/packet_header.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -61,4 +61,7 @@
 #define PACKET_MAGIC_VALUE	0x11227788
 
+/** Maximum total length of the packet */
+#define PACKET_MAX_LENGTH  65536
+
 /** Packet header. */
 struct packet {
@@ -85,4 +88,10 @@
 	 */
 	size_t length;
+
+	/** Offload info provided by the NIC */
+	uint32_t offload_info;
+
+	/** Mask which bits in offload info are valid */
+	uint32_t offload_mask;
 
 	/** Stored source and destination addresses length. */
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/drv/Makefile	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -39,4 +39,5 @@
 	generic/remote_hw_res.c \
 	generic/remote_char_dev.c \
+	generic/remote_nic.c \
 	generic/remote_usb.c \
 	generic/remote_pci.c \
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/drv/generic/dev_iface.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -41,4 +41,5 @@
 #include "remote_hw_res.h"
 #include "remote_char_dev.h"
+#include "remote_nic.h"
 #include "remote_usb.h"
 #include "remote_usbhc.h"
@@ -50,4 +51,5 @@
 		&remote_hw_res_iface,
 		&remote_char_dev_iface,
+		&remote_nic_iface,
 		&remote_pci_iface,
 		&remote_usb_iface,
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/drv/generic/driver.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -303,4 +303,14 @@
 }
 
+static void driver_dev_added(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&devices_mutex);
+	ddf_dev_t *dev = driver_get_device(IPC_GET_ARG1(*icall));
+	fibril_mutex_unlock(&devices_mutex);
+	
+	if (dev != NULL && driver->driver_ops->device_added != NULL)
+		driver->driver_ops->device_added(dev);
+}
+
 static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall)
 {
@@ -450,4 +460,8 @@
 		case DRIVER_DEV_ADD:
 			driver_dev_add(callid, &call);
+			break;
+		case DRIVER_DEV_ADDED:
+			async_answer_0(callid, EOK);
+			driver_dev_added(callid, &call);
 			break;
 		case DRIVER_DEV_REMOVE:
Index: uspace/lib/drv/generic/remote_nic.c
===================================================================
--- uspace/lib/drv/generic/remote_nic.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
+++ uspace/lib/drv/generic/remote_nic.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -0,0 +1,1253 @@
+/*
+ * Copyright (c) 2011 Radim Vansa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/**
+ * @file
+ * @brief Driver-side RPC skeletons for DDF NIC interface
+ */
+
+#include <assert.h>
+#include <async.h>
+#include <errno.h>
+#include <ipc/services.h>
+#include <adt/measured_strings.h>
+#include <sys/time.h>
+#include "ops/nic.h"
+
+static void remote_nic_send_message(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	assert(nic_iface->send_message);
+	
+	packet_id_t packet_id = (packet_id_t) IPC_GET_ARG2(*call);
+	
+	int rc = nic_iface->send_message(dev, packet_id);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_connect_to_nil(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	assert(nic_iface->connect_to_nil);
+	
+	services_t nil_service = (services_t) IPC_GET_ARG2(*call);
+	nic_device_id_t device_id = (nic_device_id_t) IPC_GET_ARG3(*call);
+	
+	int rc = nic_iface->connect_to_nil(dev, nil_service, device_id);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_get_state(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	assert(nic_iface->get_state);
+	
+	nic_device_state_t state = NIC_STATE_MAX;
+	
+	int rc = nic_iface->get_state(dev, &state);
+	async_answer_1(callid, rc, state);
+}
+
+static void remote_nic_set_state(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	assert(nic_iface->set_state);
+	
+	nic_device_state_t state = (nic_device_state_t) IPC_GET_ARG2(*call);
+	
+	int rc = nic_iface->set_state(dev, state);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_get_address(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	assert(nic_iface->get_address);
+	
+	nic_address_t address;
+	bzero(&address, sizeof(nic_address_t));
+	
+	int rc = nic_iface->get_address(dev, &address);
+	if (rc == EOK) {
+		size_t max_len;
+		ipc_callid_t data_callid;
+		
+		/* All errors will be translated into EPARTY anyway */
+		if (!async_data_read_receive(&data_callid, &max_len)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		if (max_len != sizeof(nic_address_t)) {
+			async_answer_0(data_callid, ELIMIT);
+			async_answer_0(callid, ELIMIT);
+			return;
+		}
+		
+		async_data_read_finalize(data_callid, &address,
+		    sizeof(nic_address_t));
+	}
+	
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_set_address(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	
+	size_t length;
+	ipc_callid_t data_callid;
+	if (!async_data_write_receive(&data_callid, &length)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+	
+	if (length > sizeof(nic_address_t)) {
+		async_answer_0(data_callid, ELIMIT);
+		async_answer_0(callid, ELIMIT);
+		return;
+	}
+	
+	nic_address_t address;
+	if (async_data_write_finalize(data_callid, &address, length) != EOK) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+	
+	if (nic_iface->set_address != NULL) {
+		int rc = nic_iface->set_address(dev, &address);
+		async_answer_0(callid, rc);
+	} else
+		async_answer_0(callid, ENOTSUP);
+}
+
+static void remote_nic_get_stats(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->get_stats == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_device_stats_t stats;
+	bzero(&stats, sizeof(nic_device_stats_t));
+	
+	int rc = nic_iface->get_stats(dev, &stats);
+	if (rc == EOK) {
+		ipc_callid_t data_callid;
+		size_t max_len;
+		if (!async_data_read_receive(&data_callid, &max_len)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		if (max_len < sizeof(nic_device_stats_t)) {
+			async_answer_0(data_callid, ELIMIT);
+			async_answer_0(callid, ELIMIT);
+			return;
+		}
+		
+		async_data_read_finalize(data_callid, &stats,
+		    sizeof(nic_device_stats_t));
+	}
+	
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_get_device_info(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->get_device_info == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_device_info_t info;
+	bzero(&info, sizeof(nic_device_info_t));
+	
+	int rc = nic_iface->get_device_info(dev, &info);
+	if (rc == EOK) {
+		ipc_callid_t data_callid;
+		size_t max_len;
+		if (!async_data_read_receive(&data_callid, &max_len)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		if (max_len < sizeof (nic_device_info_t)) {
+			async_answer_0(data_callid, ELIMIT);
+			async_answer_0(callid, ELIMIT);
+			return;
+		}
+		
+		async_data_read_finalize(data_callid, &info,
+		    sizeof(nic_device_info_t));
+	}
+	
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_get_cable_state(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->get_cable_state == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_cable_state_t cs = NIC_CS_UNKNOWN;
+	
+	int rc = nic_iface->get_cable_state(dev, &cs);
+	async_answer_1(callid, rc, (sysarg_t) cs);
+}
+
+static void remote_nic_get_operation_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->get_operation_mode == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	int speed = 0;
+	nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
+	nic_role_t role = NIC_ROLE_UNKNOWN;
+	
+	int rc = nic_iface->get_operation_mode(dev, &speed, &duplex, &role);
+	async_answer_3(callid, rc, (sysarg_t) speed, (sysarg_t) duplex,
+	    (sysarg_t) role);
+}
+
+static void remote_nic_set_operation_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->set_operation_mode == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	int speed = (int) IPC_GET_ARG2(*call);
+	nic_channel_mode_t duplex = (nic_channel_mode_t) IPC_GET_ARG3(*call);
+	nic_role_t role = (nic_role_t) IPC_GET_ARG4(*call);
+	
+	int rc = nic_iface->set_operation_mode(dev, speed, duplex, role);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_autoneg_enable(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->autoneg_enable == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	uint32_t advertisement = (uint32_t) IPC_GET_ARG2(*call);
+	
+	int rc = nic_iface->autoneg_enable(dev, advertisement);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_autoneg_disable(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->autoneg_disable == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	int rc = nic_iface->autoneg_disable(dev);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_autoneg_probe(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->autoneg_probe == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	uint32_t our_adv = 0;
+	uint32_t their_adv = 0;
+	nic_result_t result = NIC_RESULT_NOT_AVAILABLE;
+	nic_result_t their_result = NIC_RESULT_NOT_AVAILABLE;
+	
+	int rc = nic_iface->autoneg_probe(dev, &our_adv, &their_adv, &result,
+	    &their_result);
+	async_answer_4(callid, rc, our_adv, their_adv, (sysarg_t) result,
+	    (sysarg_t) their_result);
+}
+
+static void remote_nic_autoneg_restart(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->autoneg_restart == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	int rc = nic_iface->autoneg_restart(dev);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_get_pause(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->get_pause == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_result_t we_send;
+	nic_result_t we_receive;
+	uint16_t pause;
+	
+	int rc = nic_iface->get_pause(dev, &we_send, &we_receive, &pause);
+	async_answer_3(callid, rc, we_send, we_receive, pause);
+}
+
+static void remote_nic_set_pause(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->set_pause == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	int allow_send = (int) IPC_GET_ARG2(*call);
+	int allow_receive = (int) IPC_GET_ARG3(*call);
+	uint16_t pause = (uint16_t) IPC_GET_ARG4(*call);
+	
+	int rc = nic_iface->set_pause(dev, allow_send, allow_receive,
+	    pause);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_unicast_get_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->unicast_get_mode == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	size_t max_count = IPC_GET_ARG2(*call);
+	nic_address_t *address_list = NULL;
+	
+	if (max_count != 0) {
+		address_list = malloc(max_count * sizeof (nic_address_t));
+		if (!address_list) {
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+	}
+	
+	bzero(address_list, max_count * sizeof(nic_address_t));
+	nic_unicast_mode_t mode = NIC_UNICAST_DEFAULT;
+	size_t address_count = 0;
+	
+	int rc = nic_iface->unicast_get_mode(dev, &mode, max_count, address_list,
+	    &address_count);
+	
+	if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
+		free(address_list);
+		async_answer_2(callid, rc, mode, address_count);
+		return;
+	}
+	
+	ipc_callid_t data_callid;
+	size_t max_len;
+	if (!async_data_read_receive(&data_callid, &max_len)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_2(callid, rc, mode, address_count);
+		free(address_list);
+		return;
+	}
+	
+	if (max_len > address_count * sizeof(nic_address_t))
+		max_len = address_count * sizeof(nic_address_t);
+	
+	if (max_len > max_count * sizeof(nic_address_t))
+		max_len = max_count * sizeof(nic_address_t);
+	
+	async_data_read_finalize(data_callid, address_list, max_len);
+	async_answer_0(data_callid, EINVAL);
+	
+	free(address_list);
+	async_answer_2(callid, rc, mode, address_count);
+}
+
+static void remote_nic_unicast_set_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	
+	size_t length;
+	nic_unicast_mode_t mode = IPC_GET_ARG2(*call);
+	size_t address_count = IPC_GET_ARG3(*call);
+	nic_address_t *address_list = NULL;
+	
+	if (address_count) {
+		ipc_callid_t data_callid;
+		if (!async_data_write_receive(&data_callid, &length)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		if (length != address_count * sizeof(nic_address_t)) {
+			async_answer_0(data_callid, ELIMIT);
+			async_answer_0(callid, ELIMIT);
+			return;
+		}
+		
+		address_list = malloc(length);
+		if (address_list == NULL) {
+			async_answer_0(data_callid, ENOMEM);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+		
+		if (async_data_write_finalize(data_callid, address_list,
+		    length) != EOK) {
+			async_answer_0(callid, EINVAL);
+			free(address_list);
+			return;
+		}
+	}
+	
+	if (nic_iface->unicast_set_mode != NULL) {
+		int rc = nic_iface->unicast_set_mode(dev, mode, address_list,
+		    address_count);
+		async_answer_0(callid, rc);
+	} else
+		async_answer_0(callid, ENOTSUP);
+	
+	free(address_list);
+}
+
+static void remote_nic_multicast_get_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->multicast_get_mode == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	size_t max_count = IPC_GET_ARG2(*call);
+	nic_address_t *address_list = NULL;
+	
+	if (max_count != 0) {
+		address_list = malloc(max_count * sizeof(nic_address_t));
+		if (!address_list) {
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+	}
+	
+	bzero(address_list, max_count * sizeof(nic_address_t));
+	nic_multicast_mode_t mode = NIC_MULTICAST_BLOCKED;
+	size_t address_count = 0;
+	
+	int rc = nic_iface->multicast_get_mode(dev, &mode, max_count, address_list,
+	    &address_count);
+	
+	
+	if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
+		free(address_list);
+		async_answer_2(callid, rc, mode, address_count);
+		return;
+	}
+	
+	ipc_callid_t data_callid;
+	size_t max_len;
+	if (!async_data_read_receive(&data_callid, &max_len)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_2(callid, rc, mode, address_count);
+		free(address_list);
+		return;
+	}
+	
+	if (max_len > address_count * sizeof(nic_address_t))
+		max_len = address_count * sizeof(nic_address_t);
+	
+	if (max_len > max_count * sizeof(nic_address_t))
+		max_len = max_count * sizeof(nic_address_t);
+	
+	async_data_read_finalize(data_callid, address_list, max_len);
+	
+	free(address_list);
+	async_answer_2(callid, rc, mode, address_count);
+}
+
+static void remote_nic_multicast_set_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	
+	nic_multicast_mode_t mode = IPC_GET_ARG2(*call);
+	size_t address_count = IPC_GET_ARG3(*call);
+	nic_address_t *address_list = NULL;
+	
+	if (address_count) {
+		ipc_callid_t data_callid;
+		size_t length;
+		if (!async_data_write_receive(&data_callid, &length)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		if (length != address_count * sizeof (nic_address_t)) {
+			async_answer_0(data_callid, ELIMIT);
+			async_answer_0(callid, ELIMIT);
+			return;
+		}
+		
+		address_list = malloc(length);
+		if (address_list == NULL) {
+			async_answer_0(data_callid, ENOMEM);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+		
+		if (async_data_write_finalize(data_callid, address_list,
+		    length) != EOK) {
+			async_answer_0(callid, EINVAL);
+			free(address_list);
+			return;
+		}
+	}
+	
+	if (nic_iface->multicast_set_mode != NULL) {
+		int rc = nic_iface->multicast_set_mode(dev, mode, address_list,
+		    address_count);
+		async_answer_0(callid, rc);
+	} else
+		async_answer_0(callid, ENOTSUP);
+	
+	free(address_list);
+}
+
+static void remote_nic_broadcast_get_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->broadcast_get_mode == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_broadcast_mode_t mode = NIC_BROADCAST_ACCEPTED;
+	
+	int rc = nic_iface->broadcast_get_mode(dev, &mode);
+	async_answer_1(callid, rc, mode);
+}
+
+static void remote_nic_broadcast_set_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->broadcast_set_mode == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_broadcast_mode_t mode = IPC_GET_ARG2(*call);
+	
+	int rc = nic_iface->broadcast_set_mode(dev, mode);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_defective_get_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->defective_get_mode == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	uint32_t mode = 0;
+	
+	int rc = nic_iface->defective_get_mode(dev, &mode);
+	async_answer_1(callid, rc, mode);
+}
+
+static void remote_nic_defective_set_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->defective_set_mode == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	uint32_t mode = IPC_GET_ARG2(*call);
+	
+	int rc = nic_iface->defective_set_mode(dev, mode);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_blocked_sources_get(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->blocked_sources_get == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	size_t max_count = IPC_GET_ARG2(*call);
+	nic_address_t *address_list = NULL;
+	
+	if (max_count != 0) {
+		address_list = malloc(max_count * sizeof(nic_address_t));
+		if (!address_list) {
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+	}
+	
+	bzero(address_list, max_count * sizeof(nic_address_t));
+	size_t address_count = 0;
+	
+	int rc = nic_iface->blocked_sources_get(dev, max_count, address_list,
+	    &address_count);
+	
+	if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
+		async_answer_1(callid, rc, address_count);
+		free(address_list);
+		return;
+	}
+	
+	ipc_callid_t data_callid;
+	size_t max_len;
+	if (!async_data_read_receive(&data_callid, &max_len)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_1(callid, rc, address_count);
+		free(address_list);
+		return;
+	}
+	
+	if (max_len > address_count * sizeof(nic_address_t))
+		max_len = address_count * sizeof(nic_address_t);
+	
+	if (max_len > max_count * sizeof(nic_address_t))
+		max_len = max_count * sizeof(nic_address_t);
+	
+	async_data_read_finalize(data_callid, address_list, max_len);
+	async_answer_0(data_callid, EINVAL);
+	
+	free(address_list);
+	async_answer_1(callid, rc, address_count);
+}
+
+static void remote_nic_blocked_sources_set(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	
+	size_t length;
+	size_t address_count = IPC_GET_ARG2(*call);
+	nic_address_t *address_list = NULL;
+	
+	if (address_count) {
+		ipc_callid_t data_callid;
+		if (!async_data_write_receive(&data_callid, &length)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		if (length != address_count * sizeof(nic_address_t)) {
+			async_answer_0(data_callid, ELIMIT);
+			async_answer_0(callid, ELIMIT);
+			return;
+		}
+		
+		address_list = malloc(length);
+		if (address_list == NULL) {
+			async_answer_0(data_callid, ENOMEM);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+		
+		if (async_data_write_finalize(data_callid, address_list,
+		    length) != EOK) {
+			async_answer_0(callid, EINVAL);
+			free(address_list);
+			return;
+		}
+	}
+	
+	if (nic_iface->blocked_sources_set != NULL) {
+		int rc = nic_iface->blocked_sources_set(dev, address_list,
+		    address_count);
+		async_answer_0(callid, rc);
+	} else
+		async_answer_0(callid, ENOTSUP);
+	
+	free(address_list);
+}
+
+static void remote_nic_vlan_get_mask(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->vlan_get_mask == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_vlan_mask_t vlan_mask;
+	bzero(&vlan_mask, sizeof(nic_vlan_mask_t));
+	
+	int rc = nic_iface->vlan_get_mask(dev, &vlan_mask);
+	if (rc == EOK) {
+		ipc_callid_t data_callid;
+		size_t max_len;
+		if (!async_data_read_receive(&data_callid, &max_len)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		if (max_len != sizeof(nic_vlan_mask_t)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		async_data_read_finalize(data_callid, &vlan_mask, max_len);
+	}
+	
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_vlan_set_mask(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	
+	nic_vlan_mask_t vlan_mask;
+	nic_vlan_mask_t *vlan_mask_pointer = NULL;
+	bool vlan_mask_set = (bool) IPC_GET_ARG2(*call);
+	
+	if (vlan_mask_set) {
+		ipc_callid_t data_callid;
+		size_t length;
+		if (!async_data_write_receive(&data_callid, &length)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		if (length != sizeof(nic_vlan_mask_t)) {
+			async_answer_0(data_callid, ELIMIT);
+			async_answer_0(callid, ELIMIT);
+			return;
+		}
+		
+		if (async_data_write_finalize(data_callid, &vlan_mask,
+		    length) != EOK) {
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		vlan_mask_pointer = &vlan_mask;
+	}
+	
+	if (nic_iface->vlan_set_mask != NULL) {
+		int rc = nic_iface->vlan_set_mask(dev, vlan_mask_pointer);
+		async_answer_0(callid, rc);
+	} else
+		async_answer_0(callid, ENOTSUP);
+}
+
+static void remote_nic_vlan_set_tag(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	
+	if (nic_iface->vlan_set_tag == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	uint16_t tag = (uint16_t) IPC_GET_ARG2(*call);
+	int add = (int) IPC_GET_ARG3(*call);
+	int strip = (int) IPC_GET_ARG4(*call);
+	
+	int rc = nic_iface->vlan_set_tag(dev, tag, add, strip);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_wol_virtue_add(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	
+	int send_data = (int) IPC_GET_ARG3(*call);
+	ipc_callid_t data_callid;
+	
+	if (nic_iface->wol_virtue_add == NULL) {
+		if (send_data) {
+			async_data_write_receive(&data_callid, NULL);
+			async_answer_0(data_callid, ENOTSUP);
+		}
+		
+		async_answer_0(callid, ENOTSUP);
+	}
+	
+	size_t length = 0;
+	void *data = NULL;
+	
+	if (send_data) {
+		if (!async_data_write_receive(&data_callid, &length)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		data = malloc(length);
+		if (data == NULL) {
+			async_answer_0(data_callid, ENOMEM);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+		
+		if (async_data_write_finalize(data_callid, data,
+		    length) != EOK) {
+			async_answer_0(callid, EINVAL);
+			free(data);
+			return;
+		}
+	}
+	
+	nic_wv_id_t id = 0;
+	nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
+	
+	int rc = nic_iface->wol_virtue_add(dev, type, data, length, &id);
+	async_answer_1(callid, rc, (sysarg_t) id);
+	free(data);
+}
+
+static void remote_nic_wol_virtue_remove(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	
+	if (nic_iface->wol_virtue_remove == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
+	
+	int rc = nic_iface->wol_virtue_remove(dev, id);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_wol_virtue_probe(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	
+	if (nic_iface->wol_virtue_probe == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_wv_id_t id = (nic_wv_id_t) IPC_GET_ARG2(*call);
+	size_t max_length = IPC_GET_ARG3(*call);
+	nic_wv_type_t type = NIC_WV_NONE;
+	size_t length = 0;
+	ipc_callid_t data_callid;
+	void *data = NULL;
+	
+	if (max_length != 0) {
+		data = malloc(max_length);
+		if (data == NULL) {
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+	}
+	
+	bzero(data, max_length);
+	
+	int rc = nic_iface->wol_virtue_probe(dev, id, &type, max_length,
+	    data, &length);
+	
+	if ((max_length != 0) && (length != 0)) {
+		size_t req_length;
+		if (!async_data_read_receive(&data_callid, &req_length)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			free(data);
+			return;
+		}
+		
+		if (req_length > length)
+			req_length = length;
+		
+		if (req_length > max_length)
+			req_length = max_length;
+		
+		async_data_read_finalize(data_callid, data, req_length);
+	}
+	
+	async_answer_2(callid, rc, (sysarg_t) type, (sysarg_t) length);
+	free(data);
+}
+
+static void remote_nic_wol_virtue_list(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->wol_virtue_list == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
+	size_t max_count = IPC_GET_ARG3(*call);
+	size_t count = 0;
+	nic_wv_id_t *id_list = NULL;
+	ipc_callid_t data_callid;
+	
+	if (max_count != 0) {
+		id_list = malloc(max_count * sizeof(nic_wv_id_t));
+		if (id_list == NULL) {
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+	}
+	
+	bzero(id_list, max_count * sizeof (nic_wv_id_t));
+	
+	int rc = nic_iface->wol_virtue_list(dev, type, max_count, id_list,
+	    &count);
+	
+	if ((max_count != 0) && (count != 0)) {
+		size_t req_length;
+		if (!async_data_read_receive(&data_callid, &req_length)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			free(id_list);
+			return;
+		}
+		
+		if (req_length > count * sizeof(nic_wv_id_t))
+			req_length = count * sizeof(nic_wv_id_t);
+		
+		if (req_length > max_count * sizeof(nic_wv_id_t))
+			req_length = max_count * sizeof(nic_wv_id_t);
+		
+		rc = async_data_read_finalize(data_callid, id_list, req_length);
+	}
+	
+	async_answer_1(callid, rc, (sysarg_t) count);
+	free(id_list);
+}
+
+static void remote_nic_wol_virtue_get_caps(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->wol_virtue_get_caps == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	int count = -1;
+	nic_wv_type_t type = (nic_wv_type_t) IPC_GET_ARG2(*call);
+	
+	int rc = nic_iface->wol_virtue_get_caps(dev, type, &count);
+	async_answer_1(callid, rc, (sysarg_t) count);
+}
+
+static void remote_nic_wol_load_info(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->wol_load_info == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	size_t max_length = (size_t) IPC_GET_ARG2(*call);
+	size_t frame_length = 0;
+	nic_wv_type_t type = NIC_WV_NONE;
+	uint8_t *data = NULL;
+	
+	if (max_length != 0) {
+		data = malloc(max_length);
+		if (data == NULL) {
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+	}
+	
+	bzero(data, max_length);
+	
+	int rc = nic_iface->wol_load_info(dev, &type, max_length, data,
+	    &frame_length);
+	if (rc == EOK) {
+		ipc_callid_t data_callid;
+		size_t req_length;
+		if (!async_data_read_receive(&data_callid, &req_length)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			free(data);
+			return;
+		}
+		
+		req_length = req_length > max_length ? max_length : req_length;
+		req_length = req_length > frame_length ? frame_length : req_length;
+		async_data_read_finalize(data_callid, data, req_length);
+	}
+	
+	async_answer_2(callid, rc, (sysarg_t) type, (sysarg_t) frame_length);
+	free(data);
+}
+
+static void remote_nic_offload_probe(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->offload_probe == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	uint32_t supported = 0;
+	uint32_t active = 0;
+	
+	int rc = nic_iface->offload_probe(dev, &supported, &active);
+	async_answer_2(callid, rc, supported, active);
+}
+
+static void remote_nic_offload_set(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->offload_set == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	uint32_t mask = (uint32_t) IPC_GET_ARG2(*call);
+	uint32_t active = (uint32_t) IPC_GET_ARG3(*call);
+	
+	int rc = nic_iface->offload_set(dev, mask, active);
+	async_answer_0(callid, rc);
+}
+
+static void remote_nic_poll_get_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->poll_get_mode == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	nic_poll_mode_t mode = NIC_POLL_IMMEDIATE;
+	int request_data = IPC_GET_ARG2(*call);
+	struct timeval period = {
+		.tv_sec = 0,
+		.tv_usec = 0
+	};
+	
+	int rc = nic_iface->poll_get_mode(dev, &mode, &period);
+	if ((rc == EOK) && (request_data)) {
+		size_t max_len;
+		ipc_callid_t data_callid;
+		
+		if (!async_data_read_receive(&data_callid, &max_len)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		if (max_len != sizeof(struct timeval)) {
+			async_answer_0(data_callid, ELIMIT);
+			async_answer_0(callid, ELIMIT);
+			return;
+		}
+		
+		async_data_read_finalize(data_callid, &period,
+		    sizeof(struct timeval));
+	}
+	
+	async_answer_1(callid, rc, (sysarg_t) mode);
+}
+
+static void remote_nic_poll_set_mode(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	
+	nic_poll_mode_t mode = IPC_GET_ARG2(*call);
+	int has_period = IPC_GET_ARG3(*call);
+	struct timeval period_buf;
+	struct timeval *period = NULL;
+	size_t length;
+	
+	if (has_period) {
+		ipc_callid_t data_callid;
+		if (!async_data_write_receive(&data_callid, &length)) {
+			async_answer_0(data_callid, EINVAL);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+		
+		if (length != sizeof(struct timeval)) {
+			async_answer_0(data_callid, ELIMIT);
+			async_answer_0(callid, ELIMIT);
+			return;
+		}
+		
+		period = &period_buf;
+		if (async_data_write_finalize(data_callid, period,
+		    length) != EOK) {
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+	}
+	
+	if (nic_iface->poll_set_mode != NULL) {
+		int rc = nic_iface->poll_set_mode(dev, mode, period);
+		async_answer_0(callid, rc);
+	} else
+		async_answer_0(callid, ENOTSUP);
+}
+
+static void remote_nic_poll_now(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	if (nic_iface->poll_now == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	int rc = nic_iface->poll_now(dev);
+	async_answer_0(callid, rc);
+}
+
+/** Remote NIC interface operations.
+ *
+ */
+static remote_iface_func_ptr_t remote_nic_iface_ops[] = {
+	&remote_nic_send_message,
+	&remote_nic_connect_to_nil,
+	&remote_nic_get_state,
+	&remote_nic_set_state,
+	&remote_nic_get_address,
+	&remote_nic_set_address,
+	&remote_nic_get_stats,
+	&remote_nic_get_device_info,
+	&remote_nic_get_cable_state,
+	&remote_nic_get_operation_mode,
+	&remote_nic_set_operation_mode,
+	&remote_nic_autoneg_enable,
+	&remote_nic_autoneg_disable,
+	&remote_nic_autoneg_probe,
+	&remote_nic_autoneg_restart,
+	&remote_nic_get_pause,
+	&remote_nic_set_pause,
+	&remote_nic_unicast_get_mode,
+	&remote_nic_unicast_set_mode,
+	&remote_nic_multicast_get_mode,
+	&remote_nic_multicast_set_mode,
+	&remote_nic_broadcast_get_mode,
+	&remote_nic_broadcast_set_mode,
+	&remote_nic_defective_get_mode,
+	&remote_nic_defective_set_mode,
+	&remote_nic_blocked_sources_get,
+	&remote_nic_blocked_sources_set,
+	&remote_nic_vlan_get_mask,
+	&remote_nic_vlan_set_mask,
+	&remote_nic_vlan_set_tag,
+	&remote_nic_wol_virtue_add,
+	&remote_nic_wol_virtue_remove,
+	&remote_nic_wol_virtue_probe,
+	&remote_nic_wol_virtue_list,
+	&remote_nic_wol_virtue_get_caps,
+	&remote_nic_wol_load_info,
+	&remote_nic_offload_probe,
+	&remote_nic_offload_set,
+	&remote_nic_poll_get_mode,
+	&remote_nic_poll_set_mode,
+	&remote_nic_poll_now
+};
+
+/** Remote NIC interface structure.
+ *
+ * Interface for processing request from remote
+ * clients addressed to the NIC interface.
+ *
+ */
+remote_iface_t remote_nic_iface = {
+	.method_count = sizeof(remote_nic_iface_ops) /
+	    sizeof(remote_iface_func_ptr_t),
+	.methods = remote_nic_iface_ops
+};
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/drv/include/ddf/driver.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -137,4 +137,10 @@
 	/** Callback method for passing a new device to the device driver */
 	int (*add_device)(ddf_dev_t *);
+	/**
+	 * Notification that the device was succesfully added.
+	 * The driver can do any blocking operation without
+	 * blocking the device manager.
+	 */
+	void (*device_added)(ddf_dev_t *dev);
 	/** Ask driver to remove a device */
 	int (*dev_remove)(ddf_dev_t *);
Index: uspace/lib/drv/include/ops/nic.h
===================================================================
--- uspace/lib/drv/include/ops/nic.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
+++ uspace/lib/drv/include/ops/nic.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011 Radim Vansa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ * @brief DDF NIC interface definition
+ */
+
+#ifndef LIBDRV_OPS_NIC_H_
+#define LIBDRV_OPS_NIC_H_
+
+#include <net/packet.h>
+#include <ipc/services.h>
+#include <net/device.h>
+#include <sys/time.h>
+
+#include "../ddf/driver.h"
+
+typedef struct nic_iface {
+	/** Mandatory methods */
+	int (*send_message)(ddf_fun_t *, packet_id_t);
+	int (*connect_to_nil)(ddf_fun_t *, services_t, nic_device_id_t);
+	int (*get_state)(ddf_fun_t *, nic_device_state_t *);
+	int (*set_state)(ddf_fun_t *, nic_device_state_t);
+	int (*get_address)(ddf_fun_t *, nic_address_t *);
+	
+	/** Optional methods */
+	int (*set_address)(ddf_fun_t *, const nic_address_t *);
+	int (*get_stats)(ddf_fun_t *, nic_device_stats_t *);
+	int (*get_device_info)(ddf_fun_t *, nic_device_info_t *);
+	int (*get_cable_state)(ddf_fun_t *, nic_cable_state_t *);
+	
+	int (*get_operation_mode)(ddf_fun_t *, int *, nic_channel_mode_t *,
+	    nic_role_t *);
+	int (*set_operation_mode)(ddf_fun_t *, int, nic_channel_mode_t,
+	    nic_role_t);
+	int (*autoneg_enable)(ddf_fun_t *, uint32_t);
+	int (*autoneg_disable)(ddf_fun_t *);
+	int (*autoneg_probe)(ddf_fun_t *, uint32_t *, uint32_t *,
+	    nic_result_t *, nic_result_t *);
+	int (*autoneg_restart)(ddf_fun_t *);
+	int (*get_pause)(ddf_fun_t *, nic_result_t *, nic_result_t *,
+		uint16_t *);
+	int (*set_pause)(ddf_fun_t *, int, int, uint16_t);
+	
+	int (*unicast_get_mode)(ddf_fun_t *, nic_unicast_mode_t *, size_t,
+	    nic_address_t *, size_t *);
+	int (*unicast_set_mode)(ddf_fun_t *, nic_unicast_mode_t,
+	    const nic_address_t *, size_t);
+	int (*multicast_get_mode)(ddf_fun_t *, nic_multicast_mode_t *, size_t,
+	    nic_address_t *, size_t *);
+	int (*multicast_set_mode)(ddf_fun_t *, nic_multicast_mode_t,
+	    const nic_address_t *, size_t);
+	int (*broadcast_get_mode)(ddf_fun_t *, nic_broadcast_mode_t *);
+	int (*broadcast_set_mode)(ddf_fun_t *, nic_broadcast_mode_t);
+	int (*defective_get_mode)(ddf_fun_t *, uint32_t *);
+	int (*defective_set_mode)(ddf_fun_t *, uint32_t);
+	int (*blocked_sources_get)(ddf_fun_t *, size_t, nic_address_t *,
+	    size_t *);
+	int (*blocked_sources_set)(ddf_fun_t *, const nic_address_t *, size_t);
+	
+	int (*vlan_get_mask)(ddf_fun_t *, nic_vlan_mask_t *);
+	int (*vlan_set_mask)(ddf_fun_t *, const nic_vlan_mask_t *);
+	int (*vlan_set_tag)(ddf_fun_t *, uint16_t, int, int);
+	
+	int (*wol_virtue_add)(ddf_fun_t *, nic_wv_type_t, const void *,
+	    size_t, nic_wv_id_t *);
+	int (*wol_virtue_remove)(ddf_fun_t *, nic_wv_id_t);
+	int (*wol_virtue_probe)(ddf_fun_t *, nic_wv_id_t, nic_wv_type_t *,
+	    size_t, void *, size_t *);
+	int (*wol_virtue_list)(ddf_fun_t *, nic_wv_type_t, size_t,
+	    nic_wv_id_t *, size_t *);
+	int (*wol_virtue_get_caps)(ddf_fun_t *, nic_wv_type_t, int *);
+	int (*wol_load_info)(ddf_fun_t *, nic_wv_type_t *, size_t,
+	    uint8_t *, size_t *);
+	
+	int (*offload_probe)(ddf_fun_t *, uint32_t *, uint32_t *);
+	int (*offload_set)(ddf_fun_t *, uint32_t, uint32_t);
+	
+	int (*poll_get_mode)(ddf_fun_t *, nic_poll_mode_t *,
+	    struct timeval *);
+	int (*poll_set_mode)(ddf_fun_t *, nic_poll_mode_t,
+	    const struct timeval *);
+	int (*poll_now)(ddf_fun_t *);
+} nic_iface_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/remote_nic.h
===================================================================
--- uspace/lib/drv/include/remote_nic.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
+++ uspace/lib/drv/include/remote_nic.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 Radim Vansa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_NIC_H_
+#define LIBDRV_REMOTE_NIC_H_
+
+extern remote_iface_t remote_nic_iface;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/net/Makefile
===================================================================
--- uspace/lib/net/Makefile	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/Makefile	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -40,6 +40,4 @@
 	generic/protocol_map.c \
 	adt/module_map.c \
-	netif/netif_remote.c \
-	netif/netif_skel.c \
 	nil/nil_remote.c \
 	nil/nil_skel.c \
Index: uspace/lib/net/generic/generic.c
===================================================================
--- uspace/lib/net/generic/generic.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/generic/generic.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -54,5 +54,5 @@
  */
 int generic_device_state_msg_remote(async_sess_t *sess, sysarg_t message,
-    device_id_t device_id, sysarg_t state, services_t target)
+    nic_device_id_t device_id, sysarg_t state, services_t target)
 {
 	async_exch_t *exch = async_exchange_begin(sess);
@@ -68,5 +68,4 @@
  * @param[in] message   Service specific message.
  * @param[in] device_id Device identifier.
- * @param[in] arg2      Second argument of the message.
  * @param[in] service   Device module service.
  *
@@ -77,9 +76,9 @@
  */
 int generic_device_req_remote(async_sess_t *sess, sysarg_t message,
-    device_id_t device_id, sysarg_t arg2, services_t service)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_3_0(exch, message, (sysarg_t) device_id,
-	    arg2, (sysarg_t) service);
+    nic_device_id_t device_id, services_t service)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_2_0(exch, message, (sysarg_t) device_id,
+	    (sysarg_t) service);
 	async_exchange_end(exch);
 	
@@ -103,25 +102,21 @@
  */
 int generic_get_addr_req(async_sess_t *sess, sysarg_t message,
-    device_id_t device_id, measured_string_t **address, uint8_t **data)
-{
-	if ((!address) || (!data))
+    nic_device_id_t device_id, uint8_t *address, size_t max_len)
+{
+	if (!address)
 		return EBADMEM;
 	
 	/* Request the address */
 	async_exch_t *exch = async_exchange_begin(sess);
-	aid_t message_id = async_send_1(exch, message, (sysarg_t) device_id,
+	aid_t aid = async_send_1(exch, message, (sysarg_t) device_id,
 	    NULL);
-	int rc = measured_strings_return(exch, address, data, 1);
+	int rc = async_data_read_start(exch, address, max_len);
 	async_exchange_end(exch);
 	
 	sysarg_t result;
-	async_wait_for(message_id, &result);
-	
-	/* If not successful */
-	if ((rc == EOK) && (result != EOK)) {
-		/* Clear the data */
-		free(*address);
-		free(*data);
-	}
+	async_wait_for(aid, &result);
+	
+	if (rc != EOK)
+		return rc;
 	
 	return (int) result;
@@ -142,5 +137,5 @@
  */
 int generic_packet_size_req_remote(async_sess_t *sess, sysarg_t message,
-    device_id_t device_id, packet_dimension_t *packet_dimension)
+    nic_device_id_t device_id, packet_dimension_t *packet_dimension)
 {
 	if (!packet_dimension)
@@ -179,5 +174,5 @@
  */
 int generic_received_msg_remote(async_sess_t *sess, sysarg_t message,
-    device_id_t device_id, packet_id_t packet_id, services_t target,
+    nic_device_id_t device_id, packet_id_t packet_id, services_t target,
     services_t error)
 {
@@ -210,5 +205,5 @@
  */
 int generic_send_msg_remote(async_sess_t *sess, sysarg_t message,
-    device_id_t device_id, packet_id_t packet_id, services_t sender,
+    nic_device_id_t device_id, packet_id_t packet_id, services_t sender,
     services_t error)
 {
@@ -251,5 +246,5 @@
  */
 int generic_translate_req(async_sess_t *sess, sysarg_t message,
-    device_id_t device_id, services_t service,
+    nic_device_id_t device_id, services_t service,
     measured_string_t *configuration, size_t count,
     measured_string_t **translation, uint8_t **data)
Index: uspace/lib/net/generic/net_checksum.c
===================================================================
--- uspace/lib/net/generic/net_checksum.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/generic/net_checksum.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -40,8 +40,8 @@
 
 /** Big-endian encoding CRC divider. */
-#define CRC_DIVIDER_BE	0x04c11db7
+#define CRC_DIVIDER_BE  0x04c11db7
 
 /** Little-endian encoding CRC divider. */
-#define CRC_DIVIDER_LE	0xedb88320
+#define CRC_DIVIDER_LE  0xedb88320
 
 /** Compacts the computed checksum to the 16 bit number adding the carries.
@@ -203,5 +203,5 @@
 }
 
-/** Computes the ip header checksum.
+/** Compute the IP header checksum.
  *
  * To compute the checksum of a new packet, the checksum header field must be
Index: uspace/lib/net/generic/net_remote.c
===================================================================
--- uspace/lib/net/generic/net_remote.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/generic/net_remote.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -38,7 +38,7 @@
 #include <ipc/services.h>
 #include <ipc/net_net.h>
-
 #include <malloc.h>
-
+#include <async.h>
+#include <devman.h>
 #include <generic.h>
 #include <net/modules.h>
@@ -98,5 +98,5 @@
     size_t count, uint8_t **data)
 {
-	return generic_translate_req(sess, NET_NET_GET_DEVICE_CONF, 0, 0,
+	return generic_translate_req(sess, NET_NET_GET_CONF, 0, 0,
 	    *configuration, count, configuration, data);
 }
@@ -124,5 +124,5 @@
  *
  */
-int net_get_device_conf_req(async_sess_t *sess, device_id_t device_id,
+int net_get_device_conf_req(async_sess_t *sess, nic_device_id_t device_id,
     measured_string_t **configuration, size_t count, uint8_t **data)
 {
@@ -131,4 +131,49 @@
 }
 
+int net_get_devices_req(async_sess_t *sess, measured_string_t **devices,
+    size_t *count, uint8_t **data)
+{
+	if ((!devices) || (!count))
+		return EBADMEM;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	int rc = async_req_0_1(exch, NET_NET_GET_DEVICES_COUNT, count);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	if (*count == 0) {
+		async_exchange_end(exch);
+		*data = NULL;
+		return EOK;
+	}
+	
+	aid_t message_id = async_send_0(exch, NET_NET_GET_DEVICES, NULL);
+	rc = measured_strings_return(exch, devices, data, *count);
+	
+	async_exchange_end(exch);
+	
+	sysarg_t result;
+	async_wait_for(message_id, &result);
+	
+	if ((rc == EOK) && (result != EOK)) {
+		free(*devices);
+		free(*data);
+	}
+	
+	return (int) result;
+}
+
+int net_driver_ready(async_sess_t *sess, devman_handle_t handle)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_1_0(exch, NET_NET_DRIVER_READY, handle);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
 /** @}
  */
Index: uspace/lib/net/generic/protocol_map.c
===================================================================
--- uspace/lib/net/generic/protocol_map.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/generic/protocol_map.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -50,5 +50,5 @@
 	switch (nil) {
 	case SERVICE_ETHERNET:
-	case SERVICE_NE2000:
+	case SERVICE_NILDUMMY:
 		switch (il) {
 		case SERVICE_IP:
@@ -76,5 +76,5 @@
 	switch (nil) {
 	case SERVICE_ETHERNET:
-	case SERVICE_NE2000:
+	case SERVICE_NILDUMMY:
 		switch (protocol) {
 		case ETH_P_IP:
@@ -139,5 +139,4 @@
 	switch (nil) {
 	case SERVICE_ETHERNET:
-	case SERVICE_NE2000:
 		return HW_ETHER;
 	default:
Index: uspace/lib/net/il/arp_remote.c
===================================================================
--- uspace/lib/net/il/arp_remote.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/il/arp_remote.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -84,5 +84,5 @@
  *
  */
-int arp_clear_address_req(async_sess_t *sess, device_id_t device_id,
+int arp_clear_address_req(async_sess_t *sess, nic_device_id_t device_id,
     services_t protocol, measured_string_t *address)
 {
@@ -108,5 +108,5 @@
  *
  */
-int arp_clear_device_req(async_sess_t *sess, device_id_t device_id)
+int arp_clear_device_req(async_sess_t *sess, nic_device_id_t device_id)
 {
 	async_exch_t *exch = async_exchange_begin(sess);
@@ -143,5 +143,5 @@
  *
  */
-int arp_device_req(async_sess_t *sess, device_id_t device_id,
+int arp_device_req(async_sess_t *sess, nic_device_id_t device_id,
     services_t protocol, services_t netif, measured_string_t *address)
 {
@@ -177,5 +177,5 @@
  *
  */
-int arp_translate_req(async_sess_t *sess, device_id_t device_id,
+int arp_translate_req(async_sess_t *sess, nic_device_id_t device_id,
     services_t protocol, measured_string_t *address,
     measured_string_t **translation, uint8_t **data)
Index: uspace/lib/net/il/il_remote.c
===================================================================
--- uspace/lib/net/il/il_remote.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/il/il_remote.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -55,6 +55,6 @@
  *
  */
-int il_device_state_msg(async_sess_t *sess, device_id_t device_id,
-    device_state_t state, services_t target)
+int il_device_state_msg(async_sess_t *sess, nic_device_id_t device_id,
+    nic_device_state_t state, services_t target)
 {
 	return generic_device_state_msg_remote(sess, NET_IL_DEVICE_STATE,
@@ -73,6 +73,6 @@
  *
  */
-int il_received_msg(async_sess_t *sess, device_id_t device_id, packet_t *packet,
-    services_t target)
+int il_received_msg(async_sess_t *sess, nic_device_id_t device_id,
+    packet_t *packet, services_t target)
 {
 	return generic_received_msg_remote(sess, NET_IL_RECEIVED, device_id,
@@ -91,5 +91,5 @@
  *
  */
-int il_mtu_changed_msg(async_sess_t *sess, device_id_t device_id, size_t mtu,
+int il_mtu_changed_msg(async_sess_t *sess, nic_device_id_t device_id, size_t mtu,
     services_t target)
 {
@@ -98,4 +98,26 @@
 }
 
+/** Notify IL layer modules about address change (implemented by ARP)
+ *
+ */
+int il_addr_changed_msg(async_sess_t *sess, nic_device_id_t device_id,
+    size_t addr_len, const uint8_t *address)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	aid_t message_id = async_send_1(exch, NET_IL_ADDR_CHANGED,
+			(sysarg_t) device_id, NULL);
+	int rc = async_data_write_start(exch, address, addr_len);
+	
+	async_exchange_end(exch);
+	
+	sysarg_t res;
+    async_wait_for(message_id, &res);
+    if (rc != EOK)
+		return rc;
+	
+    return (int) res;
+}
+
 /** @}
  */
Index: uspace/lib/net/il/ip_remote.c
===================================================================
--- uspace/lib/net/il/ip_remote.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/il/ip_remote.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -62,5 +62,5 @@
  *
  */
-int ip_add_route_req_remote(async_sess_t *sess, device_id_t device_id,
+int ip_add_route_req_remote(async_sess_t *sess, nic_device_id_t device_id,
     in_addr_t address, in_addr_t netmask, in_addr_t gateway)
 {
@@ -123,8 +123,8 @@
  *
  */
-int ip_device_req_remote(async_sess_t *sess, device_id_t device_id,
+int ip_device_req_remote(async_sess_t *sess, nic_device_id_t device_id,
     services_t service)
 {
-	return generic_device_req_remote(sess, NET_IP_DEVICE, device_id, 0,
+	return generic_device_req_remote(sess, NET_IP_DEVICE, device_id,
 	    service);
 }
@@ -144,5 +144,5 @@
 int ip_get_route_req_remote(async_sess_t *sess, ip_protocol_t protocol,
     const struct sockaddr *destination, socklen_t addrlen,
-    device_id_t *device_id, void **header, size_t *headerlen)
+    nic_device_id_t *device_id, void **header, size_t *headerlen)
 {
 	if ((!destination) || (addrlen == 0))
@@ -196,5 +196,5 @@
  *
  */
-int ip_packet_size_req_remote(async_sess_t *sess, device_id_t device_id,
+int ip_packet_size_req_remote(async_sess_t *sess, nic_device_id_t device_id,
     packet_dimension_t *packet_dimension)
 {
@@ -216,5 +216,5 @@
  *
  */
-int ip_received_error_msg_remote(async_sess_t *sess, device_id_t device_id,
+int ip_received_error_msg_remote(async_sess_t *sess, nic_device_id_t device_id,
     packet_t *packet, services_t target, services_t error)
 {
@@ -240,5 +240,5 @@
  *
  */
-int ip_send_msg_remote(async_sess_t *sess, device_id_t device_id,
+int ip_send_msg_remote(async_sess_t *sess, nic_device_id_t device_id,
     packet_t *packet, services_t sender, services_t error)
 {
@@ -256,5 +256,5 @@
  *
  */
-int ip_set_gateway_req_remote(async_sess_t *sess, device_id_t device_id,
+int ip_set_gateway_req_remote(async_sess_t *sess, nic_device_id_t device_id,
     in_addr_t gateway)
 {
Index: uspace/lib/net/include/arp_interface.h
===================================================================
--- uspace/lib/net/include/arp_interface.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/arp_interface.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -46,10 +46,10 @@
 /*@{*/
 
-extern int arp_device_req(async_sess_t *, device_id_t, services_t, services_t,
+extern int arp_device_req(async_sess_t *, nic_device_id_t, services_t, services_t,
     measured_string_t *);
-extern int arp_translate_req(async_sess_t *, device_id_t, services_t,
+extern int arp_translate_req(async_sess_t *, nic_device_id_t, services_t,
     measured_string_t *, measured_string_t **, uint8_t **);
-extern int arp_clear_device_req(async_sess_t *, device_id_t);
-extern int arp_clear_address_req(async_sess_t *, device_id_t, services_t,
+extern int arp_clear_device_req(async_sess_t *, nic_device_id_t);
+extern int arp_clear_address_req(async_sess_t *, nic_device_id_t, services_t,
     measured_string_t *);
 extern int arp_clean_cache_req(async_sess_t *);
Index: uspace/lib/net/include/generic.h
===================================================================
--- uspace/lib/net/include/generic.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/generic.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -45,16 +45,16 @@
 
 extern int generic_device_state_msg_remote(async_sess_t *, sysarg_t,
-    device_id_t, sysarg_t, services_t);
-extern int generic_device_req_remote(async_sess_t *, sysarg_t, device_id_t,
-    sysarg_t, services_t);
-extern int generic_get_addr_req(async_sess_t *, sysarg_t, device_id_t,
-    measured_string_t **, uint8_t **);
-extern int generic_packet_size_req_remote(async_sess_t *, sysarg_t, device_id_t,
-    packet_dimension_t *);
-extern int generic_received_msg_remote(async_sess_t *, sysarg_t, device_id_t,
+    nic_device_id_t, sysarg_t, services_t);
+extern int generic_device_req_remote(async_sess_t *, sysarg_t, nic_device_id_t,
+    services_t);
+extern int generic_get_addr_req(async_sess_t *, sysarg_t, nic_device_id_t,
+    uint8_t *address, size_t max_length);
+extern int generic_packet_size_req_remote(async_sess_t *, sysarg_t,
+    nic_device_id_t, packet_dimension_t *);
+extern int generic_received_msg_remote(async_sess_t *, sysarg_t,
+    nic_device_id_t, packet_id_t, services_t, services_t);
+extern int generic_send_msg_remote(async_sess_t *, sysarg_t, nic_device_id_t,
     packet_id_t, services_t, services_t);
-extern int generic_send_msg_remote(async_sess_t *, sysarg_t, device_id_t,
-    packet_id_t, services_t, services_t);
-extern int generic_translate_req(async_sess_t *, sysarg_t, device_id_t,
+extern int generic_translate_req(async_sess_t *, sysarg_t, nic_device_id_t,
     services_t, measured_string_t *, size_t, measured_string_t **, uint8_t **);
 
Index: uspace/lib/net/include/il_remote.h
===================================================================
--- uspace/lib/net/include/il_remote.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/il_remote.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -50,8 +50,12 @@
 /*@{*/
 
-extern int il_device_state_msg(async_sess_t *, device_id_t, device_state_t,
+extern int il_device_state_msg(async_sess_t *, nic_device_id_t,
+    nic_device_state_t, services_t);
+extern int il_received_msg(async_sess_t *, nic_device_id_t, packet_t *,
     services_t);
-extern int il_received_msg(async_sess_t *, device_id_t, packet_t *, services_t);
-extern int il_mtu_changed_msg(async_sess_t *, device_id_t, size_t, services_t);
+extern int il_mtu_changed_msg(async_sess_t *, nic_device_id_t, size_t,
+    services_t);
+extern int il_addr_changed_msg(async_sess_t *, nic_device_id_t, size_t,
+    const uint8_t *);
 
 /*@}*/
Index: uspace/lib/net/include/ip_interface.h
===================================================================
--- uspace/lib/net/include/ip_interface.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/ip_interface.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -69,5 +69,5 @@
  *
  */
-typedef int (*tl_received_msg_t)(device_id_t device_id, packet_t *packet,
+typedef int (*tl_received_msg_t)(nic_device_id_t device_id, packet_t *packet,
     services_t receiver, services_t error);
 
Index: uspace/lib/net/include/ip_remote.h
===================================================================
--- uspace/lib/net/include/ip_remote.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/ip_remote.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -43,16 +43,16 @@
 #include <async.h>
 
-extern int ip_set_gateway_req_remote(async_sess_t *, device_id_t, in_addr_t);
-extern int ip_packet_size_req_remote(async_sess_t *, device_id_t,
+extern int ip_set_gateway_req_remote(async_sess_t *, nic_device_id_t, in_addr_t);
+extern int ip_packet_size_req_remote(async_sess_t *, nic_device_id_t,
     packet_dimension_t *);
-extern int ip_received_error_msg_remote(async_sess_t *, device_id_t, packet_t *,
+extern int ip_received_error_msg_remote(async_sess_t *, nic_device_id_t, packet_t *,
     services_t, services_t);
-extern int ip_device_req_remote(async_sess_t *, device_id_t, services_t);
-extern int ip_add_route_req_remote(async_sess_t *, device_id_t, in_addr_t,
+extern int ip_device_req_remote(async_sess_t *, nic_device_id_t, services_t);
+extern int ip_add_route_req_remote(async_sess_t *, nic_device_id_t, in_addr_t,
     in_addr_t, in_addr_t);
-extern int ip_send_msg_remote(async_sess_t *, device_id_t, packet_t *,
+extern int ip_send_msg_remote(async_sess_t *, nic_device_id_t, packet_t *,
     services_t, services_t);
 extern int ip_get_route_req_remote(async_sess_t *, ip_protocol_t,
-    const struct sockaddr *, socklen_t, device_id_t *, void **, size_t *);
+    const struct sockaddr *, socklen_t, nic_device_id_t *, void **, size_t *);
 
 #endif
Index: uspace/lib/net/include/net_checksum.h
===================================================================
--- uspace/lib/net/include/net_checksum.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/net_checksum.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -30,5 +30,4 @@
  * @{
  */
-
 /** @file
  * General CRC and checksum computation.
@@ -42,14 +41,22 @@
 
 /** IP checksum value for computed zero checksum.
+ *
  * Zero is returned as 0xFFFF (not flipped)
+ *
  */
-#define IP_CHECKSUM_ZERO	0xffffU
+#define IP_CHECKSUM_ZERO  0xffffU
 
-#ifdef ARCH_IS_BIG_ENDIAN
+#ifdef __BE__
+
 #define compute_crc32(seed, data, length) \
 	compute_crc32_be(seed, (uint8_t *) data, length)
-#else
+
+#endif
+
+#ifdef __LE__
+
 #define compute_crc32(seed, data, length) \
 	compute_crc32_le(seed, (uint8_t *) data, length)
+
 #endif
 
Index: uspace/lib/net/include/net_interface.h
===================================================================
--- uspace/lib/net/include/net_interface.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/net_interface.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -35,8 +35,8 @@
 
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <adt/measured_strings.h>
 #include <async.h>
+#include <devman.h>
 
 /** @name Networking module interface
@@ -45,9 +45,12 @@
 /*@{*/
 
-extern int net_get_device_conf_req(async_sess_t *, device_id_t,
+extern int net_get_device_conf_req(async_sess_t *, nic_device_id_t,
     measured_string_t **, size_t, uint8_t **);
 extern int net_get_conf_req(async_sess_t *, measured_string_t **, size_t,
     uint8_t **);
 extern void net_free_settings(measured_string_t *, uint8_t *);
+extern int net_get_devices_req(async_sess_t *, measured_string_t **, size_t *,
+    uint8_t **);
+extern int net_driver_ready(async_sess_t *, devman_handle_t);
 extern async_sess_t *net_connect_module(void);
 
Index: pace/lib/net/include/netif_remote.h
===================================================================
--- uspace/lib/net/include/netif_remote.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libnet
- * @{
- */
-
-#ifndef LIBNET_NETIF_REMOTE_H_
-#define LIBNET_NETIF_REMOTE_H_
-
-#include <ipc/services.h>
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <async.h>
-
-extern int netif_get_addr_req(async_sess_t *, device_id_t, measured_string_t **,
-    uint8_t **);
-extern int netif_probe_req(async_sess_t *, device_id_t, int, void *);
-extern int netif_send_msg(async_sess_t *, device_id_t, packet_t *, services_t);
-extern int netif_start_req(async_sess_t *, device_id_t);
-extern int netif_stop_req(async_sess_t *, device_id_t);
-extern int netif_stats_req(async_sess_t *, device_id_t, device_stats_t *);
-extern async_sess_t *netif_bind_service(services_t, device_id_t, services_t,
-    async_client_conn_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/net/include/netif_skel.h
===================================================================
--- uspace/lib/net/include/netif_skel.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,212 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libnet
- * @{
- */
-
-/** @file
- * Network interface module skeleton.
- * The skeleton has to be part of each network interface module.
- */
-
-#ifndef NET_NETIF_SKEL_H_
-#define NET_NETIF_SKEL_H_
-
-#include <fibril_synch.h>
-#include <ipc/services.h>
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <async.h>
-
-/** Network interface device specific data. */
-typedef struct {
-	device_id_t device_id;   /**< Device identifier. */
-	device_state_t state;    /**< Actual device state. */
-	void *specific;          /**< Driver specific data. */
-} netif_device_t;
-
-/** Device map.
- *
- * Maps device identifiers to the network interface device specific data.
- * @see device.h
- *
- */
-DEVICE_MAP_DECLARE(netif_device_map, netif_device_t);
-
-/** Network interface module skeleton global data. */
-typedef struct {
-	async_sess_t *sess;             /**< Networking module session. */
-	async_sess_t *nil_sess;         /**< Network interface layer session. */
-	netif_device_map_t device_map;  /**< Device map. */
-	fibril_rwlock_t lock;           /**< Safety lock. */
-} netif_globals_t;
-
-extern netif_globals_t netif_globals;
-
-/** Initialize the specific module.
- *
- * This function has to be implemented in user code.
- *
- */
-extern int netif_initialize(void);
-
-/** Probe the existence of the device.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device_id Device identifier.
- * @param[in] irq       Device interrupt number.
- * @param[in] io        Device input/output address.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the find_device()
- *         function.
- * @return Other error codes as defined for the specific module
- *         message implementation.
- *
- */
-extern int netif_probe_message(device_id_t device_id, int irq, void *io);
-
-/** Send the packet queue.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device_id Device identifier.
- * @param[in] packet    Packet queue.
- * @param[in] sender    Sending module service.
- *
- * @return EOK on success.
- * @return EFORWARD if the device is not active (in the
- *         NETIF_ACTIVE state).
- * @return Other error codes as defined for the find_device()
- *         function.
- * @return Other error codes as defined for the specific module
- *         message implementation.
- *
- */
-extern int netif_send_message(device_id_t device_id, packet_t *packet,
-    services_t sender);
-
-/** Start the device.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device Device structure.
- *
- * @return New network interface state (non-negative values).
- * @return Other error codes as defined for the find_device()
- *         function.
- * @return Other error codes as defined for the specific module
- *         message implementation.
- *
- */
-extern int netif_start_message(netif_device_t *device);
-
-/** Stop the device.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device Device structure.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the find_device()
- *         function.
- * @return Other error codes as defined for the specific module
- *         message implementation.
- *
- */
-extern int netif_stop_message(netif_device_t *device);
-
-/** Return the device local hardware address.
- *
- * This has to be implemented in user code.
- *
- * @param[in] device_id Device identifier.
- * @param[out] address  Device local hardware address.
- *
- * @return EOK on success.
- * @return EBADMEM if the address parameter is NULL.
- * @return ENOENT if there no such device.
- * @return Other error codes as defined for the find_device()
- *         function.
- * @return Other error codes as defined for the specific module
- *         message implementation.
- *
- */
-extern int netif_get_addr_message(device_id_t device_id,
-    measured_string_t *address);
-
-/** Process the netif driver specific message.
- *
- * This function is called for uncommon messages received by the netif
- * skeleton. This has to be implemented in user code.
- *
- * @param[in]  callid Message identifier.
- * @param[in]  call   Message.
- * @param[out] answer Answer.
- * @param[out] count  Number of answer arguments.
- *
- * @return EOK on success.
- * @return ENOTSUP if the message is not known.
- * @return Other error codes as defined for the specific module
- *         message implementation.
- *
- */
-extern int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *count);
-
-/** Return the device usage statistics.
- *
- * This has to be implemented in user code.
- *
- * @param[in]  device_id Device identifier.
- * @param[out] stats     Device usage statistics.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the find_device()
- *         function.
- * @return Other error codes as defined for the specific module
- *         message implementation.
- *
- */
-extern int netif_get_device_stats(device_id_t device_id,
-    device_stats_t *stats);
-
-extern int find_device(device_id_t, netif_device_t **);
-extern void null_device_stats(device_stats_t *);
-extern void netif_pq_release(packet_id_t);
-extern packet_t *netif_packet_get_1(size_t);
-
-extern int netif_module_start(void);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/net/include/nil_remote.h
===================================================================
--- uspace/lib/net/include/nil_remote.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/nil_remote.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -34,7 +34,7 @@
 #define __NET_NIL_REMOTE_H__
 
-#include <ipc/services.h>
 #include <net/device.h>
 #include <net/packet.h>
+#include <devman.h>
 #include <generic.h>
 #include <async.h>
@@ -58,11 +58,10 @@
 	    packet_get_id(packet), sender, 0)
 
-#define nil_device_req(sess, device_id, mtu, netif_service) \
-	generic_device_req_remote(sess, NET_NIL_DEVICE, device_id, mtu, \
-	    netif_service)
-
-extern int nil_device_state_msg(async_sess_t *, device_id_t, sysarg_t);
-extern int nil_received_msg(async_sess_t *, device_id_t, packet_t *,
-    services_t);
+extern int nil_device_req(async_sess_t *, nic_device_id_t, devman_handle_t,
+    size_t);
+extern int nil_device_state_msg(async_sess_t *, nic_device_id_t, sysarg_t);
+extern int nil_received_msg(async_sess_t *, nic_device_id_t, packet_id_t);
+extern int nil_addr_changed_msg(async_sess_t *, nic_device_id_t,
+    const nic_address_t *);
 
 #endif
Index: uspace/lib/net/include/nil_skel.h
===================================================================
--- uspace/lib/net/include/nil_skel.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/nil_skel.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -70,5 +70,5 @@
  *
  */
-extern int nil_device_state_msg_local(device_id_t device_id, sysarg_t state);
+extern int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state);
 
 /** Pass the packet queue to the network interface layer.
@@ -81,5 +81,4 @@
  * @param[in] device_id Source device identifier.
  * @param[in] packet    Received packet or the received packet queue.
- * @param[in] target    Target service. Ignored parameter.
  *
  * @return EOK on success.
@@ -88,6 +87,5 @@
  *
  */
-extern int nil_received_msg_local(device_id_t device_id, packet_t *packet,
-    services_t target);
+extern int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet);
 
 /** Message processing function.
Index: uspace/lib/net/include/tl_common.h
===================================================================
--- uspace/lib/net/include/tl_common.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/tl_common.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -52,7 +52,7 @@
 
 extern int tl_get_ip_packet_dimension(async_sess_t *, packet_dimensions_t *,
-    device_id_t, packet_dimension_t **);
+    nic_device_id_t, packet_dimension_t **);
 extern int tl_get_address_port(const struct sockaddr *, int, uint16_t *);
-extern int tl_update_ip_packet_dimension(packet_dimensions_t *, device_id_t,
+extern int tl_update_ip_packet_dimension(packet_dimensions_t *, nic_device_id_t,
     size_t);
 extern int tl_set_address_port(struct sockaddr *, int, uint16_t);
Index: uspace/lib/net/include/tl_remote.h
===================================================================
--- uspace/lib/net/include/tl_remote.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/include/tl_remote.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -51,6 +51,6 @@
 /*@{*/
 
-extern int tl_received_msg(async_sess_t *, device_id_t, packet_t *, services_t,
-    services_t);
+extern int tl_received_msg(async_sess_t *, nic_device_id_t, packet_t *,
+    services_t, services_t);
 
 /*@}*/
Index: pace/lib/net/netif/netif_remote.c
===================================================================
--- uspace/lib/net/netif/netif_remote.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,199 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libnet
- * @{
- */
-
-/** @file
- * Network interface module interface implementation for remote modules.
- */
-
-#include <netif_remote.h>
-#include <packet_client.h>
-#include <generic.h>
-#include <ipc/services.h>
-#include <ipc/netif.h>
-#include <net/modules.h>
-#include <adt/measured_strings.h>
-#include <net/packet.h>
-#include <net/device.h>
-
-/** Return the device local hardware address.
- *
- * @param[in]  sess      Network interface session.
- * @param[in]  device_id Device identifier.
- * @param[out] address   Device local hardware address.
- * @param[out] data      Address data.
- *
- * @return EOK on success.
- * @return EBADMEM if the address parameter is NULL.
- * @return ENOENT if there no such device.
- * @return Other error codes as defined for the
- *         netif_get_addr_message() function.
- *
- */
-int netif_get_addr_req(async_sess_t *sess, device_id_t device_id,
-    measured_string_t **address, uint8_t **data)
-{
-	return generic_get_addr_req(sess, NET_NETIF_GET_ADDR, device_id,
-	    address, data);
-}
-
-/** Probe the existence of the device.
- *
- * @param[in] sess      Network interface session.
- * @param[in] device_id Device identifier.
- * @param[in] irq       Device interrupt number.
- * @param[in] io        Device input/output address.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the
- *         netif_probe_message().
- *
- */
-int netif_probe_req(async_sess_t *sess, device_id_t device_id, int irq, void *io)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_3_0(exch, NET_NETIF_PROBE, device_id, (sysarg_t) irq,
-	    (sysarg_t) io);
-	async_exchange_end(exch);
-	
-	return rc;
-}
-
-/** Send the packet queue.
- *
- * @param[in] sess      Network interface session.
- * @param[in] device_id Device identifier.
- * @param[in] packet    Packet queue.
- * @param[in] sender    Sending module service.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the generic_send_msg()
- *         function.
- *
- */
-int netif_send_msg(async_sess_t *sess, device_id_t device_id, packet_t *packet,
-    services_t sender)
-{
-	return generic_send_msg_remote(sess, NET_NETIF_SEND, device_id,
-	    packet_get_id(packet), sender, 0);
-}
-
-/** Start the device.
- *
- * @param[in] sess      Network interface session.
- * @param[in] device_id Device identifier.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the find_device()
- *         function.
- * @return Other error codes as defined for the
- *         netif_start_message() function.
- *
- */
-int netif_start_req(async_sess_t *sess, device_id_t device_id)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_1_0(exch, NET_NETIF_START, device_id);
-	async_exchange_end(exch);
-	
-	return rc;
-}
-
-/** Stop the device.
- *
- * @param[in] sess      Network interface session.
- * @param[in] device_id Device identifier.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the find_device()
- *         function.
- * @return Other error codes as defined for the
- *         netif_stop_message() function.
- *
- */
-int netif_stop_req(async_sess_t *sess, device_id_t device_id)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_1_0(exch, NET_NETIF_STOP, device_id);
-	async_exchange_end(exch);
-	
-	return rc;
-}
-
-/** Return the device usage statistics.
- *
- * @param[in]  sess      Network interface session.
- * @param[in]  device_id Device identifier.
- * @param[out] stats     Device usage statistics.
- *
- * @return EOK on success.
- *
- */
-int netif_stats_req(async_sess_t *sess, device_id_t device_id,
-    device_stats_t *stats)
-{
-	if (!stats)
-		return EBADMEM;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	aid_t message_id = async_send_1(exch, NET_NETIF_STATS,
-	    (sysarg_t) device_id, NULL);
-	async_data_read_start(exch, stats, sizeof(*stats));
-	async_exchange_end(exch);
-	
-	sysarg_t result;
-	async_wait_for(message_id, &result);
-	
-	return (int) result;
-}
-
-/** Create bidirectional connection with the network interface module
- *
- * Create bidirectional connection with the network interface module and
- * register the message receiver.
- *
- * @param[in] service   Network interface module service.
- * @param[in] device_id Device identifier.
- * @param[in] me        Requesting module service.
- * @param[in] receiver  Message receiver.
- *
- * @return Session to the needed service.
- * @return NULL on failure.
- *
- */
-async_sess_t *netif_bind_service(services_t service, device_id_t device_id,
-    services_t me, async_client_conn_t receiver)
-{
-	return bind_service(service, device_id, me, 0, receiver);
-}
-
-/** @}
- */
Index: pace/lib/net/netif/netif_skel.c
===================================================================
--- uspace/lib/net/netif/netif_skel.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,422 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libnet
- * @{
- */
-
-/** @file
- * Network interface module skeleton implementation.
- * @see netif_skel.h
- */
-
-#include <async.h>
-#include <mem.h>
-#include <fibril_synch.h>
-#include <stdio.h>
-#include <ipc/services.h>
-#include <ipc/netif.h>
-#include <errno.h>
-
-#include <generic.h>
-#include <net/modules.h>
-#include <net/packet.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <netif_skel.h>
-#include <nil_remote.h>
-
-DEVICE_MAP_IMPLEMENT(netif_device_map, netif_device_t);
-
-/** Network interface global data. */
-netif_globals_t netif_globals;
-
-/** Probe the existence of the device.
- *
- * @param[in] device_id   Device identifier.
- * @param[in] irq         Device interrupt number.
- * @param[in] io          Device input/output address.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the
- *         netif_probe_message().
- *
- */
-static int netif_probe_req_local(device_id_t device_id, int irq, void *io)
-{
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	int result = netif_probe_message(device_id, irq, io);
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	return result;
-}
-
-/** Send the packet queue.
- *
- * @param[in] device_id   Device identifier.
- * @param[in] packet      Packet queue.
- * @param[in] sender      Sending module service.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the generic_send_msg()
- *         function.
- *
- */
-static int netif_send_msg_local(device_id_t device_id, packet_t *packet,
-    services_t sender)
-{
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	int result = netif_send_message(device_id, packet, sender);
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	return result;
-}
-
-/** Start the device.
- *
- * @param[in] device_id   Device identifier.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the find_device()
- *         function.
- * @return Other error codes as defined for the
- *         netif_start_message() function.
- *
- */
-static int netif_start_req_local(device_id_t device_id)
-{
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	
-	netif_device_t *device;
-	int rc = find_device(device_id, &device);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		return rc;
-	}
-	
-	int result = netif_start_message(device);
-	if (result > NETIF_NULL) {
-		nil_device_state_msg(netif_globals.nil_sess, device_id, result);
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		return EOK;
-	}
-	
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	return result;
-}
-
-/** Stop the device.
- *
- * @param[in] device_id   Device identifier.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the find_device()
- *         function.
- * @return Other error codes as defined for the
- *         netif_stop_message() function.
- *
- */
-static int netif_stop_req_local(device_id_t device_id)
-{
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	
-	netif_device_t *device;
-	int rc = find_device(device_id, &device);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		return rc;
-	}
-	
-	int result = netif_stop_message(device);
-	if (result > NETIF_NULL) {
-		nil_device_state_msg(netif_globals.nil_sess, device_id, result);
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		return EOK;
-	}
-	
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	return result;
-}
-
-/** Find the device specific data.
- *
- * @param[in]  device_id Device identifier.
- * @param[out] device    Device specific data.
- *
- * @return EOK on success.
- * @return ENOENT if device is not found.
- * @return EPERM if the device is not initialized.
- *
- */
-int find_device(device_id_t device_id, netif_device_t **device)
-{
-	if (!device)
-		return EBADMEM;
-	
-	*device = netif_device_map_find(&netif_globals.device_map, device_id);
-	if (*device == NULL)
-		return ENOENT;
-	
-	if ((*device)->state == NETIF_NULL)
-		return EPERM;
-	
-	return EOK;
-}
-
-/** Clear the usage statistics.
- *
- * @param[in] stats The usage statistics.
- *
- */
-void null_device_stats(device_stats_t *stats)
-{
-	bzero(stats, sizeof(device_stats_t));
-}
-
-/** Release the given packet.
- *
- * Prepared for future optimization.
- *
- * @param[in] packet_id The packet identifier.
- *
- */
-void netif_pq_release(packet_id_t packet_id)
-{
-	pq_release_remote(netif_globals.sess, packet_id);
-}
-
-/** Allocate new packet to handle the given content size.
- *
- * @param[in] content Minimum content size.
- *
- * @return The allocated packet.
- * @return NULL on error.
- *
- */
-packet_t *netif_packet_get_1(size_t content)
-{
-	return packet_get_1_remote(netif_globals.sess, content);
-}
-
-/** Register the device notification receiver,
- *
- * Register a network interface layer module as the device
- * notification receiver.
- *
- * @param[in] sess      Session to the network interface layer module.
- *
- * @return EOK on success.
- * @return ELIMIT if there is another module registered.
- *
- */
-static int register_message(async_sess_t *sess)
-{
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	if (netif_globals.nil_sess != NULL) {
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		return ELIMIT;
-	}
-	
-	netif_globals.nil_sess = sess;
-	
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	return EOK;
-}
-
-/** Process the netif module messages.
- *
- * @param[in]  callid Mmessage identifier.
- * @param[in]  call   Message.
- * @param[out] answer Answer.
- * @param[out] count  Number of arguments of the answer.
- *
- * @return EOK on success.
- * @return ENOTSUP if the message is unknown.
- * @return Other error codes as defined for each specific module
- *         message function.
- *
- * @see IS_NET_NETIF_MESSAGE()
- *
- */
-static int netif_module_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *count)
-{
-	size_t length;
-	device_stats_t stats;
-	packet_t *packet;
-	measured_string_t address;
-	int rc;
-	
-	*count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return register_message(callback);
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_NETIF_PROBE:
-		return netif_probe_req_local(IPC_GET_DEVICE(*call),
-		    NETIF_GET_IRQ(*call), NETIF_GET_IO(*call));
-	
-	case NET_NETIF_SEND:
-		rc = packet_translate_remote(netif_globals.sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return netif_send_msg_local(IPC_GET_DEVICE(*call), packet,
-		    IPC_GET_SENDER(*call));
-	
-	case NET_NETIF_START:
-		return netif_start_req_local(IPC_GET_DEVICE(*call));
-	
-	case NET_NETIF_STATS:
-		fibril_rwlock_read_lock(&netif_globals.lock);
-		
-		rc = async_data_read_receive(&callid, &length);
-		if (rc != EOK) {
-			fibril_rwlock_read_unlock(&netif_globals.lock);
-			return rc;
-		}
-		
-		if (length < sizeof(device_stats_t)) {
-			fibril_rwlock_read_unlock(&netif_globals.lock);
-			return EOVERFLOW;
-		}
-		
-		rc = netif_get_device_stats(IPC_GET_DEVICE(*call), &stats);
-		if (rc == EOK) {
-			rc = async_data_read_finalize(callid, &stats,
-			    sizeof(device_stats_t));
-		}
-		
-		fibril_rwlock_read_unlock(&netif_globals.lock);
-		return rc;
-	
-	case NET_NETIF_STOP:
-		return netif_stop_req_local(IPC_GET_DEVICE(*call));
-	
-	case NET_NETIF_GET_ADDR:
-		fibril_rwlock_read_lock(&netif_globals.lock);
-		
-		rc = netif_get_addr_message(IPC_GET_DEVICE(*call), &address);
-		if (rc == EOK)
-			rc = measured_strings_reply(&address, 1);
-		
-		fibril_rwlock_read_unlock(&netif_globals.lock);
-		return rc;
-	}
-	
-	return netif_specific_message(callid, call, answer, count);
-}
-
-/** Default fibril for new module connections.
- *
- * @param[in] iid   Initial message identifier.
- * @param[in] icall Initial message call structure.
- *
- */
-static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg)
-{
-	/*
-	 * Accept the connection by answering
-	 * the initial IPC_M_CONNECT_ME_TO call.
-	 */
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		size_t count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = netif_module_message(callid, &call, &answer, &count);
-		
-		/* End if said to either by the message or the processing result */
-		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, count);
-	}
-}
-
-/** Start the network interface module.
- *
- * Initialize the client connection serving function, initialize the module,
- * registers the module service and start the async manager, processing IPC
- * messages in an infinite loop.
- *
- * @return EOK on success.
- * @return Other error codes as defined for each specific module
- *         message function.
- *
- */
-int netif_module_start(void)
-{
-	async_set_client_connection(netif_client_connection);
-	
-	netif_globals.sess = connect_to_service(SERVICE_NETWORKING);
-	netif_globals.nil_sess = NULL;
-	netif_device_map_initialize(&netif_globals.device_map);
-	
-	int rc = pm_init();
-	if (rc != EOK)
-		return rc;
-	
-	fibril_rwlock_initialize(&netif_globals.lock);
-	
-	rc = netif_initialize();
-	if (rc != EOK) {
-		pm_destroy();
-		return rc;
-	}
-	
-	async_manager();
-	
-	pm_destroy();
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/lib/net/nil/nil_remote.c
===================================================================
--- uspace/lib/net/nil/nil_remote.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/nil/nil_remote.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -54,5 +54,5 @@
  *
  */
-int nil_device_state_msg(async_sess_t *sess, device_id_t device_id,
+int nil_device_state_msg(async_sess_t *sess, nic_device_id_t device_id,
     sysarg_t state)
 {
@@ -76,9 +76,44 @@
  *
  */
-int nil_received_msg(async_sess_t *sess, device_id_t device_id,
-    packet_t *packet, services_t target)
+int nil_received_msg(async_sess_t *sess, nic_device_id_t device_id,
+    packet_id_t packet_id)
 {
 	return generic_received_msg_remote(sess, NET_NIL_RECEIVED,
-	    device_id, packet_get_id(packet), target, 0);
+	    device_id, packet_id, 0, 0);
+}
+
+/** Notify upper layers that device address has changed
+ *
+ */
+int nil_addr_changed_msg(async_sess_t *sess, nic_device_id_t device_id,
+    const nic_address_t *address)
+{
+	assert(sess);
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	aid_t message_id = async_send_1(exch, NET_NIL_ADDR_CHANGED,
+	    (sysarg_t) device_id, NULL);
+	int rc = async_data_write_start(exch, address, sizeof (nic_address_t));
+	
+	async_exchange_end(exch);
+	
+	sysarg_t res;
+    async_wait_for(message_id, &res);
+	
+    if (rc != EOK)
+		return rc;
+	
+    return (int) res;
+}
+
+int nil_device_req(async_sess_t *sess, nic_device_id_t device_id,
+    devman_handle_t handle, size_t mtu)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_3_0(exch, NET_NIL_DEVICE, (sysarg_t) device_id,
+	    (sysarg_t) handle, (sysarg_t) mtu);
+	async_exchange_end(exch);
+	return rc;
 }
 
Index: uspace/lib/net/tl/icmp_client.c
===================================================================
--- uspace/lib/net/tl/icmp_client.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/tl/icmp_client.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -39,12 +39,6 @@
 #include <icmp_header.h>
 #include <packet_client.h>
-
-#ifdef CONFIG_DEBUG
-#include <stdio.h>
-#endif
-
 #include <errno.h>
 #include <sys/types.h>
-
 #include <net/icmp_codes.h>
 #include <net/packet.h>
@@ -60,6 +54,5 @@
  * @return		Zero if the packet contains no data.
  */
-int
-icmp_client_process_packet(packet_t *packet, icmp_type_t *type,
+int icmp_client_process_packet(packet_t *packet, icmp_type_t *type,
     icmp_code_t *code, icmp_param_t *pointer, icmp_param_t *mtu)
 {
@@ -81,9 +74,4 @@
 		*mtu = header->un.frag.mtu;
 
-	/* Remove debug dump */
-#ifdef CONFIG_DEBUG
-	printf("ICMP error %d (%d) in packet %d\n", header->type, header->code,
-	    packet_get_id(packet));
-#endif
 	return sizeof(icmp_header_t);
 }
Index: uspace/lib/net/tl/tl_common.c
===================================================================
--- uspace/lib/net/tl/tl_common.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/tl/tl_common.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -119,5 +119,5 @@
  */
 int tl_get_ip_packet_dimension(async_sess_t *sess,
-    packet_dimensions_t *packet_dimensions, device_id_t device_id,
+    packet_dimensions_t *packet_dimensions, nic_device_id_t device_id,
     packet_dimension_t **packet_dimension)
 {
@@ -160,5 +160,5 @@
 int
 tl_update_ip_packet_dimension(packet_dimensions_t *packet_dimensions,
-    device_id_t device_id, size_t content)
+    nic_device_id_t device_id, size_t content)
 {
 	packet_dimension_t *packet_dimension;
@@ -170,7 +170,7 @@
 	packet_dimension->content = content;
 
-	if (device_id != DEVICE_INVALID_ID) {
+	if (device_id != NIC_DEVICE_INVALID_ID) {
 		packet_dimension = packet_dimensions_find(packet_dimensions,
-		    DEVICE_INVALID_ID);
+		    NIC_DEVICE_INVALID_ID);
 
 		if (packet_dimension) {
@@ -179,5 +179,5 @@
 			else
 				packet_dimensions_exclude(packet_dimensions,
-				    DEVICE_INVALID_ID, free);
+				    NIC_DEVICE_INVALID_ID, free);
 		}
 	}
Index: uspace/lib/net/tl/tl_remote.c
===================================================================
--- uspace/lib/net/tl/tl_remote.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/lib/net/tl/tl_remote.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -56,5 +56,5 @@
  *
  */
-int tl_received_msg(async_sess_t *sess, device_id_t device_id, packet_t *packet,
+int tl_received_msg(async_sess_t *sess, nic_device_id_t device_id, packet_t *packet,
     services_t target, services_t error)
 {
Index: pace/lib/packet/Makefile
===================================================================
--- uspace/lib/packet/Makefile	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../..
-EXTRA_CFLAGS = -Iinclude
-LIBRARY = libpacket
-
-SOURCES = \
-	generic/packet_server.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/lib/packet/generic/packet_server.c
===================================================================
--- uspace/lib/packet/generic/packet_server.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,374 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libpacket
- *  @{
- */
-
-/** @file
- * Packet server implementation.
- */
-
-#include <packet_server.h>
-#include <align.h>
-#include <assert.h>
-#include <async.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <ipc/packet.h>
-#include <ipc/net.h>
-#include <net/packet.h>
-#include <net/packet_header.h>
-
-#define FREE_QUEUES_COUNT	7
-
-/** The default address length reserved for new packets. */
-#define DEFAULT_ADDR_LEN	32
-
-/** The default prefix reserved for new packets. */
-#define DEFAULT_PREFIX		64
-
-/** The default suffix reserved for new packets. */
-#define DEFAULT_SUFFIX		64
-
-/** Packet server global data. */
-static struct {
-	/** Safety lock. */
-	fibril_mutex_t lock;
-	/** Free packet queues. */
-	packet_t *free[FREE_QUEUES_COUNT];
-	
-	/**
-	 * Packet length upper bounds of the free packet queues. The maximal
-	 * lengths of packets in each queue in the ascending order. The last
-	 * queue is not limited.
-	 */
-	size_t sizes[FREE_QUEUES_COUNT];
-	
-	/** Total packets allocated. */
-	unsigned int count;
-} ps_globals = {
-	.lock = FIBRIL_MUTEX_INITIALIZER(ps_globals.lock),
-	.free = {
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL,
-		NULL
-	},
-	.sizes = {
-		PAGE_SIZE,
-		PAGE_SIZE * 2,
-		PAGE_SIZE * 4,
-		PAGE_SIZE * 8,
-		PAGE_SIZE * 16,
-		PAGE_SIZE * 32,
-		PAGE_SIZE * 64
-	},
-	.count = 0
-};
-
-/** Clears and initializes the packet according to the given dimensions.
- *
- * @param[in] packet	The packet to be initialized.
- * @param[in] addr_len	The source and destination addresses maximal length in
- *			bytes.
- * @param[in] max_prefix The maximal prefix length in bytes.
- * @param[in] max_content The maximal content length in bytes.
- * @param[in] max_suffix The maximal suffix length in bytes.
- */
-static void
-packet_init(packet_t *packet, size_t addr_len, size_t max_prefix,
-    size_t max_content, size_t max_suffix)
-{
-	/* Clear the packet content */
-	bzero(((void *) packet) + sizeof(packet_t),
-	    packet->length - sizeof(packet_t));
-	
-	/* Clear the packet header */
-	packet->order = 0;
-	packet->metric = 0;
-	packet->previous = 0;
-	packet->next = 0;
-	packet->addr_len = 0;
-	packet->src_addr = sizeof(packet_t);
-	packet->dest_addr = packet->src_addr + addr_len;
-	packet->max_prefix = max_prefix;
-	packet->max_content = max_content;
-	packet->data_start = packet->dest_addr + addr_len + packet->max_prefix;
-	packet->data_end = packet->data_start;
-}
-
-/** Creates a new packet of dimensions at least as given.
- *
- * @param[in] length	The total length of the packet, including the header,
- *			the addresses and the data of the packet.
- * @param[in] addr_len	The source and destination addresses maximal length in
- *			bytes.
- * @param[in] max_prefix The maximal prefix length in bytes.
- * @param[in] max_content The maximal content length in bytes.
- * @param[in] max_suffix The maximal suffix length in bytes.
- * @return		The packet of dimensions at least as given.
- * @return		NULL if there is not enough memory left.
- */
-static packet_t *
-packet_create(size_t length, size_t addr_len, size_t max_prefix,
-    size_t max_content, size_t max_suffix)
-{
-	packet_t *packet;
-	int rc;
-
-	assert(fibril_mutex_is_locked(&ps_globals.lock));
-
-	/* Already locked */
-	packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
-	    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
-	if (packet == MAP_FAILED)
-		return NULL;
-
-	ps_globals.count++;
-	packet->packet_id = ps_globals.count;
-	packet->length = length;
-	packet_init(packet, addr_len, max_prefix, max_content, max_suffix);
-	packet->magic_value = PACKET_MAGIC_VALUE;
-	rc = pm_add(packet);
-	if (rc != EOK) {
-		munmap(packet, packet->length);
-		return NULL;
-	}
-	
-	return packet;
-}
-
-/** Return the packet of dimensions at least as given.
- *
- * Try to reuse free packets first.
- * Create a new packet aligned to the memory page size if none available.
- * Lock the global data during its processing.
- *
- * @param[in] addr_len	The source and destination addresses maximal length in
- *			bytes.
- * @param[in] max_prefix The maximal prefix length in bytes.
- * @param[in] max_content The maximal content length in bytes.
- * @param[in] max_suffix The maximal suffix length in bytes.
- * @return		The packet of dimensions at least as given.
- * @return		NULL if there is not enough memory left.
- */
-static packet_t *
-packet_get_local(size_t addr_len, size_t max_prefix, size_t max_content,
-    size_t max_suffix)
-{
-	size_t length = ALIGN_UP(sizeof(packet_t) + 2 * addr_len +
-	    max_prefix + max_content + max_suffix, PAGE_SIZE);
-	
-	fibril_mutex_lock(&ps_globals.lock);
-	
-	packet_t *packet;
-	unsigned int index;
-	
-	for (index = 0; index < FREE_QUEUES_COUNT; index++) {
-		if ((length > ps_globals.sizes[index]) &&
-		    (index < FREE_QUEUES_COUNT - 1))
-			continue;
-		
-		packet = ps_globals.free[index];
-		while (packet_is_valid(packet) && (packet->length < length))
-			packet = pm_find(packet->next);
-		
-		if (packet_is_valid(packet)) {
-			if (packet == ps_globals.free[index])
-				ps_globals.free[index] = pq_detach(packet);
-			else
-				pq_detach(packet);
-			
-			packet_init(packet, addr_len, max_prefix, max_content,
-			    max_suffix);
-			fibril_mutex_unlock(&ps_globals.lock);
-			
-			return packet;
-		}
-	}
-	
-	packet = packet_create(length, addr_len, max_prefix, max_content,
-	    max_suffix);
-	
-	fibril_mutex_unlock(&ps_globals.lock);
-	
-	return packet;
-}
-
-/** Release the packet and returns it to the appropriate free packet queue.
- *
- * @param[in] packet	The packet to be released.
- *
- */
-static void packet_release(packet_t *packet)
-{
-	int index;
-	int result;
-
-	assert(fibril_mutex_is_locked(&ps_globals.lock));
-
-	for (index = 0; (index < FREE_QUEUES_COUNT - 1) &&
-	    (packet->length > ps_globals.sizes[index]); index++) {
-		;
-	}
-	
-	result = pq_add(&ps_globals.free[index], packet, packet->length,
-	    packet->length);
-	assert(result == EOK);
-}
-
-/** Releases the packet queue.
- *
- * @param[in] packet_id	The first packet identifier.
- * @return		EOK on success.
- * @return		ENOENT if there is no such packet.
- */
-static int packet_release_wrapper(packet_id_t packet_id)
-{
-	packet_t *packet;
-
-	packet = pm_find(packet_id);
-	if (!packet_is_valid(packet))
-		return ENOENT;
-
-	fibril_mutex_lock(&ps_globals.lock);
-	pq_destroy(packet, packet_release);
-	fibril_mutex_unlock(&ps_globals.lock);
-
-	return EOK;
-}
-
-/** Shares the packet memory block.
- * @param[in] packet	The packet to be shared.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		EINVAL if the calling module does not accept the memory.
- * @return		ENOMEM if the desired and actual sizes differ.
- * @return		Other error codes as defined for the
- *			async_share_in_finalize() function.
- */
-static int packet_reply(packet_t *packet)
-{
-	ipc_callid_t callid;
-	size_t size;
-
-	if (!packet_is_valid(packet))
-		return EINVAL;
-
-	if (!async_share_in_receive(&callid, &size)) {
-		async_answer_0(callid, EINVAL);
-		return EINVAL;
-	}
-
-	if (size != packet->length) {
-		async_answer_0(callid, ENOMEM);
-		return ENOMEM;
-	}
-	
-	return async_share_in_finalize(callid, packet,
-	    PROTO_READ | PROTO_WRITE);
-}
-
-/** Processes the packet server message.
- *
- * @param[in] callid	The message identifier.
- * @param[in] call	The message parameters.
- * @param[out] answer	The message answer parameters.
- * @param[out] answer_count The last parameter for the actual answer in the
- *			answer parameter.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- * @return		ENOENT if there is no such packet as in the packet
- *			message parameter.
- * @return		ENOTSUP if the message is not known.
- * @return		Other error codes as defined for the
- *			packet_release_wrapper() function.
- */
-int packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    size_t *answer_count)
-{
-	packet_t *packet;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	*answer_count = 0;
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_PACKET_CREATE_1:
-		packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX,
-		    IPC_GET_CONTENT(*call), DEFAULT_SUFFIX);
-		if (!packet)
-			return ENOMEM;
-		*answer_count = 2;
-		IPC_SET_ARG1(*answer, (sysarg_t) packet->packet_id);
-		IPC_SET_ARG2(*answer, (sysarg_t) packet->length);
-		return EOK;
-	
-	case NET_PACKET_CREATE_4:
-		packet = packet_get_local(
-		    ((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(*call)) ?
-		    IPC_GET_ADDR_LEN(*call) : DEFAULT_ADDR_LEN),
-		    DEFAULT_PREFIX + IPC_GET_PREFIX(*call),
-		    IPC_GET_CONTENT(*call),
-		    DEFAULT_SUFFIX + IPC_GET_SUFFIX(*call));
-		if (!packet)
-			return ENOMEM;
-		*answer_count = 2;
-		IPC_SET_ARG1(*answer, (sysarg_t) packet->packet_id);
-		IPC_SET_ARG2(*answer, (sysarg_t) packet->length);
-		return EOK;
-	
-	case NET_PACKET_GET:
-		packet = pm_find(IPC_GET_ID(*call));
-		if (!packet_is_valid(packet))
-			return ENOENT;
-		return packet_reply(packet);
-	
-	case NET_PACKET_GET_SIZE:
-		packet = pm_find(IPC_GET_ID(*call));
-		if (!packet_is_valid(packet))
-			return ENOENT;
-		IPC_SET_ARG1(*answer, (sysarg_t) packet->length);
-		*answer_count = 1;
-		return EOK;
-	
-	case NET_PACKET_RELEASE:
-		return packet_release_wrapper(IPC_GET_ID(*call));
-	}
-	
-	return ENOTSUP;
-}
-
-/** @}
- */
Index: pace/lib/packet/include/packet_server.h
===================================================================
--- uspace/lib/packet/include/packet_server.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libpacket
- * @{
- */
-
-/** @file
- * Packet server.
- * The hosting module has to be compiled with both the packet.c and the
- * packet_server.c source files. To function correctly, initialization of the
- * packet map by the pm_init() function has to happen at the first place. Then
- * the packet messages have to be processed by the packet_server_message()
- * function. The packet map should be released by the pm_destroy() function
- * during the module termination.
- * @see IS_NET_PACKET_MESSAGE()
- */
-
-#ifndef LIBPACKET_PACKET_SERVER_H_
-#define LIBPACKET_PACKET_SERVER_H_
-
-#include <ipc/common.h>
-
-extern int packet_server_message(ipc_callid_t, ipc_call_t *, ipc_call_t *,
-    size_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/devman/devman.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -794,4 +794,7 @@
 	case EOK:
 		dev->state = DEVICE_USABLE;
+		exch = async_exchange_begin(drv->sess);
+		async_msg_1(exch, DRIVER_DEV_ADDED, dev->handle);
+		async_exchange_end(exch);
 		break;
 	case ENOENT:
Index: pace/srv/hw/netif/ne2000/Makefile
===================================================================
--- uspace/srv/hw/netif/ne2000/Makefile	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,47 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-BINARY = ne2000
-
-SOURCES = \
-	dp8390.c \
-	ne2000.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/hw/netif/ne2000/dp8390.c
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,655 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This code is based upon the NE2000 driver for MINIX,
- * distributed according to a BSD-style license.
- *
- * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
- * Copyright (c) 1992, 1994 Philip Homburg
- * Copyright (c) 1996 G. Falzoni
- *
- */
-
-/** @addtogroup ne2000
- *  @{
- */
-
-/** @file
- *
- * NE2000 (based on DP8390) network interface core implementation.
- * Only the basic NE2000 PIO (ISA) interface is supported, remote
- * DMA is completely absent from this code for simplicity.
- *
- */
-
-#include <assert.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <stdio.h>
-#include <libarch/ddi.h>
-#include <net/packet.h>
-#include <packet_client.h>
-#include "dp8390.h"
-
-/** Page size */
-#define DP_PAGE  256
-
-/** 6 * DP_PAGE >= 1514 bytes */
-#define SQ_PAGES  6
-
-/* NE2000 implementation. */
-
-/** NE2000 Data Register */
-#define NE2K_DATA  0x0010
-
-/** NE2000 Reset register */
-#define NE2K_RESET  0x001f
-
-/** NE2000 data start */
-#define NE2K_START  0x4000
-
-/** NE2000 data size */
-#define NE2K_SIZE  0x4000
-
-/** NE2000 retry count */
-#define NE2K_RETRY  0x1000
-
-/** NE2000 error messages rate limiting */
-#define NE2K_ERL  10
-
-/** Minimum Ethernet packet size in bytes */
-#define ETH_MIN_PACK_SIZE  60
-
-/** Maximum Ethernet packet size in bytes */
-#define ETH_MAX_PACK_SIZE_TAGGED  1518
-
-/** Type definition of the receive header
- *
- */
-typedef struct {
-	/** Copy of RSR */
-	uint8_t status;
-	
-	/** Pointer to next packet */
-	uint8_t next;
-	
-	/** Receive Byte Count Low */
-	uint8_t rbcl;
-	
-	/** Receive Byte Count High */
-	uint8_t rbch;
-} recv_header_t;
-
-/** Read a memory block word by word.
- *
- * @param[in]  port Source address.
- * @param[out] buf  Destination buffer.
- * @param[in]  size Memory block size in bytes.
- *
- */
-static void pio_read_buf_16(void *port, void *buf, size_t size)
-{
-	size_t i;
-	
-	for (i = 0; (i << 1) < size; i++)
-		*((uint16_t *) buf + i) = pio_read_16((ioport16_t *) (port));
-}
-
-/** Write a memory block word by word.
- *
- * @param[in] port Destination address.
- * @param[in] buf  Source buffer.
- * @param[in] size Memory block size in bytes.
- *
- */
-static void pio_write_buf_16(void *port, void *buf, size_t size)
-{
-	size_t i;
-	
-	for (i = 0; (i << 1) < size; i++)
-		pio_write_16((ioport16_t *) port, *((uint16_t *) buf + i));
-}
-
-static void ne2k_download(ne2k_t *ne2k, void *buf, size_t addr, size_t size)
-{
-	size_t esize = size & ~1;
-	
-	pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff);
-	pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff);
-	pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff);
-	pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff);
-	pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	if (esize != 0) {
-		pio_read_buf_16(ne2k->data_port, buf, esize);
-		size -= esize;
-		buf += esize;
-	}
-	
-	if (size) {
-		assert(size == 1);
-		
-		uint16_t word = pio_read_16(ne2k->data_port);
-		memcpy(buf, &word, 1);
-	}
-}
-
-static void ne2k_upload(ne2k_t *ne2k, void *buf, size_t addr, size_t size)
-{
-	size_t esize = size & ~1;
-	
-	pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff);
-	pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff);
-	pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff);
-	pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff);
-	pio_write_8(ne2k->port + DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
-	
-	if (esize != 0) {
-		pio_write_buf_16(ne2k->data_port, buf, esize);
-		size -= esize;
-		buf += esize;
-	}
-	
-	if (size) {
-		assert(size == 1);
-		
-		uint16_t word = 0;
-		
-		memcpy(&word, buf, 1);
-		pio_write_16(ne2k->data_port, word);
-	}
-}
-
-static void ne2k_init(ne2k_t *ne2k)
-{
-	unsigned int i;
-	
-	/* Reset the ethernet card */
-	uint8_t val = pio_read_8(ne2k->port + NE2K_RESET);
-	usleep(2000);
-	pio_write_8(ne2k->port + NE2K_RESET, val);
-	usleep(2000);
-	
-	/* Reset the DP8390 */
-	pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
-	for (i = 0; i < NE2K_RETRY; i++) {
-		if (pio_read_8(ne2k->port + DP_ISR) != 0)
-			break;
-	}
-}
-
-/** Probe and initialize the network interface.
- *
- * @param[in,out] ne2k Network interface structure.
- * @param[in]     port Device address.
- * @param[in]     irq  Device interrupt vector.
- *
- * @return EOK on success.
- * @return EXDEV if the network interface was not recognized.
- *
- */
-int ne2k_probe(ne2k_t *ne2k, void *port, int irq)
-{
-	unsigned int i;
-	
-	/* General initialization */
-	ne2k->port = port;
-	ne2k->data_port = ne2k->port + NE2K_DATA;
-	ne2k->irq = irq;
-	ne2k->probed = false;
-	ne2k->up = false;
-	
-	ne2k_init(ne2k);
-	
-	/* Check if the DP8390 is really there */
-	uint8_t val = pio_read_8(ne2k->port + DP_CR);
-	if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
-		return EXDEV;
-	
-	/* Disable the receiver and init TCR and DCR */
-	pio_write_8(ne2k->port + DP_RCR, RCR_MON);
-	pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
-	pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
-	
-	/* Setup a transfer to get the MAC address */
-	pio_write_8(ne2k->port + DP_RBCR0, ETH_ADDR << 1);
-	pio_write_8(ne2k->port + DP_RBCR1, 0);
-	pio_write_8(ne2k->port + DP_RSAR0, 0);
-	pio_write_8(ne2k->port + DP_RSAR1, 0);
-	pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < ETH_ADDR; i++)
-		ne2k->mac[i] = pio_read_16(ne2k->data_port);
-	
-	ne2k->probed = true;
-	return EOK;
-}
-
-/** Start the network interface.
- *
- * @param[in,out] ne2k Network interface structure.
- *
- * @return EOK on success.
- * @return EXDEV if the network interface is disabled.
- *
- */
-int ne2k_up(ne2k_t *ne2k)
-{
-	if (!ne2k->probed)
-		return EXDEV;
-	
-	ne2k_init(ne2k);
-	
-	/*
-	 * Setup send queue. Use the first
-	 * SQ_PAGES of NE2000 memory for the send
-	 * buffer.
-	 */
-	ne2k->sq.dirty = false;
-	ne2k->sq.page = NE2K_START / DP_PAGE;
-	fibril_mutex_initialize(&ne2k->sq_mutex);
-	fibril_condvar_initialize(&ne2k->sq_cv);
-	
-	/*
-	 * Setup receive ring buffer. Use all the rest
-	 * of the NE2000 memory (except the first SQ_PAGES
-	 * reserved for the send buffer) for the receive
-	 * ring buffer.
-	 */
-	ne2k->start_page = ne2k->sq.page + SQ_PAGES;
-	ne2k->stop_page = ne2k->sq.page + NE2K_SIZE / DP_PAGE;
-	
-	/*
-	 * Initialization of the DP8390 following the mandatory procedure
-	 * in reference manual ("DP8390D/NS32490D NIC Network Interface
-	 * Controller", National Semiconductor, July 1995, Page 29).
-	 */
-	
-	/* Step 1: */
-	pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
-	
-	/* Step 2: */
-	pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
-	
-	/* Step 3: */
-	pio_write_8(ne2k->port + DP_RBCR0, 0);
-	pio_write_8(ne2k->port + DP_RBCR1, 0);
-	
-	/* Step 4: */
-	pio_write_8(ne2k->port + DP_RCR, RCR_AB);
-	
-	/* Step 5: */
-	pio_write_8(ne2k->port + DP_TCR, TCR_INTERNAL);
-	
-	/* Step 6: */
-	pio_write_8(ne2k->port + DP_BNRY, ne2k->start_page);
-	pio_write_8(ne2k->port + DP_PSTART, ne2k->start_page);
-	pio_write_8(ne2k->port + DP_PSTOP, ne2k->stop_page);
-	
-	/* Step 7: */
-	pio_write_8(ne2k->port + DP_ISR, 0xff);
-	
-	/* Step 8: */
-	pio_write_8(ne2k->port + DP_IMR,
-	    IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
-	
-	/* Step 9: */
-	pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
-	
-	pio_write_8(ne2k->port + DP_PAR0, ne2k->mac[0]);
-	pio_write_8(ne2k->port + DP_PAR1, ne2k->mac[1]);
-	pio_write_8(ne2k->port + DP_PAR2, ne2k->mac[2]);
-	pio_write_8(ne2k->port + DP_PAR3, ne2k->mac[3]);
-	pio_write_8(ne2k->port + DP_PAR4, ne2k->mac[4]);
-	pio_write_8(ne2k->port + DP_PAR5, ne2k->mac[5]);
-	
-	pio_write_8(ne2k->port + DP_MAR0, 0xff);
-	pio_write_8(ne2k->port + DP_MAR1, 0xff);
-	pio_write_8(ne2k->port + DP_MAR2, 0xff);
-	pio_write_8(ne2k->port + DP_MAR3, 0xff);
-	pio_write_8(ne2k->port + DP_MAR4, 0xff);
-	pio_write_8(ne2k->port + DP_MAR5, 0xff);
-	pio_write_8(ne2k->port + DP_MAR6, 0xff);
-	pio_write_8(ne2k->port + DP_MAR7, 0xff);
-	
-	pio_write_8(ne2k->port + DP_CURR, ne2k->start_page + 1);
-	
-	/* Step 10: */
-	pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA);
-	
-	/* Step 11: */
-	pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
-	
-	/* Reset counters by reading */
-	pio_read_8(ne2k->port + DP_CNTR0);
-	pio_read_8(ne2k->port + DP_CNTR1);
-	pio_read_8(ne2k->port + DP_CNTR2);
-	
-	/* Finish the initialization */
-	ne2k->up = true;
-	return EOK;
-}
-
-/** Stop the network interface.
- *
- * @param[in,out] ne2k Network interface structure.
- *
- */
-void ne2k_down(ne2k_t *ne2k)
-{
-	if ((ne2k->probed) && (ne2k->up)) {
-		pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
-		ne2k_init(ne2k);
-		ne2k->up = false;
-	}
-}
-
-/** Send a frame.
- *
- * @param[in,out] ne2k   Network interface structure.
- * @param[in]     packet Frame to be sent.
- *
- */
-void ne2k_send(ne2k_t *ne2k, packet_t *packet)
-{
-	assert(ne2k->probed);
-	assert(ne2k->up);
-	
-	fibril_mutex_lock(&ne2k->sq_mutex);
-	
-	while (ne2k->sq.dirty)
-		fibril_condvar_wait(&ne2k->sq_cv, &ne2k->sq_mutex);
-	
-	void *buf = packet_get_data(packet);
-	size_t size = packet_get_data_length(packet);
-	
-	if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) {
-		fibril_mutex_unlock(&ne2k->sq_mutex);
-		fprintf(stderr, "%s: Frame dropped (invalid size %zu bytes)\n",
-		    NAME, size);
-		return;
-	}
-	
-	/* Upload the frame to the ethernet card */
-	ne2k_upload(ne2k, buf, ne2k->sq.page * DP_PAGE, size);
-	ne2k->sq.dirty = true;
-	ne2k->sq.size = size;
-	
-	/* Initialize the transfer */
-	pio_write_8(ne2k->port + DP_TPSR, ne2k->sq.page);
-	pio_write_8(ne2k->port + DP_TBCR0, size & 0xff);
-	pio_write_8(ne2k->port + DP_TBCR1, (size >> 8) & 0xff);
-	pio_write_8(ne2k->port + DP_CR, CR_TXP | CR_STA);
-	
-	fibril_mutex_unlock(&ne2k->sq_mutex);
-}
-
-static void ne2k_reset(ne2k_t *ne2k)
-{
-	unsigned int i;
-	
-	/* Stop the chip */
-	pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
-	pio_write_8(ne2k->port + DP_RBCR0, 0);
-	pio_write_8(ne2k->port + DP_RBCR1, 0);
-	
-	for (i = 0; i < NE2K_RETRY; i++) {
-		if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0)
-			break;
-	}
-	
-	pio_write_8(ne2k->port + DP_TCR, TCR_1EXTERNAL | TCR_OFST);
-	pio_write_8(ne2k->port + DP_CR, CR_STA | CR_DM_ABORT);
-	pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
-	
-	/* Acknowledge the ISR_RDC (remote DMA) interrupt */
-	for (i = 0; i < NE2K_RETRY; i++) {
-		if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0)
-			break;
-	}
-	
-	uint8_t val = pio_read_8(ne2k->port + DP_ISR);
-	pio_write_8(ne2k->port + DP_ISR, val & ~ISR_RDC);
-	
-	/*
-	 * Reset the transmit ring. If we were transmitting a frame,
-	 * we pretend that the packet is processed. Higher layers will
-	 * retransmit if the packet wasn't actually sent.
-	 */
-	fibril_mutex_lock(&ne2k->sq_mutex);
-	ne2k->sq.dirty = false;
-	fibril_mutex_unlock(&ne2k->sq_mutex);
-}
-
-static frame_t *ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length)
-{
-	frame_t *frame = (frame_t *) malloc(sizeof(frame_t));
-	if (frame == NULL)
-		return NULL;
-	
-	link_initialize(&frame->link);
-	
-	frame->packet = netif_packet_get_1(length);
-	if (frame->packet == NULL) {
-		free(frame);
-		return NULL;
-	}
-	
-	void *buf = packet_suffix(frame->packet, length);
-	bzero(buf, length);
-	uint8_t last = page + length / DP_PAGE;
-	
-	if (last >= ne2k->stop_page) {
-		size_t left = (ne2k->stop_page - page) * DP_PAGE
-		    - sizeof(recv_header_t);
-		
-		ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
-		    left);
-		ne2k_download(ne2k, buf + left, ne2k->start_page * DP_PAGE,
-		    length - left);
-	} else
-		ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
-		    length);
-	
-	ne2k->stats.receive_packets++;
-	return frame;
-}
-
-static list_t *ne2k_receive(ne2k_t *ne2k)
-{
-	/*
-	 * Allocate memory for the list of received frames.
-	 * If the allocation fails here we still receive the
-	 * frames from the network, but they will be lost.
-	 */
-	list_t *frames = (list_t *) malloc(sizeof(list_t));
-	if (frames != NULL)
-		list_initialize(frames);
-	
-	while (true) {
-		uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1;
-		
-		if (boundary == ne2k->stop_page)
-			boundary = ne2k->start_page;
-		
-		pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_STA);
-		uint8_t current = pio_read_8(ne2k->port + DP_CURR);
-		pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA);
-		
-		if (current == boundary)
-			/* No more frames to process */
-			break;
-		
-		recv_header_t header;
-		size_t size = sizeof(header);
-		size_t offset = boundary * DP_PAGE;
-		
-		/* Get the frame header */
-		pio_write_8(ne2k->port + DP_RBCR0, size & 0xff);
-		pio_write_8(ne2k->port + DP_RBCR1, (size >> 8) & 0xff);
-		pio_write_8(ne2k->port + DP_RSAR0, offset & 0xff);
-		pio_write_8(ne2k->port + DP_RSAR1, (offset >> 8) & 0xff);
-		pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-		
-		pio_read_buf_16(ne2k->data_port, (void *) &header, size);
-		
-		size_t length =
-		    (((size_t) header.rbcl) | (((size_t) header.rbch) << 8)) - size;
-		uint8_t next = header.next;
-		
-		if ((length < ETH_MIN_PACK_SIZE)
-		    || (length > ETH_MAX_PACK_SIZE_TAGGED)) {
-			fprintf(stderr, "%s: Rant frame (%zu bytes)\n", NAME, length);
-			next = current;
-		} else if ((header.next < ne2k->start_page)
-		    || (header.next > ne2k->stop_page)) {
-			fprintf(stderr, "%s: Malformed next frame %u\n", NAME,
-			    header.next);
-			next = current;
-		} else if (header.status & RSR_FO) {
-			/*
-			 * This is very serious, so we issue a warning and
-			 * reset the buffers.
-			 */
-			fprintf(stderr, "%s: FIFO overrun\n", NAME);
-			ne2k->overruns++;
-			next = current;
-		} else if ((header.status & RSR_PRX) && (ne2k->up)) {
-			if (frames != NULL) {
-				frame_t *frame = ne2k_receive_frame(ne2k, boundary, length);
-				if (frame != NULL)
-					list_append(&frame->link, frames);
-			}
-		}
-		
-		/*
-		 * Update the boundary pointer
-		 * to the value of the page
-		 * prior to the next packet to
-		 * be processed.
-		 */
-		if (next == ne2k->start_page)
-			next = ne2k->stop_page - 1;
-		else
-			next--;
-		
-		pio_write_8(ne2k->port + DP_BNRY, next);
-	}
-	
-	return frames;
-}
-
-list_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
-{
-	/* List of received frames */
-	list_t *frames = NULL;
-	
-	if (isr & (ISR_PTX | ISR_TXE)) {
-		if (isr & ISR_TXE)
-			ne2k->stats.send_errors++;
-		else {
-			if (tsr & TSR_PTX)
-				ne2k->stats.send_packets++;
-			
-			if (tsr & TSR_COL)
-				ne2k->stats.collisions++;
-			
-			if (tsr & TSR_ABT)
-				ne2k->stats.send_aborted_errors++;
-			
-			if (tsr & TSR_CRS)
-				ne2k->stats.send_carrier_errors++;
-			
-			if (tsr & TSR_FU) {
-				ne2k->underruns++;
-				if (ne2k->underruns < NE2K_ERL)
-					fprintf(stderr, "%s: FIFO underrun\n", NAME);
-			}
-			
-			if (tsr & TSR_CDH) {
-				ne2k->stats.send_heartbeat_errors++;
-				if (ne2k->stats.send_heartbeat_errors < NE2K_ERL)
-					fprintf(stderr, "%s: CD heartbeat failure\n", NAME);
-			}
-			
-			if (tsr & TSR_OWC)
-				ne2k->stats.send_window_errors++;
-		}
-		
-		fibril_mutex_lock(&ne2k->sq_mutex);
-		
-		if (ne2k->sq.dirty) {
-			/* Prepare the buffer for next packet */
-			ne2k->sq.dirty = false;
-			ne2k->sq.size = 0;
-			
-			/* Signal a next frame to be sent */
-			fibril_condvar_broadcast(&ne2k->sq_cv);
-		} else {
-			ne2k->misses++;
-			if (ne2k->misses < NE2K_ERL)
-				fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);
-		}
-		
-		fibril_mutex_unlock(&ne2k->sq_mutex);
-	}
-	
-	if (isr & ISR_RXE)
-		ne2k->stats.receive_errors++;
-	
-	if (isr & ISR_CNT) {
-		ne2k->stats.receive_crc_errors +=
-		    pio_read_8(ne2k->port + DP_CNTR0);
-		ne2k->stats.receive_frame_errors +=
-		    pio_read_8(ne2k->port + DP_CNTR1);
-		ne2k->stats.receive_missed_errors +=
-		    pio_read_8(ne2k->port + DP_CNTR2);
-	}
-	
-	if (isr & ISR_PRX)
-		frames = ne2k_receive(ne2k);
-	
-	if (isr & ISR_RST) {
-		/*
-		 * The chip is stopped, and all arrived
-		 * frames are delivered.
-		 */
-		ne2k_reset(ne2k);
-	}
-	
-	/* Unmask interrupts to be processed in the next round */
-	pio_write_8(ne2k->port + DP_IMR,
-	    IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
-	
-	return frames;
-}
-
-/** @}
- */
Index: pace/srv/hw/netif/ne2000/dp8390.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,248 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This code is based upon the NE2000 driver for MINIX,
- * distributed according to a BSD-style license.
- *
- * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
- * Copyright (c) 1992, 1994 Philip Homburg
- * Copyright (c) 1996 G. Falzoni
- *
- */
-
-/** @addtogroup ne2000
- *  @{
- */
-
-/** @file
- *  DP8390 network interface definitions.
- */
-
-#ifndef __NET_NETIF_DP8390_H__
-#define __NET_NETIF_DP8390_H__
-
-#include <fibril_synch.h>
-#include <adt/list.h>
-#include <net/packet.h>
-#include <netif_skel.h>
-
-/** Module name */
-#define NAME  "ne2000"
-
-/** Input/output size */
-#define NE2K_IO_SIZE  0x0020
-
-/** Ethernet address length */
-#define ETH_ADDR  6
-
-/* National Semiconductor DP8390 Network Interface Controller. */
-
-/** Page 0, for reading */
-#define DP_CR     0x00  /**< Command Register */
-#define DP_CLDA0  0x01  /**< Current Local DMA Address 0 */
-#define DP_CLDA1  0x02  /**< Current Local DMA Address 1 */
-#define DP_BNRY   0x03  /**< Boundary Pointer */
-#define DP_TSR    0x04  /**< Transmit Status Register */
-#define DP_NCR    0x05  /**< Number of Collisions Register */
-#define DP_FIFO   0x06  /**< FIFO */
-#define DP_ISR    0x07  /**< Interrupt Status Register */
-#define DP_CRDA0  0x08  /**< Current Remote DMA Address 0 */
-#define DP_CRDA1  0x09  /**< Current Remote DMA Address 1 */
-#define DP_RSR    0x0c  /**< Receive Status Register */
-#define DP_CNTR0  0x0d  /**< Tally Counter 0 */
-#define DP_CNTR1  0x0e  /**< Tally Counter 1 */
-#define DP_CNTR2  0x0f  /**< Tally Counter 2 */
-
-/** Page 0, for writing */
-#define DP_PSTART  0x01  /**< Page Start Register*/
-#define DP_PSTOP   0x02  /**< Page Stop Register */
-#define DP_TPSR    0x04  /**< Transmit Page Start Register */
-#define DP_TBCR0   0x05  /**< Transmit Byte Count Register 0 */
-#define DP_TBCR1   0x06  /**< Transmit Byte Count Register 1 */
-#define DP_RSAR0   0x08  /**< Remote Start Address Register 0 */
-#define DP_RSAR1   0x09  /**< Remote Start Address Register 1 */
-#define DP_RBCR0   0x0a  /**< Remote Byte Count Register 0 */
-#define DP_RBCR1   0x0b  /**< Remote Byte Count Register 1 */
-#define DP_RCR     0x0c  /**< Receive Configuration Register */
-#define DP_TCR     0x0d  /**< Transmit Configuration Register */
-#define DP_DCR     0x0e  /**< Data Configuration Register */
-#define DP_IMR     0x0f  /**< Interrupt Mask Register */
-
-/** Page 1, read/write */
-#define DP_PAR0  0x01  /**< Physical Address Register 0 */
-#define DP_PAR1  0x02  /**< Physical Address Register 1 */
-#define DP_PAR2  0x03  /**< Physical Address Register 2 */
-#define DP_PAR3  0x04  /**< Physical Address Register 3 */
-#define DP_PAR4  0x05  /**< Physical Address Register 4 */
-#define DP_PAR5  0x06  /**< Physical Address Register 5 */
-#define DP_CURR  0x07  /**< Current Page Register */
-#define DP_MAR0  0x08  /**< Multicast Address Register 0 */
-#define DP_MAR1  0x09  /**< Multicast Address Register 1 */
-#define DP_MAR2  0x0a  /**< Multicast Address Register 2 */
-#define DP_MAR3  0x0b  /**< Multicast Address Register 3 */
-#define DP_MAR4  0x0c  /**< Multicast Address Register 4 */
-#define DP_MAR5  0x0d  /**< Multicast Address Register 5 */
-#define DP_MAR6  0x0e  /**< Multicast Address Register 6 */
-#define DP_MAR7  0x0f  /**< Multicast Address Register 7 */
-
-/* Bits in Command Register */
-#define CR_STP       0x01  /**< Stop (software reset) */
-#define CR_STA       0x02  /**< Start (activate NIC) */
-#define CR_TXP       0x04  /**< Transmit Packet */
-#define CR_DMA       0x38  /**< Mask for DMA control */
-#define CR_DM_NOP    0x00  /**< DMA: No Operation */
-#define CR_DM_RR     0x08  /**< DMA: Remote Read */
-#define CR_DM_RW     0x10  /**< DMA: Remote Write */
-#define CR_DM_SP     0x18  /**< DMA: Send Packet */
-#define CR_DM_ABORT  0x20  /**< DMA: Abort Remote DMA Operation */
-#define CR_PS        0xc0  /**< Mask for Page Select */
-#define CR_PS_P0     0x00  /**< Register Page 0 */
-#define CR_PS_P1     0x40  /**< Register Page 1 */
-#define CR_PS_P2     0x80  /**< Register Page 2 */
-#define CR_PS_T1     0xc0  /**< Test Mode Register Map */
-
-/* Bits in Interrupt State Register */
-#define ISR_PRX  0x01  /**< Packet Received with no errors */
-#define ISR_PTX  0x02  /**< Packet Transmitted with no errors */
-#define ISR_RXE  0x04  /**< Receive Error */
-#define ISR_TXE  0x08  /**< Transmit Error */
-#define ISR_OVW  0x10  /**< Overwrite Warning */
-#define ISR_CNT  0x20  /**< Counter Overflow */
-#define ISR_RDC  0x40  /**< Remote DMA Complete */
-#define ISR_RST  0x80  /**< Reset Status */
-
-/* Bits in Interrupt Mask Register */
-#define IMR_PRXE  0x01  /**< Packet Received Interrupt Enable */
-#define IMR_PTXE  0x02  /**< Packet Transmitted Interrupt Enable */
-#define IMR_RXEE  0x04  /**< Receive Error Interrupt Enable */
-#define IMR_TXEE  0x08  /**< Transmit Error Interrupt Enable */
-#define IMR_OVWE  0x10  /**< Overwrite Warning Interrupt Enable */
-#define IMR_CNTE  0x20  /**< Counter Overflow Interrupt Enable */
-#define IMR_RDCE  0x40  /**< DMA Complete Interrupt Enable */
-
-/* Bits in Data Configuration Register */
-#define DCR_WTS        0x01  /**< Word Transfer Select */
-#define DCR_BYTEWIDE   0x00  /**< WTS: byte wide transfers */
-#define DCR_WORDWIDE   0x01  /**< WTS: word wide transfers */
-#define DCR_BOS        0x02  /**< Byte Order Select */
-#define DCR_LTLENDIAN  0x00  /**< BOS: Little Endian */
-#define DCR_BIGENDIAN  0x02  /**< BOS: Big Endian */
-#define DCR_LAS        0x04  /**< Long Address Select */
-#define DCR_BMS        0x08  /**< Burst Mode Select */
-#define DCR_AR         0x10  /**< Autoinitialize Remote */
-#define DCR_FTS        0x60  /**< Fifo Threshold Select */
-#define DCR_2BYTES     0x00  /**< 2 bytes */
-#define DCR_4BYTES     0x40  /**< 4 bytes */
-#define DCR_8BYTES     0x20  /**< 8 bytes */
-#define DCR_12BYTES    0x60  /**< 12 bytes */
-
-/* Bits in Transmit Configuration Register */
-#define TCR_CRC        0x01  /**< Inhibit CRC */
-#define TCR_ELC        0x06  /**< Encoded Loopback Control */
-#define TCR_NORMAL     0x00  /**< ELC: Normal Operation */
-#define TCR_INTERNAL   0x02  /**< ELC: Internal Loopback */
-#define TCR_0EXTERNAL  0x04  /**< ELC: External Loopback LPBK=0 */
-#define TCR_1EXTERNAL  0x06  /**< ELC: External Loopback LPBK=1 */
-#define TCR_ATD        0x08  /**< Auto Transmit Disable */
-#define TCR_OFST       0x10  /**< Collision Offset Enable (be nice) */
-
-/* Bits in Interrupt Status Register */
-#define TSR_PTX  0x01  /**< Packet Transmitted (without error) */
-#define TSR_DFR  0x02  /**< Transmit Deferred (reserved) */
-#define TSR_COL  0x04  /**< Transmit Collided */
-#define TSR_ABT  0x08  /**< Transmit Aborted */
-#define TSR_CRS  0x10  /**< Carrier Sense Lost */
-#define TSR_FU   0x20  /**< FIFO Underrun */
-#define TSR_CDH  0x40  /**< CD Heartbeat */
-#define TSR_OWC  0x80  /**< Out of Window Collision */
-
-/* Bits in Receive Configuration Register */
-#define RCR_SEP  0x01  /**< Save Errored Packets */
-#define RCR_AR   0x02  /**< Accept Runt Packets */
-#define RCR_AB   0x04  /**< Accept Broadcast */
-#define RCR_AM   0x08  /**< Accept Multicast */
-#define RCR_PRO  0x10  /**< Physical Promiscuous */
-#define RCR_MON  0x20  /**< Monitor Mode */
-
-/* Bits in Receive Status Register */
-#define RSR_PRX  0x01  /**< Packet Received Intact */
-#define RSR_CRC  0x02  /**< CRC Error */
-#define RSR_FAE  0x04  /**< Frame Alignment Error */
-#define RSR_FO   0x08  /**< FIFO Overrun */
-#define RSR_MPA  0x10  /**< Missed Packet */
-#define RSR_PHY  0x20  /**< Multicast Address Match */
-#define RSR_DIS  0x40  /**< Receiver Disabled */
-#define RSR_DFR  0x80  /**< In later manuals: Deferring */
-
-typedef struct {
-	/* Device configuration */
-	void *port;
-	void *data_port;
-	int irq;
-	uint8_t mac[ETH_ADDR];
-	
-	uint8_t start_page;  /**< Ring buffer start page */
-	uint8_t stop_page;   /**< Ring buffer stop page */
-	
-	/* Send queue */
-	struct {
-		bool dirty;    /**< Buffer contains a packet */
-		size_t size;   /**< Packet size */
-		uint8_t page;  /**< Starting page of the buffer */
-	} sq;
-	fibril_mutex_t sq_mutex;
-	fibril_condvar_t sq_cv;
-	
-	/* Driver run-time variables */
-	bool probed;
-	bool up;
-	
-	/* Device statistics */
-	device_stats_t stats;
-	uint64_t misses;     /**< Receive frame misses */
-	uint64_t underruns;  /**< FIFO underruns */
-	uint64_t overruns;   /**< FIFO overruns */
-} ne2k_t;
-
-typedef struct {
-	link_t link;
-	packet_t *packet;
-} frame_t;
-
-extern int ne2k_probe(ne2k_t *, void *, int);
-extern int ne2k_up(ne2k_t *);
-extern void ne2k_down(ne2k_t *);
-extern void ne2k_send(ne2k_t *, packet_t *);
-extern list_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hw/netif/ne2000/ne2000.c
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,410 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ne2000
- *  @{
- */
-
-/** @file
- *  NE2000 network interface implementation.
- */
-
-#include <assert.h>
-#include <async.h>
-#include <ddi.h>
-#include <errno.h>
-#include <err.h>
-#include <malloc.h>
-#include <sysinfo.h>
-#include <ns.h>
-#include <ipc/services.h>
-#include <ipc/irc.h>
-#include <net/modules.h>
-#include <packet_client.h>
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <netif_skel.h>
-#include <nil_remote.h>
-#include "dp8390.h"
-
-/** Return the device from the interrupt call.
- *
- *  @param[in] call The interrupt call.
- *
- */
-#define IRQ_GET_DEVICE(call)  ((device_id_t) IPC_GET_IMETHOD(call))
-
-/** Return the ISR from the interrupt call.
- *
- * @param[in] call The interrupt call.
- *
- */
-#define IRQ_GET_ISR(call)  ((int) IPC_GET_ARG2(call))
-
-/** Return the TSR from the interrupt call.
- *
- * @param[in] call The interrupt call.
- *
- */
-#define IRQ_GET_TSR(call)  ((int) IPC_GET_ARG3(call))
-
-static bool irc_service = false;
-static async_sess_t *irc_sess = NULL;
-
-/** NE2000 kernel interrupt command sequence.
- *
- */
-static irq_cmd_t ne2k_cmds[] = {
-	{
-		/* Read Interrupt Status Register */
-		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,
-		.dstarg = 2
-	},
-	{
-		/* Mask supported interrupt causes */
-		.cmd = CMD_BTEST,
-		.value = (ISR_PRX | ISR_PTX | ISR_RXE | ISR_TXE | ISR_OVW |
-		    ISR_CNT | ISR_RDC),
-		.srcarg = 2,
-		.dstarg = 3,
-	},
-	{
-		/* Predicate for accepting the interrupt */
-		.cmd = CMD_PREDICATE,
-		.value = 4,
-		.srcarg = 3
-	},
-	{
-		/*
-		 * Mask future interrupts via
-		 * Interrupt Mask Register
-		 */
-		.cmd = CMD_PIO_WRITE_8,
-		.addr = NULL,
-		.value = 0
-	},
-	{
-		/* Acknowledge the current interrupt */
-		.cmd = CMD_PIO_WRITE_A_8,
-		.addr = NULL,
-		.srcarg = 3
-	},
-	{
-		/* Read Transmit Status Register */
-		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,
-		.dstarg = 3
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-/** NE2000 kernel interrupt code.
- *
- */
-static irq_code_t ne2k_code = {
-	sizeof(ne2k_cmds) / sizeof(irq_cmd_t),
-	ne2k_cmds
-};
-
-/** Handle the interrupt notification.
- *
- * This is the interrupt notification function. It is quarantied
- * that there is only a single instance of this notification
- * function running at one time until the return from the
- * ne2k_interrupt() function (where the interrupts are unmasked
- * again).
- *
- * @param[in] iid  Interrupt notification identifier.
- * @param[in] call Interrupt notification.
- *
- */
-static void irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	device_id_t device_id = IRQ_GET_DEVICE(*call);
-	netif_device_t *device;
-	async_sess_t *nil_sess;
-	ne2k_t *ne2k;
-	
-	fibril_rwlock_read_lock(&netif_globals.lock);
-	
-	nil_sess = netif_globals.nil_sess;
-	
-	if (find_device(device_id, &device) == EOK)
-		ne2k = (ne2k_t *) device->specific;
-	else
-		ne2k = NULL;
-	
-	fibril_rwlock_read_unlock(&netif_globals.lock);
-	
-	if (ne2k != NULL) {
-		list_t *frames =
-		    ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call));
-		
-		if (frames != NULL) {
-			while (!list_empty(frames)) {
-				frame_t *frame = list_get_instance(
-				    list_first(frames), frame_t, link);
-				
-				list_remove(&frame->link);
-				nil_received_msg(nil_sess, device_id, frame->packet,
-				    SERVICE_NONE);
-				free(frame);
-			}
-			
-			free(frames);
-		}
-	}
-}
-
-/** Change the network interface state.
- *
- * @param[in,out] device Network interface.
- * @param[in]     state  New state.
- *
- */
-static void change_state(netif_device_t *device, device_state_t state)
-{
-	if (device->state != state) {
-		device->state = state;
-		
-		const char *desc;
-		switch (state) {
-		case NETIF_ACTIVE:
-			desc = "active";
-			break;
-		case NETIF_STOPPED:
-			desc = "stopped";
-			break;
-		default:
-			desc = "unknown";
-		}
-		
-		printf("%s: State changed to %s\n", NAME, desc);
-	}
-}
-
-int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *count)
-{
-	return ENOTSUP;
-}
-
-int netif_get_device_stats(device_id_t device_id, device_stats_t *stats)
-{
-	if (!stats)
-		return EBADMEM;
-	
-	netif_device_t *device;
-	int rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	ne2k_t *ne2k = (ne2k_t *) device->specific;
-	
-	memcpy(stats, &ne2k->stats, sizeof(device_stats_t));
-	return EOK;
-}
-
-int netif_get_addr_message(device_id_t device_id, measured_string_t *address)
-{
-	if (!address)
-		return EBADMEM;
-	
-	netif_device_t *device;
-	int rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	ne2k_t *ne2k = (ne2k_t *) device->specific;
-	
-	address->value = ne2k->mac;
-	address->length = ETH_ADDR;
-	return EOK;
-}
-
-int netif_probe_message(device_id_t device_id, int irq, void *io)
-{
-	netif_device_t *device =
-	    (netif_device_t *) malloc(sizeof(netif_device_t));
-	if (!device)
-		return ENOMEM;
-	
-	ne2k_t *ne2k = (ne2k_t *) malloc(sizeof(ne2k_t));
-	if (!ne2k) {
-		free(device);
-		return ENOMEM;
-	}
-	
-	void *port;
-	int rc = pio_enable((void *) io, NE2K_IO_SIZE, &port);
-	if (rc != EOK) {
-		free(ne2k);
-		free(device);
-		return rc;
-	}
-	
-	bzero(device, sizeof(netif_device_t));
-	bzero(ne2k, sizeof(ne2k_t));
-	
-	device->device_id = device_id;
-	device->specific = (void *) ne2k;
-	device->state = NETIF_STOPPED;
-	
-	rc = ne2k_probe(ne2k, port, irq);
-	if (rc != EOK) {
-		printf("%s: No ethernet card found at I/O address %p\n",
-		    NAME, port);
-		free(ne2k);
-		free(device);
-		return rc;
-	}
-	
-	rc = netif_device_map_add(&netif_globals.device_map, device->device_id, device);
-	if (rc != EOK) {
-		free(ne2k);
-		free(device);
-		return rc;
-	}
-	
-	printf("%s: Ethernet card at I/O address %p, IRQ %d, MAC ",
-	    NAME, port, irq);
-	
-	unsigned int i;
-	for (i = 0; i < ETH_ADDR; i++)
-		printf("%02x%c", ne2k->mac[i], i < 5 ? ':' : '\n');
-	
-	return EOK;
-}
-
-int netif_start_message(netif_device_t *device)
-{
-	if (device->state != NETIF_ACTIVE) {
-		ne2k_t *ne2k = (ne2k_t *) device->specific;
-		
-		ne2k_cmds[0].addr = ne2k->port + DP_ISR;
-		ne2k_cmds[3].addr = ne2k->port + DP_IMR;
-		ne2k_cmds[4].addr = ne2k_cmds[0].addr;
-		ne2k_cmds[5].addr = ne2k->port + DP_TSR;
-		
-		int rc = register_irq(ne2k->irq, device->device_id,
-		    device->device_id, &ne2k_code);
-		if (rc != EOK)
-			return rc;
-		
-		rc = ne2k_up(ne2k);
-		if (rc != EOK) {
-			unregister_irq(ne2k->irq, device->device_id);
-			return rc;
-		}
-		
-		change_state(device, NETIF_ACTIVE);
-		
-		if (irc_service) {
-			async_exch_t *exch = async_exchange_begin(irc_sess);
-			async_msg_1(exch, IRC_ENABLE_INTERRUPT, ne2k->irq);
-			async_exchange_end(exch);
-		}
-	}
-	
-	return device->state;
-}
-
-int netif_stop_message(netif_device_t *device)
-{
-	if (device->state != NETIF_STOPPED) {
-		ne2k_t *ne2k = (ne2k_t *) device->specific;
-		
-		ne2k_down(ne2k);
-		unregister_irq(ne2k->irq, device->device_id);
-		change_state(device, NETIF_STOPPED);
-	}
-	
-	return device->state;
-}
-
-int netif_send_message(device_id_t device_id, packet_t *packet,
-    services_t sender)
-{
-	netif_device_t *device;
-	int rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	if (device->state != NETIF_ACTIVE) {
-		netif_pq_release(packet_get_id(packet));
-		return EFORWARD;
-	}
-	
-	ne2k_t *ne2k = (ne2k_t *) device->specific;
-	
-	/*
-	 * Process the packet queue
-	 */
-	
-	do {
-		packet_t *next = pq_detach(packet);
-		ne2k_send(ne2k, packet);
-		netif_pq_release(packet_get_id(packet));
-		packet = next;
-	} while (packet);
-	
-	return EOK;
-}
-
-int netif_initialize(void)
-{
-	sysarg_t apic;
-	sysarg_t i8259;
-	
-	if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
-	    || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)))
-		irc_service = true;
-	
-	if (irc_service) {
-		while (!irc_sess)
-			irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
-			    SERVICE_IRC, 0, 0);
-	}
-	
-	async_set_interrupt_received(irq_handler);
-	
-	return service_register(SERVICE_NE2000);
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return netif_module_start();
-}
-
-/** @}
- */
Index: uspace/srv/loc/loc.c
===================================================================
--- uspace/srv/loc/loc.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/loc/loc.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -1288,6 +1288,8 @@
 	cat = category_new("virtual");
 	categ_dir_add_cat(&cdir, cat);
-
-
+	
+	cat = category_new("nic");
+	categ_dir_add_cat(&cdir, cat);
+	
 	return true;
 }
Index: pace/srv/net/cfg/lo
===================================================================
--- uspace/srv/net/cfg/lo	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(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/lo.nic
===================================================================
--- uspace/srv/net/cfg/lo.nic	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
+++ uspace/srv/net/cfg/lo.nic	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -0,0 +1,13 @@
+# loopback configuration
+
+NAME=lo
+
+HWPATH=/virt/lo/port0
+NIL=nildummy
+IL=ip
+
+IP_CONFIG=static
+IP_ADDR=127.0.0.1
+IP_NETMASK=255.0.0.0
+
+MTU=15535
Index: pace/srv/net/cfg/ne2k
===================================================================
--- uspace/srv/net/cfg/ne2k	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,24 +1,0 @@
-# DP8390 (NE2k) configuration
-
-NAME=ne2k
-
-NETIF=ne2000
-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.0
-IP_BROADCAST=10.0.2.255
-IP_GATEWAY=10.0.2.2
-ARP=arp
-
-MTU=1500
Index: uspace/srv/net/cfg/ne2k.nic
===================================================================
--- uspace/srv/net/cfg/ne2k.nic	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
+++ uspace/srv/net/cfg/ne2k.nic	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -0,0 +1,21 @@
+# NE2000 configuration
+
+NAME=ne2k
+
+HWPATH=/hw/pci0/00:01.0/ne2000/port0
+NIL=eth
+IL=ip
+
+# 8023_2_LSAP, 8023_2_SNAP
+ETH_MODE=DIX
+ETH_DUMMY=no
+
+IP_CONFIG=static
+IP_ADDR=10.0.2.15
+IP_ROUTING=yes
+IP_NETMASK=255.255.255.240
+IP_BROADCAST=10.0.2.255
+IP_GATEWAY=10.0.2.2
+ARP=arp
+
+MTU=1492
Index: pace/srv/net/documentation.txt
===================================================================
--- uspace/srv/net/documentation.txt	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,201 +1,0 @@
-/**
-
-\mainpage Networking and TCP/IP Stack for HelenOS system
-
-\section introduction Introduction
-
-<p>
-For the microkernel HelenOS a completely new networking stack was designed.
-The networking stack was intended to implement current basic standards of the TCP/IP Stack.
-Only the minimalistic functionality allowing the stack to function was to be implemented.
-The networking stack is written in C.
-</p>
-<p>
-Please see
-</p>
-<ul>
-	<li>\ref build</li>
-	<li>\ref software</li>
-	<li>\ref running</li>
-	<li>\ref testing</li>
-</ul>
-
-\page build Build from sources
-
-<p>
-To compile the HelenOS from sources (the cross compilers from the <code>build/</code> directory are recommended):
-</p>
-<ol>
-	<li>change the working directory to the HelenOS source directory</li>
-	<li>run <code># make config</code></li>
-	<li>check/change the configuration</li>
-	<li>save and exit the configuration tool</li>
-	<li>run <code># make</code></li>
-</ol>
-<p>
-The <code>image.iso</code> should be created on success.
-</p>
-
-\page running Running the HelenOS with networking
-
-\section netstart Starting the networking
-
-<p>
-After starting the HelenOS boot image in <em>Qemu</em>, the command line appears.
-To run <em>Qemu</em> a script <code>contrib/conf/qemu.sh</code> for Linux or <code>contrib/conf/qemu.bat</code> for Windows in the HelenOS source directory can be used.
-The provided scripts set the needed arguments:
-<br><code>-vga std -M isapc -net nic,model=ne2k_isa -net user -redir udp:8080::8080 -redir udp:8081::8081 -boot d -cdrom image.iso</code><br>
-Additional arguments may be specified on the command line, they override these set.
-</p>
-
-<p>
-The networking stack is started and initialized by running a command
-<br><code># netstart</code><br>
-The networking stack is then started and configured network interfaces are enabled.
-The current configuration is printed out.
-Since that networking applications can be run using the command line as well.
-</p>
-
-\section network Qemu network
-
-<p>
-In the common mode <em>Qemu</em> creates a simple network with a gateway and settles the guest system in.
-The network is 10.0.2.*, the gateway's address 10.0.2.2 and the guest system has 10.0.2.15.
-%Even this simple setting was a bit hard to find in the documentation.
-Therefore a static configuration is possible and no additional DHCP nor BOOTP implementations are necessary.
-On the other hand the guest system is behind a firewall.
-<em>Qemu</em> may be configured to forward some ports to the guest system and allows all outgoing traffic except ICMP and ARP protocols, so you can ping only the gateway.
-</p>
-
-\section applications Applications
-
-<p>
-A few networking applications are located in the app/ directory.
-Common functions for parsing command line arguments and printing textual networking error messages are located in that directory as well.
-The networking applications should be built with the libsocket library located in the socket/libsocket.a file.
-They can use functions and definitions from the include/socket.h header file which contains socket API and further includes:
-</p>
-<ul>
-	<li>include/byteorder.h containing byte order manipulation,</li>
-	<li>include/in.h containing IPv4 socket address structure,</li>
-	<li>include/in6.h containing IPv6 socket address structure,</li>
-	<li>include/inet.h containing socket address structure and parsing functions,</li>
-	<li>include/socket codes.h containing address and protocol families and socket types and option levels, and</li>
-	<li>include/socket errno.h containing socket and general error codes.</li>
-</ul>
-
-\page software Software prerequisites
-
-<p>
-The networking and TCP/IP stack is implemented for the ia32 architecture on top of HelenOS 0.4.1 (Escalopino), the most current stable release of HelenOS.
-So far the only one operational network interface supported is in Qemu 0.10.2 and newer.
-To run <em>Qemu</em> a script contrib/conf/qemu.sh for Linux or contrib/conf/qemu.bat for Windows in the HelenOS source directory can be used.
-The qemu and its libraries have to be installed and in the path.
-These scripts set all the necessary parameters
-with some ports redirected from the local host to the guest system.
-For testing purposes at least a low level communication application is recommended, N.E.T., netcat etc.
-</p>
-<p>
-In order to build HelenOS and the networking stack from sources a few tools are
-required:
-<ul>
-	<li>binutils in version 2.19.1,</li>
-	<li>gcc–core in version 4.3.3 11,</li>
-	<li>gcc–objc in version 4.3.3, and</li>
-	<li>gcc–g++ in version 4.3.3.</li>
-</ul>
-<p>
-All these can be downloaded and installed as cross–compilers on Linux using a script contrib/toolchain.sh in the HelenOS source directory.
-In addition rats, a static source code analyzer, and Doxygen, a documentation generator, were used.
-All development was tracked in the HelenOS subversion repository.
-</p>
-<ul>
-	<li>HelenOS website: <a href="http://www.helenos.org/" title="HelenOS website">http://www.helenos.org/</a></li>
-	<li><em>Qemu</em> website: <a href="http://www.qemu.org/" title="Qemu website">http://www.qemu.org/</a></li>
-	<li><em>binutils</em> website: <a href="http://www.gnu.org/software/binutils/" title="binutils website">http://www.gnu.org/software/binutils/</a></li>
-	<li><em>GCC</em> website: <a href="http://gcc.gnu.org/" title="GCC website">http://gcc.gnu.org/</a></li>
-	<li><em>RATS</em> website: <a href="http://www.fortify.com/security-resources/rats.jsp" title="RATS website">http://www.fortify.com/security-resources/rats.jsp</a></li>
-	<li><em>Doxygen</em> website: <a href="http://www.stack.nl/ dimitri/doxygen/index.html" title="Doxygen website">http://www.stack.nl/ dimitri/doxygen/index.html</a></li>
-	<li><em>Subversion</em> website: <a href="http://subversion.tigris.org/" title="Subversion website">http://subversion.tigris.org/</a></li>
-</ul>
-
-\page testing Testing scenarios
-
-<p>
-The scenarios contain the following shortcuts:
-</p>
-<ul>
-	<li>g for the quest system, HelenOS in <em>Qemu</em></li>
-	<li>h for the host system</li>
-	<li>n for the <em>NET</em> application</li>
-	<li>e for echo echo application run in HelenOS</li>
-</ul>
-
-\section scenarios Testing scenarios
-<ul>
-	<li>UDP
-		<ol>
-			<li>g #netstart</li>
-			<li>h wine net.exe (->n) (or net.exe)</li>
-			<li>n set 127.0.0.1:8080 address and port, BuiltinUDP protocol</li>
-			<li>n send some data (an ARP will be generated and the original packet gets lost)</li>
-			<li>n send some data (the port is unreachable and the packet is discarded)</li>
-			<li>g #echo -p 8080 -c 3 -v (->e)</li>
-			<li>g prints Listening</li>
-			<li>n send some data</li>
-			<li>e prints received data</li>
-			<li>h prints reply</li>
-			<li>n click disconnect</li>
-			<li>n set :8081 port</li>
-			<li>n send some data</li>
-			<li>n click disconnect</li>
-			<li>n set :8080 port</li>
-			<li>count-1 times:
-				<ol>
-					<li>n send some data</li>
-					<li>e prints received data</li>
-					<li>h prints reply</li>
-				</ol>
-			</li>
-			<li>e prints Exiting</li>
-			<li>e quits</li>
-			<li>n send some data (the port is unreachable and the packet is discarded)</li>
-		</ol>
-	</li>
-	<li>ICMP echo to 10.0.2.2
-		<ol>
-			<li>g #netstart</li>
-			<li>g #ping 10.0.2.2 (->p)</li>
-			<li>g prints ARP request for 10.0.2.2</li>
-			<li>g prints ARP reply from 10.0.2.2</li>
-			<li>p prints timeouted</li>
-			<li>p prints round trip time</li>
-			<li>p prints round trip time</li>
-			<li>p quits</li>
-		</ol>
-	</li>
-	<li>ICMP echo to 127.0.0.1
-		<ol>
-			<li>g #netstart</li>
-			<li>g #ping 127.0.0.1 (->p)</li>
-			<li>p prints round trip time</li>
-			<li>p prints round trip time</li>
-			<li>p prints round trip time</li>
-			<li>p quits</li>
-		</ol>
-	</li>
-	<li>ICMP with no internet on the host system (!)
-		<ol>
-			<li>g #netstart</li>
-			<li>g #ping 123.123.123.3 (->p)</li>
-			<li>g prints ARP request for 10.0.2.2</li>
-			<li>g prints ARP reply from 10.0.2.2</li>
-			<li>p prints timeouted</li>
-			<li>p prints destination unreachable</li>
-			<li>p prints destination unreachable</li>
-			<li>p quits</li>
-		</ol>
-	</li>
-</ul>
-
-*/
Index: uspace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/il/arp/arp.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -174,12 +174,6 @@
 		    count);
 		
-		if (device) {
+		if (device)
 			arp_clear_device(device);
-			if (device->addr_data)
-				free(device->addr_data);
-			
-			if (device->broadcast_data)
-				free(device->broadcast_data);
-		}
 	}
 	
@@ -190,6 +184,6 @@
 }
 
-static int arp_clear_address_req(device_id_t device_id, services_t protocol,
-    measured_string_t *address)
+static int arp_clear_address_req(nic_device_id_t device_id,
+    services_t protocol, measured_string_t *address)
 {
 	fibril_mutex_lock(&arp_globals.lock);
@@ -218,5 +212,5 @@
 }
 
-static int arp_clear_device_req(device_id_t device_id)
+static int arp_clear_device_req(nic_device_id_t device_id)
 {
 	fibril_mutex_lock(&arp_globals.lock);
@@ -289,5 +283,5 @@
  *
  */
-static int arp_receive_message(device_id_t device_id, packet_t *packet)
+static int arp_receive_message(nic_device_id_t device_id, packet_t *packet)
 {
 	int rc;
@@ -365,5 +359,5 @@
 			memcpy(src_proto, proto->addr->value,
 			    header->protocol_length);
-			memcpy(src_hw, device->addr->value,
+			memcpy(src_hw, device->addr,
 			    device->packet_dimension.addr_len);
 			memcpy(des_hw, trans->hw_addr->value,
@@ -393,5 +387,5 @@
  *
  */
-static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
+static int arp_mtu_changed_message(nic_device_id_t device_id, size_t mtu)
 {
 	fibril_mutex_lock(&arp_globals.lock);
@@ -409,4 +403,36 @@
 	printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
 	
+	return EOK;
+}
+
+static int arp_addr_changed_message(nic_device_id_t device_id)
+{
+	uint8_t addr_buffer[NIC_MAX_ADDRESS_LENGTH];
+	size_t length;
+	ipc_callid_t data_callid;
+	if (!async_data_write_receive(&data_callid, &length)) {
+		async_answer_0(data_callid, EINVAL);
+		return EINVAL;
+	}
+	if (length > NIC_MAX_ADDRESS_LENGTH) {
+		async_answer_0(data_callid, ELIMIT);
+		return ELIMIT;
+	}
+	if (async_data_write_finalize(data_callid, addr_buffer, length) != EOK) {
+		return EINVAL;
+	}
+
+	fibril_mutex_lock(&arp_globals.lock);
+
+	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
+	if (!device) {
+		fibril_mutex_unlock(&arp_globals.lock);
+		return ENOENT;
+	}
+
+	memcpy(device->addr, addr_buffer, length);
+	device->addr_len = length;
+
+	fibril_mutex_unlock(&arp_globals.lock);
 	return EOK;
 }
@@ -456,4 +482,7 @@
 			async_answer_0(iid, (sysarg_t) rc);
 			break;
+		case NET_IL_ADDR_CHANGED:
+			rc = arp_addr_changed_message(IPC_GET_DEVICE(*icall));
+			async_answer_0(iid, (sysarg_t) rc);
 		
 		default:
@@ -483,5 +512,5 @@
  *
  */
-static int arp_device_message(device_id_t device_id, services_t service,
+static int arp_device_message(nic_device_id_t device_id, services_t service,
     services_t protocol, measured_string_t *address)
 {
@@ -586,24 +615,26 @@
 		
 		/* Get hardware address */
-		rc = nil_get_addr_req(device->sess, device_id, &device->addr,
-		    &device->addr_data);
-		if (rc != EOK) {
+		int len = nil_get_addr_req(device->sess, device_id, device->addr,
+		    NIC_MAX_ADDRESS_LENGTH);
+		if (len < 0) {
 			fibril_mutex_unlock(&arp_globals.lock);
 			arp_protos_destroy(&device->protos, free);
 			free(device);
-			return rc;
-		}
+			return len;
+		}
+		
+		device->addr_len = len;
 		
 		/* Get broadcast address */
-		rc = nil_get_broadcast_addr_req(device->sess, device_id,
-		    &device->broadcast_addr, &device->broadcast_data);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			free(device->addr);
-			free(device->addr_data);
+		len = nil_get_broadcast_addr_req(device->sess, device_id,
+		    device->broadcast_addr, NIC_MAX_ADDRESS_LENGTH);
+		if (len < 0) {
+			fibril_mutex_unlock(&arp_globals.lock);
 			arp_protos_destroy(&device->protos, free);
 			free(device);
-			return rc;
-		}
+			return len;
+		}
+		
+		device->broadcast_addr_len = len;
 		
 		rc = arp_cache_add(&arp_globals.cache, device->device_id,
@@ -611,8 +642,4 @@
 		if (rc != EOK) {
 			fibril_mutex_unlock(&arp_globals.lock);
-			free(device->addr);
-			free(device->addr_data);
-			free(device->broadcast_addr);
-			free(device->broadcast_data);
 			arp_protos_destroy(&device->protos, free);
 			free(device);
@@ -640,9 +667,9 @@
 }
 
-static int arp_send_request(device_id_t device_id, services_t protocol,
+static int arp_send_request(nic_device_id_t device_id, services_t protocol,
     measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
 {
 	/* ARP packet content size = header + (address + translation) * 2 */
-	size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
+	size_t length = 8 + 2 * (proto->addr->length + device->addr_len);
 	if (length > device->packet_dimension.content)
 		return ELIMIT;
@@ -661,5 +688,5 @@
 	
 	header->hardware = htons(device->hardware);
-	header->hardware_length = (uint8_t) device->addr->length;
+	header->hardware_length = (uint8_t) device->addr_len;
 	header->protocol = htons(protocol_map(device->service, protocol));
 	header->protocol_length = (uint8_t) proto->addr->length;
@@ -667,17 +694,16 @@
 	
 	length = sizeof(arp_header_t);
-	
-	memcpy(((uint8_t *) header) + length, device->addr->value,
-	    device->addr->length);
-	length += device->addr->length;
+	memcpy(((uint8_t *) header) + length, device->addr,
+	    device->addr_len);
+	length += device->addr_len;
 	memcpy(((uint8_t *) header) + length, proto->addr->value,
 	    proto->addr->length);
 	length += proto->addr->length;
-	bzero(((uint8_t *) header) + length, device->addr->length);
-	length += device->addr->length;
+	bzero(((uint8_t *) header) + length, device->addr_len);
+	length += device->addr_len;
 	memcpy(((uint8_t *) header) + length, target->value, target->length);
-	
-	int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
-	    (uint8_t *) device->broadcast_addr->value, device->addr->length);
+
+	int rc = packet_set_addr(packet, device->addr, device->broadcast_addr,
+	    device->addr_len);
 	if (rc != EOK) {
 		pq_release_remote(arp_globals.net_sess, packet_get_id(packet));
@@ -704,5 +730,5 @@
  *
  */
-static int arp_translate_message(device_id_t device_id, services_t protocol,
+static int arp_translate_message(nic_device_id_t device_id, services_t protocol,
     measured_string_t *target, measured_string_t **translation)
 {
Index: uspace/srv/net/il/arp/arp.h
===================================================================
--- uspace/srv/net/il/arp/arp.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/il/arp/arp.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -92,13 +92,13 @@
 struct arp_device {
 	/** Actual device hardware address. */
-	measured_string_t *addr;
-	/** Actual device hardware address data. */
-	uint8_t *addr_data;
+	uint8_t addr[NIC_MAX_ADDRESS_LENGTH];
+	/** Actual device hardware address length. */
+	size_t addr_len;
 	/** Broadcast device hardware address. */
-	measured_string_t *broadcast_addr;
-	/** Broadcast device hardware address data. */
-	uint8_t *broadcast_data;
+	uint8_t broadcast_addr[NIC_MAX_ADDRESS_LENGTH];
+	/** Broadcast device hardware address length. */
+	size_t broadcast_addr_len;
 	/** Device identifier. */
-	device_id_t device_id;
+	nic_device_id_t device_id;
 	/** Hardware type. */
 	hw_type_t hardware;
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/il/ip/ip.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -482,5 +482,5 @@
 }
 
-static int ip_device_req_local(device_id_t device_id, services_t netif)
+static int ip_device_req_local(nic_device_id_t device_id, services_t netif)
 {
 	ip_netif_t *ip_netif;
@@ -501,5 +501,5 @@
 	ip_netif->device_id = device_id;
 	ip_netif->service = netif;
-	ip_netif->state = NETIF_STOPPED;
+	ip_netif->state = NIC_STATE_STOPPED;
 
 	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
@@ -594,5 +594,5 @@
 	while (index >= 0) {
 		netif = ip_netifs_get_index(&ip_globals.netifs, index);
-		if (netif && (netif->state == NETIF_ACTIVE)) {
+		if (netif && (netif->state == NIC_STATE_ACTIVE)) {
 			route = ip_netif_find_route(netif, destination);
 			if (route)
@@ -1142,5 +1142,5 @@
 }
 
-static int ip_send_msg_local(device_id_t device_id, packet_t *packet,
+static int ip_send_msg_local(nic_device_id_t device_id, packet_t *packet,
     services_t sender, services_t error)
 {
@@ -1258,5 +1258,6 @@
  * @return		ENOENT if device is not found.
  */
-static int ip_device_state_message(device_id_t device_id, device_state_t state)
+static int ip_device_state_message(nic_device_id_t device_id,
+    nic_device_state_t state)
 {
 	ip_netif_t *netif;
@@ -1272,5 +1273,6 @@
 	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
 
-	printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
+	printf("%s: Device %d changed state to '%s'\n", NAME, device_id,
+	    nic_device_state_to_string(state));
 
 	return EOK;
@@ -1312,5 +1314,5 @@
  *			tl_received_msg() function.
  */
-static int ip_deliver_local(device_id_t device_id, packet_t *packet,
+static int ip_deliver_local(nic_device_id_t device_id, packet_t *packet,
     ip_header_t *header, services_t error)
 {
@@ -1413,5 +1415,5 @@
  *			is disabled.
  */
-static int ip_process_packet(device_id_t device_id, packet_t *packet)
+static int ip_process_packet(nic_device_id_t device_id, packet_t *packet)
 {
 	ip_header_t *header;
@@ -1514,5 +1516,5 @@
  *
  */
-static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
+static int ip_packet_size_message(nic_device_id_t device_id, size_t *addr_len,
     size_t *prefix, size_t *content, size_t *suffix)
 {
@@ -1572,5 +1574,5 @@
  * @return		ENOENT if device is not found.
  */
-static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
+static int ip_mtu_changed_message(nic_device_id_t device_id, size_t mtu)
 {
 	ip_netif_t *netif;
@@ -1629,5 +1631,8 @@
 			async_answer_0(iid, (sysarg_t) rc);
 			break;
-		
+		case NET_IL_ADDR_CHANGED:
+			async_answer_0(iid, (sysarg_t) EOK);
+			break;
+
 		default:
 			async_answer_0(iid, (sysarg_t) ENOTSUP);
@@ -1689,5 +1694,5 @@
 }
 
-static int ip_add_route_req_local(device_id_t device_id, in_addr_t address,
+static int ip_add_route_req_local(nic_device_id_t device_id, in_addr_t address,
     in_addr_t netmask, in_addr_t gateway)
 {
@@ -1723,5 +1728,6 @@
 }
 
-static int ip_set_gateway_req_local(device_id_t device_id, in_addr_t gateway)
+static int ip_set_gateway_req_local(nic_device_id_t device_id,
+    in_addr_t gateway)
 {
 	ip_netif_t *netif;
@@ -1757,5 +1763,5 @@
  *
  */
-static int ip_received_error_msg_local(device_id_t device_id,
+static int ip_received_error_msg_local(nic_device_id_t device_id,
     packet_t *packet, services_t target, services_t error)
 {
@@ -1818,5 +1824,5 @@
 static int ip_get_route_req_local(ip_protocol_t protocol,
     const struct sockaddr *destination, socklen_t addrlen,
-    device_id_t *device_id, void **header, size_t *headerlen)
+    nic_device_id_t *device_id, void **header, size_t *headerlen)
 {
 	struct sockaddr_in *address_in;
@@ -1909,5 +1915,5 @@
 	size_t suffix;
 	size_t content;
-	device_id_t device_id;
+	nic_device_id_t device_id;
 	int rc;
 	
Index: uspace/srv/net/il/ip/ip.h
===================================================================
--- uspace/srv/net/il/ip/ip.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/il/ip/ip.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -92,5 +92,5 @@
 	in_addr_t broadcast;
 	/** Device identifier. */
-	device_id_t device_id;
+	nic_device_id_t device_id;
 	/** Indicates whether using DHCP. */
 	int dhcp;
@@ -108,5 +108,5 @@
 	services_t service;
 	/** Device state. */
-	device_state_t state;
+	nic_device_state_t state;
 };
 
Index: uspace/srv/net/net/Makefile
===================================================================
--- uspace/srv/net/net/Makefile	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/net/Makefile	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -30,6 +30,6 @@
 USPACE_PREFIX = ../../..
 ROOT_PATH = $(USPACE_PREFIX)/..
-LIBS = $(LIBNET_PREFIX)/libnet.a $(LIBPACKET_PREFIX)/libpacket.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBPACKET_PREFIX)/include
+LIBS = $(LIBNET_PREFIX)/libnet.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
 
 COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
@@ -43,5 +43,6 @@
 SOURCES = \
 	net.c \
-	net_standalone.c
+	net_standalone.c \
+	packet_server.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/net/net.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Radim Vansa
  * All rights reserved.
  *
@@ -36,11 +37,14 @@
  */
 
+#include <assert.h>
 #include <async.h>
 #include <ctype.h>
 #include <ddi.h>
 #include <errno.h>
+#include <str_error.h>
 #include <malloc.h>
 #include <stdio.h>
 #include <str.h>
+#include <devman.h>
 #include <str_error.h>
 #include <ns.h>
@@ -49,4 +53,5 @@
 #include <ipc/net_net.h>
 #include <ipc/il.h>
+#include <ipc/ip.h>
 #include <ipc/nil.h>
 #include <net/modules.h>
@@ -57,15 +62,18 @@
 #include <adt/measured_strings.h>
 #include <adt/module_map.h>
-#include <netif_remote.h>
 #include <nil_remote.h>
 #include <net_interface.h>
 #include <ip_interface.h>
+#include <device/nic.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <cfg.h>
 #include "net.h"
+#include "packet_server.h"
 
 /** Networking module name. */
 #define NAME  "net"
 
-/** File read buffer size. */
-#define BUFFER_SIZE  256
+#define MAX_PATH_LENGTH  1024
 
 /** Networking module global data. */
@@ -109,70 +117,10 @@
 /** Generate new system-unique device identifier.
  *
- * @return		The system-unique devic identifier.
- */
-static device_id_t generate_new_device_id(void)
+ * @return The system-unique devic identifier.
+ *
+ */
+static nic_device_id_t generate_new_device_id(void)
 {
 	return device_assign_devno();
-}
-
-static int parse_line(measured_strings_t *configuration, uint8_t *line)
-{
-	int rc;
-	
-	/* From the beginning */
-	uint8_t *name = line;
-	
-	/* Skip comments and blank lines */
-	if ((*name == '#') || (*name == '\0'))
-		return EOK;
-	
-	/* Skip spaces */
-	while (isspace(*name))
-		name++;
-	
-	/* Remember the name start */
-	uint8_t *value = name;
-	
-	/* Skip the name */
-	while (isalnum(*value) || (*value == '_'))
-		value++;
-	
-	if (*value == '=') {
-		/* Terminate the name */
-		*value = '\0';
-	} else {
-		/* Terminate the name */
-		*value = '\0';
-		
-		/* Skip until '=' */
-		value++;
-		while ((*value) && (*value != '='))
-			value++;
-		
-		/* Not found? */
-		if (*value != '=')
-			return EINVAL;
-	}
-	
-	value++;
-	
-	/* Skip spaces */
-	while (isspace(*value))
-		value++;
-	
-	/* Create a bulk measured string till the end */
-	measured_string_t *setting =
-	    measured_string_create_bulk(value, 0);
-	if (!setting)
-		return ENOMEM;
-	
-	/* Add the configuration setting */
-	rc = measured_strings_add(configuration, name, 0, setting);
-	if (rc != EOK) {
-		free(setting);
-		return rc;
-	}
-	
-	return EOK;
 }
 
@@ -182,50 +130,27 @@
 	printf("%s: Reading configuration file %s/%s\n", NAME, directory, filename);
 	
-	/* Construct the full filename */
-	char fname[BUFFER_SIZE];
-	if (snprintf(fname, BUFFER_SIZE, "%s/%s", directory, filename) > BUFFER_SIZE)
-		return EOVERFLOW;
-	
-	/* Open the file */
-	FILE *cfg = fopen(fname, "r");
-	if (!cfg)
+	cfg_file_t cfg;
+	int rc = cfg_load_path(directory, filename, &cfg);
+	if (rc != EOK)
+		return rc;
+	
+	if (cfg_anonymous(&cfg) == NULL) {
+		cfg_unload(&cfg);
 		return ENOENT;
-	
-	/*
-	 * Read the configuration line by line
-	 * until an error or the end of file
-	 */
-	unsigned int line_number = 0;
-	size_t index = 0;
-	uint8_t line[BUFFER_SIZE];
-	
-	while (!ferror(cfg) && !feof(cfg)) {
-		int read = fgetc(cfg);
-		if ((read > 0) && (read != '\n') && (read != '\r')) {
-			if (index >= BUFFER_SIZE) {
-				line[BUFFER_SIZE - 1] = '\0';
-				fprintf(stderr, "%s: Configuration line %u too "
-				    "long: %s\n", NAME, line_number, (char *) line);
-				
-				/* No space left in the line buffer */
-				return EOVERFLOW;
-			}
-			/* Append the character */
-			line[index] = (uint8_t) read;
-			index++;
-		} else {
-			/* On error or new line */
-			line[index] = '\0';
-			line_number++;
-			if (parse_line(configuration, line) != EOK) {
-				fprintf(stderr, "%s: Configuration error on "
-				    "line %u: %s\n", NAME, line_number, (char *) line);
-			}
-			
-			index = 0;
-		}
-	}
-	
-	fclose(cfg);
+	}
+	
+	cfg_section_foreach(cfg_anonymous(&cfg), link) {
+		const cfg_entry_t *entry = cfg_entry_instance(link);
+		
+		rc = add_configuration(configuration,
+		    (uint8_t *) entry->key, (uint8_t *) entry->value);
+		if (rc != EOK) {
+			printf("%s: Error processing configuration\n", NAME);
+			cfg_unload(&cfg);
+			return rc;
+		}
+	}
+	
+	cfg_unload(&cfg);
 	return EOK;
 }
@@ -272,20 +197,9 @@
 	
 	netifs_initialize(&net_globals.netifs);
-	char_map_initialize(&net_globals.netif_names);
+	char_map_initialize(&net_globals.netif_hwpaths);
 	modules_initialize(&net_globals.modules);
 	measured_strings_initialize(&net_globals.configuration);
 	
-	/* TODO: dynamic configuration */
 	rc = read_configuration();
-	if (rc != EOK)
-		return rc;
-	
-	rc = add_module(NULL, &net_globals.modules, (uint8_t *) LO_NAME,
-	    (uint8_t *) LO_FILENAME, SERVICE_LO, 0, connect_to_service);
-	if (rc != EOK)
-		return rc;
-	
-	rc = add_module(NULL, &net_globals.modules, (uint8_t *) NE2000_NAME,
-	    (uint8_t *) NE2000_FILENAME, SERVICE_NE2000, 0, connect_to_service);
 	if (rc != EOK)
 		return rc;
@@ -331,13 +245,17 @@
 		return rc;
 	
+	rc = packet_server_init();
+	if (rc != EOK)
+		goto out;
+	
 	rc = net_initialize(client_connection);
 	if (rc != EOK)
 		goto out;
 	
+	rc = startup();
+	if (rc != EOK)
+		goto out;
+	
 	rc = service_register(SERVICE_NETWORKING);
-	if (rc != EOK)
-		goto out;
-	
-	rc = startup();
 	if (rc != EOK)
 		goto out;
@@ -364,8 +282,8 @@
  */
 static int net_get_conf(measured_strings_t *netif_conf,
-    measured_string_t *configuration, size_t count, uint8_t **data)
-{
-	if (data)
-		*data = NULL;
+    measured_string_t *configuration, size_t count)
+{
+	if ((!configuration) || (count <= 0))
+			return EINVAL;
 	
 	size_t index;
@@ -389,28 +307,65 @@
 }
 
-static int net_get_conf_req_local(measured_string_t **configuration,
-    size_t count, uint8_t **data)
-{
-	if (!configuration || (count <= 0))
-		return EINVAL;
-	
-	return net_get_conf(NULL, *configuration, count, data);
-}
-
-static int net_get_device_conf_req_local(device_id_t device_id,
-    measured_string_t **configuration, size_t count, uint8_t **data)
-{
-	if ((!configuration) || (count == 0))
-		return EINVAL;
-
+static int net_get_device_conf(nic_device_id_t device_id,
+    measured_string_t *configuration, size_t count)
+{
 	netif_t *netif = netifs_find(&net_globals.netifs, device_id);
 	if (netif)
-		return net_get_conf(&netif->configuration, *configuration, count, data);
+		return net_get_conf(&netif->configuration, configuration, count);
 	else
-		return net_get_conf(NULL, *configuration, count, data);
-}
-
-void net_free_settings(measured_string_t *settings, uint8_t *data)
-{
+		return net_get_conf(NULL, configuration, count);
+}
+
+static int net_get_devices(measured_string_t **devices, size_t *dev_count)
+{
+	if (!devices)
+		return EBADMEM;
+	
+	size_t max_count = netifs_count(&net_globals.netifs);
+	*devices = malloc(max_count * sizeof(measured_string_t));
+	if (*devices == NULL)
+		return ENOMEM;
+	
+	size_t count = 0;
+	for (size_t i = 0; i < max_count; i++) {
+		netif_t *item = netifs_get_index(&net_globals.netifs, i);
+		if (item->sess != NULL) {
+			/* 
+			 * Use format "device_id:device_name"
+			 * FIXME: This typecasting looks really ugly
+			 */
+			(*devices)[count].length = asprintf(
+			    (char **) &((*devices)[count].value),
+			    NIC_DEVICE_PRINT_FMT ":%s", item->id,
+			    (const char *) item->name);
+			count++;
+		}
+	}
+	
+	*dev_count = (size_t) count;
+	return EOK;
+}
+
+static int net_get_devices_count()
+{
+	size_t max_count = netifs_count(&net_globals.netifs);
+	
+	size_t count = 0;
+	for (size_t i = 0; i < max_count; i++) {
+		netif_t *item = netifs_get_index(&net_globals.netifs, i);
+		if (item->sess != NULL)
+			count++;
+	}
+	
+	return count;
+}
+
+static void net_free_devices(measured_string_t *devices, size_t count)
+{
+	size_t i;
+	for (i = 0; i < count; ++i)
+		free(devices[i].value);
+	
+	free(devices);
 }
 
@@ -431,75 +386,124 @@
  *
  */
-static int start_device(netif_t *netif)
-{
-	int rc;
-	
-	/* Mandatory netif */
-	measured_string_t *setting =
-	    measured_strings_find(&netif->configuration, (uint8_t *) CONF_NETIF, 0);
-	
-	netif->driver = get_running_module(&net_globals.modules, setting->value);
-	if (!netif->driver) {
-		fprintf(stderr, "%s: Failed to start network interface driver '%s'\n",
+static int init_device(netif_t *netif, devman_handle_t handle)
+{
+	netif->handle = handle;
+	netif->sess = devman_device_connect(EXCHANGE_SERIALIZE, netif->handle,
+	    IPC_FLAG_BLOCKING);
+	if (netif->sess == NULL) {
+		printf("%s: Unable to connect to device\n", NAME);
+		return EREFUSED;
+	}
+	
+	/* Optional network interface layer */
+	measured_string_t *setting = measured_strings_find(&netif->configuration,
+	    (uint8_t *) CONF_NIL, 0);
+	if (setting) {
+		netif->nil = get_running_module(&net_globals.modules,
+		    setting->value);
+		if (!netif->nil) {
+			printf("%s: Unable to connect to network interface layer '%s'\n",
+			    NAME, setting->value);
+			return EINVAL;
+		}
+	} else
+		netif->nil = NULL;
+	
+	/* Mandatory internet layer */
+	setting = measured_strings_find(&netif->configuration,
+	    (uint8_t *) CONF_IL, 0);
+	netif->il = get_running_module(&net_globals.modules,
+	    setting->value);
+	if (!netif->il) {
+		printf("%s: Unable to connect to internet layer '%s'\n",
 		    NAME, setting->value);
 		return EINVAL;
 	}
 	
-	/* Optional network interface layer */
-	setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_NIL, 0);
-	if (setting) {
-		netif->nil = get_running_module(&net_globals.modules, setting->value);
-		if (!netif->nil) {
-			fprintf(stderr, "%s: Failed to start network interface layer '%s'\n",
-			    NAME, setting->value);
-			return EINVAL;
-		}
-	} else
-		netif->nil = NULL;
-	
-	/* Mandatory internet layer */
-	setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IL, 0);
-	netif->il = get_running_module(&net_globals.modules, setting->value);
-	if (!netif->il) {
-		fprintf(stderr, "%s: Failed to start internet layer '%s'\n",
-		    NAME, setting->value);
-		return EINVAL;
-	}
-	
-	/* Hardware configuration */
-	setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IRQ, 0);
-	int irq = setting ? strtol((char *) setting->value, NULL, 10) : 0;
-	
-	setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IO, 0);
-	uintptr_t io = setting ? strtol((char *) setting->value, NULL, 16) : 0;
-	
-	rc = netif_probe_req(netif->driver->sess, netif->id, irq, (void *) io);
-	if (rc != EOK)
-		return rc;
-	
 	/* Network interface layer startup */
-	services_t internet_service;
+	int rc;
+	services_t nil_service;
 	if (netif->nil) {
-		setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_MTU, 0);
+		setting = measured_strings_find(&netif->configuration,
+		    (uint8_t *) CONF_MTU, 0);
 		if (!setting)
 			setting = measured_strings_find(&net_globals.configuration,
 			    (uint8_t *) CONF_MTU, 0);
 		
-		int mtu = setting ? strtol((char *) setting->value, NULL, 10) : 0;
-		rc = nil_device_req(netif->nil->sess, netif->id, mtu,
-		    netif->driver->service);
+		int mtu = setting ?
+		    strtol((const char *) setting->value, NULL, 10) : 0;
+		rc = nil_device_req(netif->nil->sess, netif->id,
+		    netif->handle, mtu);
+		if (rc != EOK) {
+			printf("%s: Unable to start network interface layer\n",
+			    NAME);
+			return rc;
+		}
+		
+		nil_service = netif->nil->service;
+	} else
+		nil_service = -1;
+	
+	/* Inter-network layer startup */
+	switch (netif->il->service) {
+	case SERVICE_IP:
+		rc = ip_device_req(netif->il->sess, netif->id, nil_service);
+		if (rc != EOK) {
+			printf("%s: Unable to start internet layer\n", NAME);
+			return rc;
+		}
+		
+		break;
+	default:
+		return ENOENT;
+	}
+	
+	return nic_set_state(netif->sess, NIC_STATE_ACTIVE);
+}
+
+static int net_driver_port_ready(devman_handle_t handle)
+{
+	char hwpath[MAX_PATH_LENGTH];
+	int rc = devman_fun_get_path(handle, hwpath, MAX_PATH_LENGTH);
+	if (rc != EOK)
+		return EINVAL;
+	
+	int index = char_map_find(&net_globals.netif_hwpaths,
+	    (uint8_t *) hwpath, 0);
+	if (index == CHAR_MAP_NULL)
+		return ENOENT;
+	
+	netif_t *netif = netifs_get_index(&net_globals.netifs, index);
+	if (netif == NULL)
+		return ENOENT;
+	
+	rc = init_device(netif, handle);
+	if (rc != EOK)
+		return rc;
+	
+	/* Increment module usage */
+	if (netif->nil)
+		netif->nil->usage++;
+	
+	netif->il->usage++;
+	
+	return EOK;
+}
+
+static int net_driver_ready_local(devman_handle_t handle)
+{
+	devman_handle_t *funs;
+	size_t count;
+	int rc = devman_dev_get_functions(handle, &funs, &count);
+	if (rc != EOK)
+		return rc;
+	
+	for (size_t i = 0; i < count; i++) {
+		rc = net_driver_port_ready(funs[i]);
 		if (rc != EOK)
 			return rc;
-		
-		internet_service = netif->nil->service;
-	} else
-		internet_service = netif->driver->service;
-	
-	/* Inter-network layer startup */
-	rc = ip_device_req(netif->il->sess, netif->id, internet_service);
-	if (rc != EOK)
-		return rc;
-	
-	return netif_start_req(netif->driver->sess, netif->id);
+	}
+	
+	return EOK;
 }
 
@@ -519,43 +523,60 @@
 static int startup(void)
 {
-	const char *conf_files[] = {
-		"lo",
-		"ne2k"
-	};
-	size_t count = sizeof(conf_files) / sizeof(char *);
 	int rc;
 	
-	size_t i;
-	for (i = 0; i < count; i++) {
+	DIR *config_dir = opendir(CONF_DIR);
+	if (config_dir == NULL)
+		return ENOENT;
+	
+	struct dirent *dir_entry;
+	while ((dir_entry = readdir(config_dir))) {
+		if (str_cmp(dir_entry->d_name + str_length(dir_entry->d_name)
+			- str_length(CONF_EXT), CONF_EXT) != 0)
+			continue;
+		
 		netif_t *netif = (netif_t *) malloc(sizeof(netif_t));
 		if (!netif)
-			return ENOMEM;
+			continue;
+		
+		netif->handle = -1;
+		netif->sess = NULL;
 		
 		netif->id = generate_new_device_id();
-		if (!netif->id)
-			return EXDEV;
+		if (!netif->id) {
+			free(netif);
+			continue;
+		}
 		
 		rc = measured_strings_initialize(&netif->configuration);
-		if (rc != EOK)
-			return rc;
-		
-		/* Read configuration files */
-		rc = read_netif_configuration(conf_files[i], netif);
 		if (rc != EOK) {
+			free(netif);
+			continue;
+		}
+		
+		rc = read_netif_configuration(dir_entry->d_name, netif);
+		if (rc != EOK) {
+			free(netif);
+			continue;
+		}
+		
+		/* Mandatory name */
+		measured_string_t *name = measured_strings_find(&netif->configuration,
+		    (uint8_t *) CONF_NAME, 0);
+		if (!name) {
+			printf("%s: Network interface name is missing\n", NAME);
 			measured_strings_destroy(&netif->configuration, free);
 			free(netif);
-			return rc;
-		}
-		
-		/* Mandatory name */
-		measured_string_t *setting =
-		    measured_strings_find(&netif->configuration, (uint8_t *) CONF_NAME, 0);
-		if (!setting) {
-			fprintf(stderr, "%s: Network interface name is missing\n", NAME);
+			continue;
+		}
+		
+		netif->name = name->value;
+		
+		/* Mandatory hardware path */
+		measured_string_t *hwpath = measured_strings_find(
+		    &netif->configuration, (const uint8_t *) CONF_HWPATH, 0);
+		if (!hwpath) {
 			measured_strings_destroy(&netif->configuration, free);
 			free(netif);
-			return EINVAL;
-		}
-		netif->name = setting->value;
+		}
 		
 		/* Add to the netifs map */
@@ -564,40 +585,20 @@
 			measured_strings_destroy(&netif->configuration, free);
 			free(netif);
-			return index;
+			continue;
 		}
 		
 		/*
-		 * Add to the netif names map and start network interfaces
+		 * Add to the hardware paths map and init network interfaces
 		 * and needed modules.
 		 */
-		rc = char_map_add(&net_globals.netif_names, netif->name, 0,
-		    index);
+		rc = char_map_add(&net_globals.netif_hwpaths, hwpath->value, 0, index);
 		if (rc != EOK) {
 			measured_strings_destroy(&netif->configuration, free);
 			netifs_exclude_index(&net_globals.netifs, index, free);
-			return rc;
-		}
-		
-		rc = start_device(netif);
-		if (rc != EOK) {
-			printf("%s: Ignoring failed interface %s (%s)\n", NAME,
-			    netif->name, str_error(rc));
-			measured_strings_destroy(&netif->configuration, free);
-			netifs_exclude_index(&net_globals.netifs, index, free);
 			continue;
 		}
-		
-		/* Increment modules' usage */
-		netif->driver->usage++;
-		if (netif->nil)
-			netif->nil->usage++;
-		netif->il->usage++;
-		
-		printf("%s: Network interface started (name: %s, id: %d, driver: %s, "
-		    "nil: %s, il: %s)\n", NAME, netif->name, netif->id,
-		    netif->driver->name, netif->nil ? (char *) netif->nil->name : "[none]",
-		    netif->il->name);
-	}
-	
+	}
+	
+	closedir(config_dir);
 	return EOK;
 }
@@ -624,4 +625,5 @@
 	uint8_t *data;
 	int rc;
+	size_t count;
 	
 	*answer_count = 0;
@@ -636,12 +638,11 @@
 		if (rc != EOK)
 			return rc;
-		net_get_device_conf_req_local(IPC_GET_DEVICE(*call), &strings,
-		    IPC_GET_COUNT(*call), NULL);
-		
-		/* Strings should not contain received data anymore */
-		free(data);
+		
+		net_get_device_conf(IPC_GET_DEVICE(*call), strings,
+		    IPC_GET_COUNT(*call));
 		
 		rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
 		free(strings);
+		free(data);
 		return rc;
 	case NET_NET_GET_CONF:
@@ -650,17 +651,31 @@
 		if (rc != EOK)
 			return rc;
-		net_get_conf_req_local(&strings, IPC_GET_COUNT(*call), NULL);
-		
-		/* Strings should not contain received data anymore */
-		free(data);
+		
+		net_get_conf(NULL, strings, IPC_GET_COUNT(*call));
 		
 		rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
 		free(strings);
-		return rc;
-	case NET_NET_STARTUP:
-		return startup();
-	}
-	
-	return ENOTSUP;
+		free(data);
+		return rc;
+	case NET_NET_GET_DEVICES_COUNT:
+		count = (size_t) net_get_devices_count();
+		IPC_SET_ARG1(*answer, count);
+		*answer_count = 1;
+		return EOK;
+	case NET_NET_GET_DEVICES:
+		rc = net_get_devices(&strings, &count);
+		if (rc != EOK)
+			return rc;
+		
+		rc = measured_strings_reply(strings, count);
+		net_free_devices(strings, count);
+		return rc;
+	case NET_NET_DRIVER_READY:
+		rc = net_driver_ready_local(IPC_GET_ARG1(*call));
+		*answer_count = 0;
+		return rc;
+	default:
+		return ENOTSUP;
+	}
 }
 
Index: uspace/srv/net/net/net.h
===================================================================
--- uspace/srv/net/net/net.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/net/net.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Radim Vansa
  * All rights reserved.
  *
@@ -45,11 +46,9 @@
 #include <adt/module_map.h>
 #include <net/packet.h>
+#include <devman.h>
 
 /** @name Modules definitions
  * @{
  */
-
-#define NE2000_FILENAME  "/srv/ne2000"
-#define NE2000_NAME      "ne2000"
 
 #define ETHERNET_FILENAME  "/srv/eth"
@@ -58,7 +57,4 @@
 #define IP_FILENAME  "/srv/ip"
 #define IP_NAME      "ip"
-
-#define LO_FILENAME  "/srv/lo"
-#define LO_NAME      "lo"
 
 #define NILDUMMY_FILENAME  "/srv/nildummy"
@@ -77,5 +73,5 @@
 #define CONF_MTU    "MTU"    /**< Maximum transmission unit configuration label. */
 #define CONF_NAME   "NAME"   /**< Network interface name configuration label. */
-#define CONF_NETIF  "NETIF"  /**< Network interface module name configuration label. */
+#define CONF_HWPATH "HWPATH" /**< Network interface hardware pathname label. */
 #define CONF_NIL    "NIL"    /**< Network interface layer module name configuration label. */
 
@@ -85,4 +81,5 @@
 #define CONF_DIR           "/cfg/net"  /**< Configuration directory. */
 #define CONF_GENERAL_FILE  "general"   /**< General configuration file. */
+#define CONF_EXT           ".nic"      /**< Extension for NIC's configuration files. */
 
 /** Configuration settings.
@@ -98,13 +95,14 @@
  */
 typedef struct {
+	uint8_t *name;     			/**< System-unique network interface name. */
+	nic_device_id_t id;  		/**< System-unique network interface identifier. */
 	measured_strings_t configuration;  /**< Configuration. */
 	
 	/** Serving network interface driver module index. */
-	module_t *driver;
+	devman_handle_t handle;		/**< Handle for devman */
+	async_sess_t *sess;		 	/**< Driver session. */
 	
-	device_id_t id;  /**< System-unique network interface identifier. */
+	module_t *nil;   /**< Serving link layer module index. */
 	module_t *il;    /**< Serving internet layer module index. */
-	uint8_t *name;   /**< System-unique network interface name. */
-	module_t *nil;   /**< Serving link layer module index. */
 } netif_t;
 
@@ -124,6 +122,6 @@
 	modules_t modules;                 /**< Available modules. */
 	
-	/** Network interface structure indices by names. */
-	char_map_t netif_names;
+	/** Network interface structure indices by hardware path. */
+	char_map_t netif_hwpaths;
 	
 	/** Present network interfaces. */
Index: uspace/srv/net/net/net_standalone.c
===================================================================
--- uspace/srv/net/net/net_standalone.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/net/net_standalone.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -35,6 +35,4 @@
  */
 
-#include "net.h"
-
 #include <str.h>
 #include <adt/measured_strings.h>
@@ -42,7 +40,7 @@
 #include <ipc/net.h>
 #include <errno.h>
-
 #include <ip_interface.h>
-#include <packet_server.h>
+#include "net.h"
+#include "packet_server.h"
 
 /** Networking module global data. */
@@ -62,5 +60,5 @@
 	int rc;
 	
-	task_id_t task_id = net_spawn((uint8_t *) "/srv/ip");
+	task_id_t task_id = net_spawn((uint8_t *) IP_FILENAME);
 	if (!task_id)
 		return EINVAL;
Index: uspace/srv/net/net/packet_server.c
===================================================================
--- uspace/srv/net/net/packet_server.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
+++ uspace/srv/net/net/packet_server.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Radim Vansa
+ * 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 libpacket
+ *  @{
+ */
+
+/** @file
+ * Packet server implementation.
+ */
+
+#include <align.h>
+#include <assert.h>
+#include <async.h>
+#include <errno.h>
+#include <str_error.h>
+#include <stdio.h>
+#include <fibril_synch.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <ipc/packet.h>
+#include <ipc/net.h>
+#include <net/packet.h>
+#include <net/packet_header.h>
+
+#include "packet_server.h"
+
+#define PACKET_SERVER_PROFILE 1
+
+/** Number of queues cacheing the unused packets */
+#define FREE_QUEUES_COUNT	7
+/** Maximum number of packets in each queue */
+#define FREE_QUEUE_MAX_LENGTH	16
+
+/** The default address length reserved for new packets. */
+#define DEFAULT_ADDR_LEN	32
+
+/** The default prefix reserved for new packets. */
+#define DEFAULT_PREFIX		64
+
+/** The default suffix reserved for new packets. */
+#define DEFAULT_SUFFIX		64
+
+/** The queue with unused packets */
+typedef struct packet_queue {
+	packet_t *first;	/**< First packet in the queue */
+	size_t packet_size; /**< Maximal size of the packets in this queue */
+	int count;			/**< Length of the queue */
+} packet_queue_t;
+
+/** Packet server global data. */
+static struct {
+	/** Safety lock. */
+	fibril_mutex_t lock;
+	/** Free packet queues. */
+	packet_queue_t free_queues[FREE_QUEUES_COUNT];
+	
+	/** Total packets allocated. */
+	packet_id_t next_id;
+} ps_globals = {
+	.lock = FIBRIL_MUTEX_INITIALIZER(ps_globals.lock),
+	.free_queues = {
+		{ NULL, PAGE_SIZE, 0},
+		{ NULL, PAGE_SIZE * 2, 0},
+		{ NULL, PAGE_SIZE * 4, 0},
+		{ NULL, PAGE_SIZE * 8, 0},
+		{ NULL, PAGE_SIZE * 16, 0},
+		{ NULL, PAGE_SIZE * 32, 0},
+		{ NULL, PAGE_SIZE * 64, 0},
+	},
+	.next_id = 1
+};
+
+/** Clears and initializes the packet according to the given dimensions.
+ *
+ * @param[in] packet	The packet to be initialized.
+ * @param[in] addr_len	The source and destination addresses maximal length in
+ *			bytes.
+ * @param[in] max_prefix The maximal prefix length in bytes.
+ * @param[in] max_content The maximal content length in bytes.
+ * @param[in] max_suffix The maximal suffix length in bytes.
+ */
+static void packet_init(packet_t *packet,
+	size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix)
+{
+	/* Clear the packet content */
+	bzero(((void *) packet) + sizeof(packet_t),
+	    packet->length - sizeof(packet_t));
+	
+	/* Clear the packet header */
+	packet->order = 0;
+	packet->metric = 0;
+	packet->previous = 0;
+	packet->next = 0;
+	packet->offload_info = 0;
+	packet->offload_mask = 0;
+	packet->addr_len = 0;
+	packet->src_addr = sizeof(packet_t);
+	packet->dest_addr = packet->src_addr + addr_len;
+	packet->max_prefix = max_prefix;
+	packet->max_content = max_content;
+	packet->data_start = packet->dest_addr + addr_len + packet->max_prefix;
+	packet->data_end = packet->data_start;
+}
+
+/**
+ * Releases the memory allocated for the packet
+ *
+ * @param[in] packet Pointer to the memory where the packet was allocated
+ */
+static void packet_dealloc(packet_t *packet)
+{
+	pm_remove(packet);
+	munmap(packet, packet->length);
+}
+
+/** Creates a new packet of dimensions at least as given.
+ *
+ * @param[in] length	The total length of the packet, including the header,
+ *			the addresses and the data of the packet.
+ * @param[in] addr_len	The source and destination addresses maximal length in
+ *			bytes.
+ * @param[in] max_prefix The maximal prefix length in bytes.
+ * @param[in] max_content The maximal content length in bytes.
+ * @param[in] max_suffix The maximal suffix length in bytes.
+ * @return		The packet of dimensions at least as given.
+ * @return		NULL if there is not enough memory left.
+ */
+static packet_t *packet_alloc(size_t length, size_t addr_len,
+	size_t max_prefix, size_t max_content, size_t max_suffix)
+{
+	packet_t *packet;
+	int rc;
+
+	/* Global lock is locked */
+	assert(fibril_mutex_is_locked(&ps_globals.lock));
+	/* The length is some multiple of PAGE_SIZE */
+	assert(!(length & (PAGE_SIZE - 1)));
+
+	packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
+		MAP_SHARED | MAP_ANONYMOUS, 0, 0);
+	if (packet == MAP_FAILED)
+		return NULL;
+	
+	/* Using 32bit packet_id the id could overflow */
+	packet_id_t pid;
+	do {
+		pid = ps_globals.next_id;
+		ps_globals.next_id++;
+	} while (!pid || pm_find(pid));
+	packet->packet_id = pid;
+
+	packet->length = length;
+	packet_init(packet, addr_len, max_prefix, max_content, max_suffix);
+	packet->magic_value = PACKET_MAGIC_VALUE;
+	rc = pm_add(packet);
+	if (rc != EOK) {
+		packet_dealloc(packet);
+		return NULL;
+	}
+	
+	return packet;
+}
+
+/** Return the packet of dimensions at least as given.
+ *
+ * Try to reuse free packets first.
+ * Create a new packet aligned to the memory page size if none available.
+ * Lock the global data during its processing.
+ *
+ * @param[in] addr_len	The source and destination addresses maximal length in
+ *			bytes.
+ * @param[in] max_prefix The maximal prefix length in bytes.
+ * @param[in] max_content The maximal content length in bytes.
+ * @param[in] max_suffix The maximal suffix length in bytes.
+ * @return		The packet of dimensions at least as given.
+ * @return		NULL if there is not enough memory left.
+ */
+static packet_t *packet_get_local(size_t addr_len,
+	size_t max_prefix, size_t max_content, size_t max_suffix)
+{
+	size_t length = ALIGN_UP(sizeof(packet_t) + 2 * addr_len
+		+ max_prefix + max_content + max_suffix, PAGE_SIZE);
+	
+	if (length > PACKET_MAX_LENGTH)
+		return NULL;
+
+	fibril_mutex_lock(&ps_globals.lock);
+	
+	packet_t *packet;
+	unsigned int index;
+	
+	for (index = 0; index < FREE_QUEUES_COUNT; index++) {
+		if ((length > ps_globals.free_queues[index].packet_size) &&
+			(index < FREE_QUEUES_COUNT - 1))
+			continue;
+		
+		packet = ps_globals.free_queues[index].first;
+		while (packet_is_valid(packet) && (packet->length < length))
+			packet = pm_find(packet->next);
+		
+		if (packet_is_valid(packet)) {
+			ps_globals.free_queues[index].count--;
+			if (packet == ps_globals.free_queues[index].first) {
+				ps_globals.free_queues[index].first = pq_detach(packet);
+			} else {
+				pq_detach(packet);
+			}
+			
+			packet_init(packet, addr_len, max_prefix, max_content, max_suffix);
+			fibril_mutex_unlock(&ps_globals.lock);
+			
+			return packet;
+		}
+	}
+	
+	packet = packet_alloc(length, addr_len,
+		max_prefix, max_content, max_suffix);
+	
+	fibril_mutex_unlock(&ps_globals.lock);
+	
+	return packet;
+}
+
+/** Release the packet and returns it to the appropriate free packet queue.
+ *
+ * @param[in] packet	The packet to be released.
+ *
+ */
+static void packet_release(packet_t *packet)
+{
+	int index;
+	int result;
+
+	assert(fibril_mutex_is_locked(&ps_globals.lock));
+
+	for (index = 0; (index < FREE_QUEUES_COUNT - 1) &&
+	    (packet->length > ps_globals.free_queues[index].packet_size); index++) {
+		;
+	}
+	
+	ps_globals.free_queues[index].count++;
+	result = pq_add(&ps_globals.free_queues[index].first, packet,
+		packet->length,	packet->length);
+	assert(result == EOK);
+}
+
+/** Releases the packet queue.
+ *
+ * @param[in] packet_id	The first packet identifier.
+ * @return		EOK on success.
+ * @return		ENOENT if there is no such packet.
+ */
+static int packet_release_wrapper(packet_id_t packet_id)
+{
+	packet_t *packet;
+
+	packet = pm_find(packet_id);
+	if (!packet_is_valid(packet))
+		return ENOENT;
+
+	fibril_mutex_lock(&ps_globals.lock);
+	pq_destroy(packet, packet_release);
+	fibril_mutex_unlock(&ps_globals.lock);
+
+	return EOK;
+}
+
+/** Shares the packet memory block.
+ * @param[in] packet	The packet to be shared.
+ * @return		EOK on success.
+ * @return		EINVAL if the packet is not valid.
+ * @return		EINVAL if the calling module does not accept the memory.
+ * @return		ENOMEM if the desired and actual sizes differ.
+ * @return		Other error codes as defined for the
+ *			async_share_in_finalize() function.
+ */
+static int packet_reply(packet_t *packet)
+{
+	ipc_callid_t callid;
+	size_t size;
+
+	if (!packet_is_valid(packet))
+		return EINVAL;
+
+	if (!async_share_in_receive(&callid, &size)) {
+		async_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+
+	if (size != packet->length) {
+		async_answer_0(callid, ENOMEM);
+		return ENOMEM;
+	}
+	
+	return async_share_in_finalize(callid, packet,
+	    PROTO_READ | PROTO_WRITE);
+}
+
+/** Processes the packet server message.
+ *
+ * @param[in] callid	The message identifier.
+ * @param[in] call	The message parameters.
+ * @param[out] answer	The message answer parameters.
+ * @param[out] answer_count The last parameter for the actual answer in the
+ *			answer parameter.
+ * @return		EOK on success.
+ * @return		ENOMEM if there is not enough memory left.
+ * @return		ENOENT if there is no such packet as in the packet
+ *			message parameter.
+ * @return		ENOTSUP if the message is not known.
+ * @return		Other error codes as defined for the
+ *			packet_release_wrapper() function.
+ */
+int packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
+    size_t *answer_count)
+{
+	packet_t *packet;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
+	*answer_count = 0;
+	switch (IPC_GET_IMETHOD(*call)) {
+	case NET_PACKET_CREATE_1:
+		packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX,
+			IPC_GET_CONTENT(*call), DEFAULT_SUFFIX);
+		if (!packet)
+			return ENOMEM;
+		*answer_count = 2;
+		IPC_SET_ARG1(*answer, (sysarg_t) packet->packet_id);
+		IPC_SET_ARG2(*answer, (sysarg_t) packet->length);
+		return EOK;
+	
+	case NET_PACKET_CREATE_4:
+		packet = packet_get_local(
+			((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(*call)) ?
+		    IPC_GET_ADDR_LEN(*call) : DEFAULT_ADDR_LEN),
+		    DEFAULT_PREFIX + IPC_GET_PREFIX(*call),
+		    IPC_GET_CONTENT(*call),
+		    DEFAULT_SUFFIX + IPC_GET_SUFFIX(*call));
+		if (!packet)
+			return ENOMEM;
+		*answer_count = 2;
+		IPC_SET_ARG1(*answer, (sysarg_t) packet->packet_id);
+		IPC_SET_ARG2(*answer, (sysarg_t) packet->length);
+		return EOK;
+	
+	case NET_PACKET_GET:
+		packet = pm_find(IPC_GET_ID(*call));
+		if (!packet_is_valid(packet)) {
+			return ENOENT;
+		}
+		return packet_reply(packet);
+	
+	case NET_PACKET_GET_SIZE:
+		packet = pm_find(IPC_GET_ID(*call));
+		if (!packet_is_valid(packet))
+			return ENOENT;
+		IPC_SET_ARG1(*answer, (sysarg_t) packet->length);
+		*answer_count = 1;
+		return EOK;
+	
+	case NET_PACKET_RELEASE:
+		return packet_release_wrapper(IPC_GET_ID(*call));
+	}
+	
+	return ENOTSUP;
+}
+
+int packet_server_init()
+{
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/net/packet_server.h
===================================================================
--- uspace/srv/net/net/packet_server.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
+++ uspace/srv/net/net/packet_server.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Radim Vansa
+ * 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 libpacket
+ * @{
+ */
+
+/** @file
+ * Packet server.
+ * The hosting module has to be compiled with both the packet.c and the
+ * packet_server.c source files. To function correctly, initialization of the
+ * packet map by the pm_init() function has to happen at the first place. Then
+ * the packet messages have to be processed by the packet_server_message()
+ * function. The packet map should be released by the pm_destroy() function
+ * during the module termination.
+ * @see IS_NET_PACKET_MESSAGE()
+ */
+
+#ifndef LIBPACKET_PACKET_SERVER_H_
+#define LIBPACKET_PACKET_SERVER_H_
+
+#include <ipc/common.h>
+
+extern int packet_server_init(void);
+extern int packet_server_message(ipc_callid_t, ipc_call_t *, ipc_call_t *,
+    size_t *);
+
+#endif
+
+/** @}
+ */
Index: pace/srv/net/netif/lo/Makefile
===================================================================
--- uspace/srv/net/netif/lo/Makefile	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,46 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-BINARY = lo
-
-SOURCES = \
-	lo.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ 	(revision )
@@ -1,231 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup lo
- * @{
- */
-
-/** @file
- * Loopback network interface implementation.
- */
-
-#include <async.h>
-#include <errno.h>
-#include <stdio.h>
-#include <str.h>
-#include <ns.h>
-#include <ipc/services.h>
-#include <ipc/nil.h>
-#include <net/modules.h>
-#include <adt/measured_strings.h>
-#include <packet_client.h>
-#include <net/device.h>
-#include <netif_skel.h>
-#include <nil_remote.h>
-
-/** Default address length. */
-#define DEFAULT_ADDR_LEN  6
-
-/** Loopback module name. */
-#define NAME  "lo"
-
-static uint8_t default_addr[DEFAULT_ADDR_LEN] =
-    {0, 0, 0, 0, 0, 0};
-
-int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *count)
-{
-	return ENOTSUP;
-}
-
-int netif_get_addr_message(device_id_t device_id, measured_string_t *address)
-{
-	if (!address)
-		return EBADMEM;
-	
-	address->value = default_addr;
-	address->length = DEFAULT_ADDR_LEN;
-	
-	return EOK;
-}
-
-int netif_get_device_stats(device_id_t device_id, device_stats_t *stats)
-{
-	if (!stats)
-		return EBADMEM;
-	
-	netif_device_t *device;
-	int rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	memcpy(stats, (device_stats_t *) device->specific,
-	    sizeof(device_stats_t));
-	
-	return EOK;
-}
-
-/** Change the loopback state.
- *
- * @param[in] device The device structure.
- * @param[in] state  The new device state.
- *
- * @return New state if changed.
- * @return EOK otherwise.
- *
- */
-static void change_state_message(netif_device_t *device, device_state_t state)
-{
-	if (device->state != state) {
-		device->state = state;
-		
-		const char *desc;
-		switch (state) {
-		case NETIF_ACTIVE:
-			desc = "active";
-			break;
-		case NETIF_STOPPED:
-			desc = "stopped";
-			break;
-		default:
-			desc = "unknown";
-		}
-		
-		printf("%s: State changed to %s\n", NAME, desc);
-	}
-}
-
-/** Create and return the loopback network interface structure.
- *
- * @param[in]  device_id New devce identifier.
- * @param[out] device    Device structure.
- *
- * @return EOK on success.
- * @return EXDEV if one loopback network interface already exists.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int lo_create(device_id_t device_id, netif_device_t **device)
-{
-	if (netif_device_map_count(&netif_globals.device_map) > 0)
-		return EXDEV;
-	
-	*device = (netif_device_t *) malloc(sizeof(netif_device_t));
-	if (!*device)
-		return ENOMEM;
-	
-	(*device)->specific = (device_stats_t *) malloc(sizeof(device_stats_t));
-	if (!(*device)->specific) {
-		free(*device);
-		return ENOMEM;
-	}
-	
-	null_device_stats((device_stats_t *) (*device)->specific);
-	(*device)->device_id = device_id;
-	(*device)->state = NETIF_STOPPED;
-	int index = netif_device_map_add(&netif_globals.device_map,
-	    (*device)->device_id, *device);
-	
-	if (index < 0) {
-		free(*device);
-		free((*device)->specific);
-		*device = NULL;
-		return index;
-	}
-	
-	return EOK;
-}
-
-int netif_initialize(void)
-{
-	return service_register(SERVICE_LO);
-}
-
-int netif_probe_message(device_id_t device_id, int irq, void *io)
-{
-	/* Create a new device */
-	netif_device_t *device;
-	int rc = lo_create(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	printf("%s: Device created (id: %d)\n", NAME, device->device_id);
-	return EOK;
-}
-
-int netif_send_message(device_id_t device_id, packet_t *packet, services_t sender)
-{
-	netif_device_t *device;
-	int rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return EOK;
-	
-	if (device->state != NETIF_ACTIVE) {
-		netif_pq_release(packet_get_id(packet));
-		return EFORWARD;
-	}
-	
-	packet_t *next = packet;
-	do {
-		((device_stats_t *) device->specific)->send_packets++;
-		((device_stats_t *) device->specific)->receive_packets++;
-		size_t length = packet_get_data_length(next);
-		((device_stats_t *) device->specific)->send_bytes += length;
-		((device_stats_t *) device->specific)->receive_bytes += length;
-		next = pq_next(next);
-	} while (next);
-	
-	async_sess_t *nil_sess = netif_globals.nil_sess;
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	nil_received_msg(nil_sess, device_id, packet, sender);
-	
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	return EOK;
-}
-
-int netif_start_message(netif_device_t *device)
-{
-	change_state_message(device, NETIF_ACTIVE);
-	return device->state;
-}
-
-int netif_stop_message(netif_device_t *device)
-{
-	change_state_message(device, NETIF_STOPPED);
-	return device->state;
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return netif_module_start();
-}
-
-/** @}
- */
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/nil/eth/eth.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Radim Vansa
  * All rights reserved.
  *
@@ -36,4 +37,5 @@
  */
 
+#include <assert.h>
 #include <async.h>
 #include <malloc.h>
@@ -52,5 +54,4 @@
 #include <protocol_map.h>
 #include <net/device.h>
-#include <netif_remote.h>
 #include <net_interface.h>
 #include <il_remote.h>
@@ -58,4 +59,5 @@
 #include <packet_client.h>
 #include <packet_remote.h>
+#include <device/nic.h>
 #include <nil_skel.h>
 #include "eth.h"
@@ -167,5 +169,5 @@
 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
 
-int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
+int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
 {
 	int index;
@@ -196,11 +198,6 @@
 	fibril_rwlock_write_lock(&eth_globals.protos_lock);
 	eth_globals.net_sess = sess;
-
-	eth_globals.broadcast_addr =
-	    measured_string_create_bulk((uint8_t *) "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ADDR);
-	if (!eth_globals.broadcast_addr) {
-		rc = ENOMEM;
-		goto out;
-	}
+	memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
+			ETH_ADDR);
 
 	rc = eth_devices_initialize(&eth_globals.devices);
@@ -215,4 +212,5 @@
 		eth_devices_destroy(&eth_globals.devices, free);
 	}
+	
 out:
 	fibril_rwlock_write_unlock(&eth_globals.protos_lock);
@@ -222,59 +220,18 @@
 }
 
-/** Process IPC messages from the registered device driver modules in an
- * infinite loop.
- *
- * @param[in]     iid   Message identifier.
- * @param[in,out] icall Message parameters.
- * @param[in]     arg   Local argument.
- *
- */
-static void eth_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-
-	while (true) {
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_NIL_DEVICE_STATE:
-			nil_device_state_msg_local(IPC_GET_DEVICE(*icall),
-			    IPC_GET_STATE(*icall));
-			async_answer_0(iid, EOK);
-			break;
-		case NET_NIL_RECEIVED:
-			rc = packet_translate_remote(eth_globals.net_sess,
-			    &packet, IPC_GET_PACKET(*icall));
-			if (rc == EOK)
-				rc = nil_received_msg_local(IPC_GET_DEVICE(*icall),
-				    packet, 0);
-			
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(iid, (sysarg_t) ENOTSUP);
-		}
-		
-		iid = async_get_call(icall);
-	}
-}
-
-/** Registers new device or updates the MTU of an existing one.
- *
- * Determines the device local hardware address.
- *
- * @param[in] device_id	The new device identifier.
- * @param[in] service	The device driver service.
- * @param[in] mtu	The device maximum transmission unit.
- * @return		EOK on success.
- * @return		EEXIST if the device with the different service exists.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			net_get_device_conf_req() function.
- * @return		Other error codes as defined for the
- *			netif_bind_service() function.
- * @return		Other error codes as defined for the
- *			netif_get_addr_req() function.
- */
-static int eth_device_message(device_id_t device_id, services_t service,
+/** Register new device or updates the MTU of an existing one.
+ *
+ * Determine the device local hardware address.
+ *
+ * @param[in] device_id New device identifier.
+ * @param[in] handle    Device driver handle.
+ * @param[in] mtu       Device maximum transmission unit.
+ *
+ * @return EOK on success.
+ * @return EEXIST if the device with the different service exists.
+ * @return ENOMEM if there is not enough memory left.
+ *
+ */
+static int eth_device_message(nic_device_id_t device_id, devman_handle_t handle,
     size_t mtu)
 {
@@ -301,5 +258,5 @@
 	device = eth_devices_find(&eth_globals.devices, device_id);
 	if (device) {
-		if (device->service != service) {
+		if (device->handle != handle) {
 			printf("Device %d already exists\n", device->device_id);
 			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
@@ -340,5 +297,5 @@
 
 	device->device_id = device_id;
-	device->service = service;
+	device->handle = handle;
 	device->flags = 0;
 	if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
@@ -377,6 +334,6 @@
 	
 	/* Bind the device driver */
-	device->sess = netif_bind_service(device->service, device->device_id,
-	    SERVICE_ETHERNET, eth_receiver);
+	device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
+	    IPC_FLAG_BLOCKING);
 	if (device->sess == NULL) {
 		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
@@ -385,7 +342,8 @@
 	}
 	
+	nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id);
+	
 	/* Get hardware address */
-	rc = netif_get_addr_req(device->sess, device->device_id, &device->addr,
-	    &device->addr_data);
+	rc = nic_get_address(device->sess, &device->addr);
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
@@ -399,16 +357,12 @@
 	if (index < 0) {
 		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		free(device->addr);
-		free(device->addr_data);
 		free(device);
 		return index;
 	}
 	
-	printf("%s: Device registered (id: %d, service: %d: mtu: %zu, "
-	    "mac: %02x:%02x:%02x:%02x:%02x:%02x, flags: 0x%x)\n",
-	    NAME, device->device_id, device->service, device->mtu,
-	    device->addr_data[0], device->addr_data[1],
-	    device->addr_data[2], device->addr_data[3],
-	    device->addr_data[4], device->addr_data[5], device->flags);
+	printf("%s: Device registered (id: %d, handle: %zu: mtu: %zu, "
+	    "mac: " PRIMAC ", flags: 0x%x)\n", NAME,
+	    device->device_id, device->handle, device->mtu,
+	    ARGSMAC(device->addr.address), device->flags);
 
 	fibril_rwlock_write_unlock(&eth_globals.devices_lock);
@@ -456,5 +410,5 @@
 		fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
 		length -= sizeof(eth_fcs_t);
-	} else if(type <= ETH_MAX_CONTENT) {
+	} else if (type <= ETH_MAX_CONTENT) {
 		/* Translate "LSAP" values */
 		if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
@@ -462,5 +416,5 @@
 			/* Raw packet -- discard */
 			return NULL;
-		} else if((header->lsap.dsap == ETH_LSAP_SNAP) &&
+		} else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
 		    (header->lsap.ssap == ETH_LSAP_SNAP)) {
 			/*
@@ -469,12 +423,10 @@
 			 */
 			type = ntohs(header->snap.ethertype);
-			prefix = sizeof(eth_header_t) +
-			    sizeof(eth_header_lsap_t) +
+			prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
 			    sizeof(eth_header_snap_t);
 		} else {
 			/* IEEE 802.3 + 802.2 LSAP */
 			type = lsap_map(header->lsap.dsap);
-			prefix = sizeof(eth_header_t) +
-			    sizeof(eth_header_lsap_t);
+			prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
 		}
 
@@ -506,6 +458,5 @@
 }
 
-int nil_received_msg_local(device_id_t device_id, packet_t *packet,
-    services_t target)
+int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
 {
 	eth_proto_t *proto;
@@ -523,6 +474,6 @@
 	flags = device->flags;
 	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-	
 	fibril_rwlock_read_lock(&eth_globals.protos_lock);
+	
 	do {
 		next = pq_detach(packet);
@@ -537,5 +488,5 @@
 		}
 		packet = next;
-	} while(packet);
+	} while (packet);
 
 	fibril_rwlock_read_unlock(&eth_globals.protos_lock);
@@ -554,5 +505,5 @@
  * @return		ENOENT if there is no such device.
  */
-static int eth_packet_space_message(device_id_t device_id, size_t *addr_len,
+static int eth_packet_space_message(nic_device_id_t device_id, size_t *addr_len,
     size_t *prefix, size_t *content, size_t *suffix)
 {
@@ -579,24 +530,22 @@
 }
 
-/** Returns the device hardware address.
+/** Send the device hardware address.
  *
  * @param[in] device_id	The device identifier.
  * @param[in] type	Type of the desired address.
- * @param[out] address	The device hardware address.
  * @return		EOK on success.
  * @return		EBADMEM if the address parameter is NULL.
  * @return		ENOENT if there no such device.
  */
-static int eth_addr_message(device_id_t device_id, eth_addr_type_t type,
-    measured_string_t **address)
-{
-	eth_device_t *device;
-
-	if (!address)
-		return EBADMEM;
-
-	if (type == ETH_BROADCAST_ADDR) {
-		*address = eth_globals.broadcast_addr;
-	} else {
+static int eth_addr_message(nic_device_id_t device_id, eth_addr_type_t type)
+{
+	eth_device_t *device = NULL;
+	uint8_t *address;
+	size_t max_len;
+	ipc_callid_t callid;
+	
+	if (type == ETH_BROADCAST_ADDR)
+		address = eth_globals.broadcast_addr;
+	else {
 		fibril_rwlock_read_lock(&eth_globals.devices_lock);
 		device = eth_devices_find(&eth_globals.devices, device_id);
@@ -605,9 +554,30 @@
 			return ENOENT;
 		}
-		*address = device->addr;
+		
+		address = (uint8_t *) &device->addr.address;
+	}
+	
+	int rc = EOK;
+	if (!async_data_read_receive(&callid, &max_len)) {
+		rc = EREFUSED;
+		goto end;
+	}
+	
+	if (max_len < ETH_ADDR) {
+		async_data_read_finalize(callid, NULL, 0);
+		rc = ELIMIT;
+		goto end;
+	}
+	
+	rc = async_data_read_finalize(callid, address, ETH_ADDR);
+	if (rc != EOK)
+		goto end;
+	
+end:
+	
+	if (type == ETH_LOCAL_ADDR)
 		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-	}
-	
-	return (*address) ? EOK : ENOENT;
+	
+	return rc;
 }
 
@@ -697,6 +667,14 @@
 	if (i < 0)
 		return i;
+	
 	if (i != ETH_ADDR)
 		return EINVAL;
+	
+	for (i = 0; i < ETH_ADDR; i++) {
+		if (src[i]) {
+			src_addr = src;
+			break;
+		}
+	}
 
 	length = packet_get_data_length(packet);
@@ -722,5 +700,5 @@
 		memcpy(header_dix->destination_address, dest, ETH_ADDR);
 		src = &header_dix->destination_address[0];
-	} else if(IS_8023_2_LSAP(flags)) {
+	} else if (IS_8023_2_LSAP(flags)) {
 		header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
 		if (!header_lsap)
@@ -735,5 +713,5 @@
 		memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
 		src = &header_lsap->header.destination_address[0];
-	} else if(IS_8023_2_SNAP(flags)) {
+	} else if (IS_8023_2_SNAP(flags)) {
 		header = PACKET_PREFIX(packet, eth_header_snap_t);
 		if (!header)
@@ -746,5 +724,5 @@
 		header->lsap.ctrl = IEEE_8023_2_UI;
 		
-		for (i = 0; i < 3; ++ i)
+		for (i = 0; i < 3; i++)
 			header->snap.protocol[i] = 0;
 		
@@ -760,5 +738,5 @@
 			return ENOMEM;
 		
-		for (i = 0; i < 7; ++ i)
+		for (i = 0; i < 7; i++)
 			preamble->preamble[i] = ETH_PREAMBLE;
 		
@@ -787,5 +765,5 @@
  * @return		EINVAL if the service parameter is not known.
  */
-static int eth_send_message(device_id_t device_id, packet_t *packet,
+static int eth_send_message(nic_device_id_t device_id, packet_t *packet,
     services_t sender)
 {
@@ -813,5 +791,5 @@
 	do {
 		rc = eth_prepare_packet(device->flags, next,
-		    (uint8_t *) device->addr->value, ethertype, device->mtu);
+		    (uint8_t *) &device->addr.address, ethertype, device->mtu);
 		if (rc != EOK) {
 			/* Release invalid packet */
@@ -825,20 +803,61 @@
 			next = pq_next(next);
 		}
-	} while(next);
+	} while (next);
 	
 	/* Send packet queue */
-	if (packet) {
-		netif_send_msg(device->sess, device_id, packet,
-		    SERVICE_ETHERNET);
-	}
-
+	if (packet)
+		nic_send_message(device->sess, packet_get_id(packet));
+	
 	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
 	return EOK;
 }
 
+static int eth_addr_changed(nic_device_id_t device_id)
+{
+	nic_address_t address;
+	size_t length;
+	ipc_callid_t data_callid;
+	if (!async_data_write_receive(&data_callid, &length)) {
+		async_answer_0(data_callid, EINVAL);
+		return EINVAL;
+	}
+	if (length > sizeof (nic_address_t)) {
+		async_answer_0(data_callid, ELIMIT);
+		return ELIMIT;
+	}
+	if (async_data_write_finalize(data_callid, &address, length) != EOK) {
+		return EINVAL;
+	}
+
+	fibril_rwlock_write_lock(&eth_globals.devices_lock);
+	/* An existing device? */
+	eth_device_t *device = eth_devices_find(&eth_globals.devices, device_id);
+	if (device) {
+		printf("Device %d changing address from " PRIMAC " to " PRIMAC "\n",
+			device_id, ARGSMAC(device->addr.address), ARGSMAC(address.address));
+		memcpy(&device->addr, &address, sizeof (nic_address_t));
+		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
+
+		/* Notify all upper layer modules */
+		fibril_rwlock_read_lock(&eth_globals.protos_lock);
+		int index;
+		for (index = 0; index < eth_protos_count(&eth_globals.protos); index++) {
+			eth_proto_t *proto = eth_protos_get_index(&eth_globals.protos, index);
+			if (proto->sess != NULL) {
+				il_addr_changed_msg(proto->sess, device->device_id,
+						ETH_ADDR, address.address);
+			}
+		}
+
+		fibril_rwlock_read_unlock(&eth_globals.protos_lock);
+		return EOK;
+	} else {
+		return ENOENT;
+	}
+}
+
 int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
     ipc_call_t *answer, size_t *answer_count)
 {
-	measured_string_t *address;
 	packet_t *packet;
 	size_t addrlen;
@@ -861,5 +880,5 @@
 	case NET_NIL_DEVICE:
 		return eth_device_message(IPC_GET_DEVICE(*call),
-		    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
+		    IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
 	case NET_NIL_SEND:
 		rc = packet_translate_remote(eth_globals.net_sess, &packet,
@@ -867,4 +886,5 @@
 		if (rc != EOK)
 			return rc;
+		
 		return eth_send_message(IPC_GET_DEVICE(*call), packet,
 		    IPC_GET_SERVICE(*call));
@@ -874,4 +894,5 @@
 		if (rc != EOK)
 			return rc;
+		
 		IPC_SET_ADDR(*answer, addrlen);
 		IPC_SET_PREFIX(*answer, prefix);
@@ -879,17 +900,40 @@
 		IPC_SET_SUFFIX(*answer, suffix);
 		*answer_count = 4;
+		
 		return EOK;
 	case NET_NIL_ADDR:
-		rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR,
-		    &address);
+		rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR);
 		if (rc != EOK)
 			return rc;
-		return measured_strings_reply(address, 1);
+		
+		IPC_SET_ADDR(*answer, ETH_ADDR);
+		*answer_count = 1;
+		
+		return EOK;
 	case NET_NIL_BROADCAST_ADDR:
-		rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR,
-		    &address);
+		rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR);
 		if (rc != EOK)
-			return EOK;
-		return measured_strings_reply(address, 1);
+			return rc;
+		
+		IPC_SET_ADDR(*answer, ETH_ADDR);
+		*answer_count = 1;
+		
+		return EOK;
+	case NET_NIL_DEVICE_STATE:
+		nil_device_state_msg_local(IPC_GET_DEVICE(*call), IPC_GET_STATE(*call));
+		async_answer_0(callid, EOK);
+		return EOK;
+	case NET_NIL_RECEIVED:
+		rc = packet_translate_remote(eth_globals.net_sess, &packet,
+		    IPC_GET_ARG2(*call));
+		if (rc == EOK)
+			rc = nil_received_msg_local(IPC_GET_ARG1(*call), packet);
+		
+		async_answer_0(callid, (sysarg_t) rc);
+		return rc;
+	case NET_NIL_ADDR_CHANGED:
+		rc = eth_addr_changed(IPC_GET_DEVICE(*call));
+		async_answer_0(callid, (sysarg_t) rc);
+		return rc;
 	}
 	
Index: uspace/srv/net/nil/eth/eth.h
===================================================================
--- uspace/srv/net/nil/eth/eth.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/nil/eth/eth.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Radim Vansa
  * All rights reserved.
  *
@@ -43,4 +44,5 @@
 #include <net/device.h>
 #include <adt/measured_strings.h>
+#include <devman.h>
 
 /** Ethernet address length. */
@@ -220,7 +222,7 @@
 struct eth_device {
 	/** Device identifier. */
-	device_id_t device_id;
-	/** Device driver service. */
-	services_t service;
+	nic_device_id_t device_id;
+	/** Device handle */
+	devman_handle_t handle;
 	/** Driver session. */
 	async_sess_t *sess;
@@ -236,8 +238,5 @@
 	
 	/** Actual device hardware address. */
-	measured_string_t *addr;
-	
-	/** Actual device hardware address data. */
-	uint8_t *addr_data;
+	nic_address_t addr;
 };
 
@@ -270,5 +269,5 @@
 	
 	/** Broadcast device hardware address. */
-	measured_string_t *broadcast_addr;
+	uint8_t broadcast_addr[ETH_ADDR];
 };
 
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Radim Vansa
  * All rights reserved.
  *
@@ -36,4 +37,5 @@
  */
 
+#include <assert.h>
 #include <async.h>
 #include <malloc.h>
@@ -50,5 +52,7 @@
 #include <net/packet.h>
 #include <packet_remote.h>
-#include <netif_remote.h>
+#include <packet_client.h>
+#include <devman.h>
+#include <device/nic.h>
 #include <nil_skel.h>
 #include "nildummy.h"
@@ -65,5 +69,5 @@
 DEVICE_MAP_IMPLEMENT(nildummy_devices, nildummy_device_t);
 
-int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
+int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
 {
 	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
@@ -91,42 +95,4 @@
 	
 	return rc;
-}
-
-/** Process IPC messages from the registered device driver modules
- *
- * @param[in]     iid   Message identifier.
- * @param[in,out] icall Message parameters.
- * @param[in]     arg    Local argument.
- *
- */
-static void nildummy_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-	
-	while (true) {
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_NIL_DEVICE_STATE:
-			rc = nil_device_state_msg_local(IPC_GET_DEVICE(*icall),
-			    IPC_GET_STATE(*icall));
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		
-		case NET_NIL_RECEIVED:
-			rc = packet_translate_remote(nildummy_globals.net_sess,
-			    &packet, IPC_GET_PACKET(*icall));
-			if (rc == EOK)
-				rc = nil_received_msg_local(IPC_GET_DEVICE(*icall),
-				    packet, 0);
-			
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		
-		default:
-			async_answer_0(iid, (sysarg_t) ENOTSUP);
-		}
-		
-		iid = async_get_call(icall);
-	}
 }
 
@@ -148,6 +114,6 @@
  *
  */
-static int nildummy_device_message(device_id_t device_id, services_t service,
-    size_t mtu)
+static int nildummy_device_message(nic_device_id_t device_id,
+    devman_handle_t handle, size_t mtu)
 {
 	fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
@@ -157,8 +123,8 @@
 	    nildummy_devices_find(&nildummy_globals.devices, device_id);
 	if (device) {
-		if (device->service != service) {
-			printf("Device %d already exists\n", device->device_id);
-			fibril_rwlock_write_unlock(
-			    &nildummy_globals.devices_lock);
+		if (device->handle != handle) {
+			printf("Device %d exists, handles do not match\n",
+			    device->device_id);
+			fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
 			return EEXIST;
 		}
@@ -170,6 +136,6 @@
 			device->mtu = NET_DEFAULT_MTU;
 		
-		printf("Device %d already exists:\tMTU\t= %zu\n",
-		    device->device_id, device->mtu);
+		printf("Device %d already exists:\tMTU\t= %zu\n", device->device_id,
+		    device->mtu);
 		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
 		
@@ -192,13 +158,13 @@
 	
 	device->device_id = device_id;
-	device->service = service;
+	device->handle = handle;
 	if (mtu > 0)
 		device->mtu = mtu;
 	else
 		device->mtu = NET_DEFAULT_MTU;
-
+	
 	/* Bind the device driver */
-	device->sess = netif_bind_service(device->service, device->device_id,
-	    SERVICE_ETHERNET, nildummy_receiver);
+	device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
+	    IPC_FLAG_BLOCKING);
 	if (device->sess == NULL) {
 		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
@@ -207,7 +173,8 @@
 	}
 	
+	nic_connect_to_nil(device->sess, SERVICE_NILDUMMY, device_id);
+	
 	/* Get hardware address */
-	int rc = netif_get_addr_req(device->sess, device->device_id,
-	    &device->addr, &device->addr_data);
+	int rc = nic_get_address(device->sess, &device->addr);
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
@@ -215,4 +182,6 @@
 		return rc;
 	}
+	
+	device->addr_len = ETH_ADDR;
 	
 	/* Add to the cache */
@@ -221,12 +190,10 @@
 	if (index < 0) {
 		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-		free(device->addr);
-		free(device->addr_data);
 		free(device);
 		return index;
 	}
 	
-	printf("%s: Device registered (id: %d, service: %d, mtu: %zu)\n",
-	    NAME, device->device_id, device->service, device->mtu);
+	printf("%s: Device registered (id: %d, mtu: %zu)\n", NAME,
+	    device->device_id, device->mtu);
 	fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
 	return EOK;
@@ -243,8 +210,7 @@
  *
  */
-static int nildummy_addr_message(device_id_t device_id,
-    measured_string_t **address)
-{
-	if (!address)
+static int nildummy_addr_message(nic_device_id_t device_id, size_t *addrlen)
+{
+	if (!addrlen)
 		return EBADMEM;
 	
@@ -258,9 +224,28 @@
 	}
 	
-	*address = device->addr;
+	ipc_callid_t callid;
+	size_t max_len;
+	if (!async_data_read_receive(&callid, &max_len)) {
+		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
+		return EREFUSED;
+	}
+	
+	if (max_len < device->addr_len) {
+		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
+		async_data_read_finalize(callid, NULL, 0);
+		return ELIMIT;
+	}
+	
+	int rc = async_data_read_finalize(callid,
+	    (uint8_t *) &device->addr.address, device->addr_len);
+	if (rc != EOK) {
+		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
+		return rc;
+	}
+	
+	*addrlen = device->addr_len;
 	
 	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-	
-	return (*address) ? EOK : ENOENT;
+	return EOK;
 }
 
@@ -278,6 +263,6 @@
  *
  */
-static int nildummy_packet_space_message(device_id_t device_id, size_t *addr_len,
-    size_t *prefix, size_t *content, size_t *suffix)
+static int nildummy_packet_space_message(nic_device_id_t device_id,
+    size_t *addr_len, size_t *prefix, size_t *content, size_t *suffix)
 {
 	if ((!addr_len) || (!prefix) || (!content) || (!suffix))
@@ -303,6 +288,5 @@
 }
 
-int nil_received_msg_local(device_id_t device_id, packet_t *packet,
-    services_t target)
+int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
 {
 	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
@@ -358,5 +342,5 @@
  *
  */
-static int nildummy_send_message(device_id_t device_id, packet_t *packet,
+static int nildummy_send_message(nic_device_id_t device_id, packet_t *packet,
     services_t sender)
 {
@@ -372,6 +356,5 @@
 	/* Send packet queue */
 	if (packet)
-		netif_send_msg(device->sess, device_id, packet,
-		    SERVICE_NILDUMMY);
+		nic_send_message(device->sess, packet_get_id(packet));
 	
 	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
@@ -383,5 +366,4 @@
     ipc_call_t *answer, size_t *answer_count)
 {
-	measured_string_t *address;
 	packet_t *packet;
 	size_t addrlen;
@@ -404,5 +386,5 @@
 	case NET_NIL_DEVICE:
 		return nildummy_device_message(IPC_GET_DEVICE(*call),
-		    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
+		    IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
 	
 	case NET_NIL_SEND:
@@ -427,14 +409,26 @@
 	
 	case NET_NIL_ADDR:
-		rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &address);
+	case NET_NIL_BROADCAST_ADDR:
+		rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &addrlen);
 		if (rc != EOK)
 			return rc;
-		return measured_strings_reply(address, 1);
-	
-	case NET_NIL_BROADCAST_ADDR:
-		rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &address);
-		if (rc != EOK)
-			return rc;
-		return measured_strings_reply(address, 1);
+		
+		IPC_SET_ADDR(*answer, addrlen);
+		*answer_count = 1;
+		return rc;
+	case NET_NIL_DEVICE_STATE:
+		rc = nil_device_state_msg_local(IPC_GET_DEVICE(*call),
+		    IPC_GET_STATE(*call));
+		async_answer_0(callid, (sysarg_t) rc);
+		return rc;
+	
+	case NET_NIL_RECEIVED:
+		rc = packet_translate_remote(nildummy_globals.net_sess, &packet,
+		    IPC_GET_ARG2(*call));
+		if (rc == EOK)
+			rc = nil_received_msg_local(IPC_GET_ARG1(*call), packet);
+		
+		async_answer_0(callid, (sysarg_t) rc);
+		return rc;
 	}
 	
Index: uspace/srv/net/nil/nildummy/nildummy.h
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/nil/nildummy/nildummy.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Radim Vansa
  * All rights reserved.
  *
@@ -41,4 +42,5 @@
 #include <fibril_synch.h>
 #include <ipc/services.h>
+#include <ipc/devman.h>
 #include <net/device.h>
 #include <adt/measured_strings.h>
@@ -76,9 +78,7 @@
 struct nildummy_device {
 	/** Device identifier. */
-	device_id_t device_id;
-	
-	/** Device driver service. */
-	services_t service;
-	
+	nic_device_id_t device_id;
+	/** Device driver handle. */
+	devman_handle_t handle;
 	/** Driver session. */
 	async_sess_t *sess;
@@ -88,8 +88,7 @@
 	
 	/** Actual device hardware address. */
-	measured_string_t *addr;
-	
-	/** Actual device hardware address data. */
-	uint8_t *addr_data;
+	nic_address_t addr;
+	/** Actual device hardware address length. */
+	size_t addr_len;
 };
 
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -169,5 +169,5 @@
 static int tcp_release_after_timeout(void *);
 
-static int tcp_process_packet(device_id_t, packet_t *, services_t);
+static int tcp_process_packet(nic_device_id_t, packet_t *, services_t);
 static int tcp_connect_core(socket_core_t *, socket_cores_t *,
     struct sockaddr *, socklen_t);
@@ -177,5 +177,5 @@
     size_t);
 static packet_t *tcp_get_packets_to_send(socket_core_t *, tcp_socket_data_t *);
-static void tcp_send_packets(device_id_t, packet_t *);
+static void tcp_send_packets(nic_device_id_t, packet_t *);
 
 static void tcp_process_acknowledgement(socket_core_t *, tcp_socket_data_t *,
@@ -205,5 +205,5 @@
 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);
+static int tcp_received_msg(nic_device_id_t, packet_t *, services_t, services_t);
 static int tcp_process_client_messages(async_sess_t *, ipc_callid_t,
     ipc_call_t);
@@ -220,5 +220,5 @@
 tcp_globals_t tcp_globals;
 
-int tcp_received_msg(device_id_t device_id, packet_t *packet,
+int tcp_received_msg(nic_device_id_t device_id, packet_t *packet,
     services_t receiver, services_t error)
 {
@@ -238,5 +238,5 @@
 }
 
-int tcp_process_packet(device_id_t device_id, packet_t *packet, services_t error)
+int tcp_process_packet(nic_device_id_t device_id, packet_t *packet, services_t error)
 {
 	size_t length;
@@ -1251,5 +1251,5 @@
 	bzero(socket_data, sizeof(*socket_data));
 	socket_data->state = TCP_SOCKET_INITIAL;
-	socket_data->device_id = DEVICE_INVALID_ID;
+	socket_data->device_id = NIC_DEVICE_INVALID_ID;
 	socket_data->window = NET_DEFAULT_TCP_WINDOW;
 	socket_data->treshold = socket_data->window;
@@ -1335,5 +1335,5 @@
 			}
 			if (tl_get_ip_packet_dimension(tcp_globals.ip_sess,
-			    &tcp_globals.dimensions, DEVICE_INVALID_ID,
+			    &tcp_globals.dimensions, NIC_DEVICE_INVALID_ID,
 			    &packet_dimension) == EOK) {
 				SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
@@ -1651,5 +1651,5 @@
 	/* Sent packet? */
 	packet = pq_find(socket_data->outgoing, sequence_number);
-	printf("retransmit %d\n", packet_get_id(packet));
+	printf("retransmit %lu\n", packet_get_id(packet));
 	if (packet) {
 		pq_get_order(packet, NULL, &data_length);
@@ -1790,5 +1790,5 @@
 
 			/* Send the packet */
-			printf("connecting %d\n", packet_get_id(packet));
+			printf("connecting %lu\n", packet_get_id(packet));
 			tcp_send_packets(socket_data->device_id, packet);
 
@@ -2004,5 +2004,5 @@
 }
 
-void tcp_send_packets(device_id_t device_id, packet_t *packet)
+void tcp_send_packets(nic_device_id_t device_id, packet_t *packet)
 {
 	packet_t *next;
Index: uspace/srv/net/tl/tcp/tcp.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp.h	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/tl/tcp/tcp.h	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -182,5 +182,5 @@
 	
 	/** Device identifier. */
-	device_id_t device_id;
+	nic_device_id_t device_id;
 	
 	/**
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision f51b1d33aaf46c98cee9c0ec13e8521a70b8616d)
+++ uspace/srv/net/tl/udp/udp.c	(revision 609243f4f1d6e7562d9c9b79e38925b36e844ac0)
@@ -124,5 +124,5 @@
  *			ip_client_process_packet() function.
  */
-static int udp_process_packet(device_id_t device_id, packet_t *packet,
+static int udp_process_packet(nic_device_id_t device_id, packet_t *packet,
     services_t error)
 {
@@ -322,5 +322,5 @@
  *			udp_process_packet() function.
  */
-static int udp_received_msg(device_id_t device_id, packet_t *packet,
+static int udp_received_msg(nic_device_id_t device_id, packet_t *packet,
     services_t receiver, services_t error)
 {
@@ -499,5 +499,5 @@
 	void *ip_header;
 	size_t headerlen;
-	device_id_t device_id;
+	nic_device_id_t device_id;
 	packet_dimension_t *packet_dimension;
 	size_t size;
@@ -617,7 +617,6 @@
 		    htons(flip_checksum(compact_checksum(checksum)));
 		free(ip_header);
-	} else {
-		device_id = DEVICE_INVALID_ID;
-	}
+	} else
+		device_id = NIC_DEVICE_INVALID_ID;
 
 	/* Prepare the first packet fragment */
@@ -806,5 +805,5 @@
 			size = MAX_UDP_FRAGMENT_SIZE;
 			if (tl_get_ip_packet_dimension(udp_globals.ip_sess,
-			    &udp_globals.dimensions, DEVICE_INVALID_ID,
+			    &udp_globals.dimensions, NIC_DEVICE_INVALID_ID,
 			    &packet_dimension) == EOK) {
 				if (packet_dimension->content < size)
