Index: boot/Makefile.grub
===================================================================
--- boot/Makefile.grub	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ boot/Makefile.grub	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -52,8 +52,8 @@
 $(BOOT_OUTPUT): build_dist
 ifeq ($(GRUB_ARCH),pc)
-	$(GENISOIMAGE) -J -r -input-charset utf-8 -V "HelenOS boot ISO" -eltorito-boot $(ELTORITO) -no-emul-boot -boot-load-size 64 -boot-info-table -o $@ $(DISTROOT)/
+	mkisofs -J -r -input-charset utf-8 -V "HelenOS boot ISO" -eltorito-boot $(ELTORITO) -no-emul-boot -boot-load-size 64 -boot-info-table -o $@ $(DISTROOT)/
 endif
 ifeq ($(GRUB_ARCH),efi)
-	$(GENISOIMAGE) -J -r -input-charset utf-8 -V "HelenOS boot ISO" -efi-boot $(ELTORITO) -o $@ $(DISTROOT)/
+	mkisofs -J -r -input-charset utf-8 -V "HelenOS boot ISO" -efi-boot $(ELTORITO) -o $@ $(DISTROOT)/
 endif
 
Index: boot/Makefile.silo
===================================================================
--- boot/Makefile.silo	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ boot/Makefile.silo	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -41,5 +41,5 @@
 
 $(POST_OUTPUT): build_dist
-	$(GENISOIMAGE) -f -G $(ISOFS_B_IN) -B ... -r -o $@ $(DISTROOT)/
+	mkisofs -f -G $(ISOFS_B_IN) -B ... -r -o $@ $(DISTROOT)/
 
 build_dist: clean
Index: boot/Makefile.yaboot
===================================================================
--- boot/Makefile.yaboot	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ boot/Makefile.yaboot	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -40,5 +40,5 @@
 
 $(POST_OUTPUT): build_dist
-	$(GENISOIMAGE) -hfs -part -map $(MAPS) -no-desktop -hfs-volid "HelenOS" -hfs-bless $(DISTROOT)/boot -r -o $@ $(DISTROOT)/
+	mkisofs -hfs -part -map $(MAPS) -no-desktop -hfs-volid "HelenOS" -hfs-bless $(DISTROOT)/boot -r -o $@ $(DISTROOT)/
 
 build_dist: clean
Index: kernel/arch/abs32le/src/abs32le.c
===================================================================
--- kernel/arch/abs32le/src/abs32le.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ kernel/arch/abs32le/src/abs32le.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -49,4 +49,5 @@
 #include <syscall/syscall.h>
 #include <console/console.h>
+#include <sysinfo/sysinfo.h>
 #include <memstr.h>
 
Index: kernel/arch/amd64/include/interrupt.h
===================================================================
--- kernel/arch/amd64/include/interrupt.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ kernel/arch/amd64/include/interrupt.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -55,4 +55,5 @@
 #define IRQ_PIC_SPUR  7
 #define IRQ_MOUSE     12
+#define IRQ_NE2000    9
 
 /* This one must have four least significant bits set to ones */
Index: kernel/arch/amd64/src/amd64.c
===================================================================
--- kernel/arch/amd64/src/amd64.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ kernel/arch/amd64/src/amd64.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -214,8 +214,22 @@
 		}
 	}
+	
+	/*
+	 * This is the necessary evil until the userspace driver is entirely
+	 * self-sufficient.
+	 */
+	sysinfo_set_item_val("i8042", NULL, true);
+	sysinfo_set_item_val("i8042.inr_a", NULL, IRQ_KBD);
+	sysinfo_set_item_val("i8042.inr_b", NULL, IRQ_MOUSE);
+	sysinfo_set_item_val("i8042.address.physical", NULL,
+	    (uintptr_t) I8042_BASE);
+	sysinfo_set_item_val("i8042.address.kernel", NULL,
+	    (uintptr_t) I8042_BASE);
 #endif
 	
 	if (irqs_info != NULL)
 		sysinfo_set_item_val(irqs_info, NULL, true);
+	
+	sysinfo_set_item_val("netif.ne2000.inr", NULL, IRQ_NE2000);
 }
 
Index: kernel/arch/arm32/src/arm32.c
===================================================================
--- kernel/arch/arm32/src/arm32.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ kernel/arch/arm32/src/arm32.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -38,4 +38,5 @@
 #include <genarch/fb/fb.h>
 #include <abi/fb/visuals.h>
+#include <sysinfo/sysinfo.h>
 #include <console/console.h>
 #include <ddi/irq.h>
Index: kernel/arch/ia32/include/interrupt.h
===================================================================
--- kernel/arch/ia32/include/interrupt.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ kernel/arch/ia32/include/interrupt.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -55,4 +55,5 @@
 #define IRQ_PIC_SPUR  7
 #define IRQ_MOUSE     12
+#define IRQ_NE2000    5
 
 /* This one must have four least significant bits set to ones */
Index: kernel/arch/ia32/src/ia32.c
===================================================================
--- kernel/arch/ia32/src/ia32.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ kernel/arch/ia32/src/ia32.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -168,8 +168,22 @@
 		}
 	}
+	
+	/*
+	 * This is the necessary evil until the userspace driver is entirely
+	 * self-sufficient.
+	 */
+	sysinfo_set_item_val("i8042", NULL, true);
+	sysinfo_set_item_val("i8042.inr_a", NULL, IRQ_KBD);
+	sysinfo_set_item_val("i8042.inr_b", NULL, IRQ_MOUSE);
+	sysinfo_set_item_val("i8042.address.physical", NULL,
+	    (uintptr_t) I8042_BASE);
+	sysinfo_set_item_val("i8042.address.kernel", NULL,
+	    (uintptr_t) I8042_BASE);
 #endif
 	
 	if (irqs_info != NULL)
 		sysinfo_set_item_val(irqs_info, NULL, true);
+	
+	sysinfo_set_item_val("netif.ne2000.inr", NULL, IRQ_NE2000);
 }
 
Index: kernel/arch/ia32/src/mm/frame.c
===================================================================
--- kernel/arch/ia32/src/mm/frame.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ kernel/arch/ia32/src/mm/frame.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -46,6 +46,4 @@
 #include <print.h>
 
-#define PHYSMEM_LIMIT32  UINT64_C(0x100000000)
-
 size_t hardcoded_unmapped_ktext_size = 0;
 size_t hardcoded_unmapped_kdata_size = 0;
@@ -58,16 +56,15 @@
 		uint64_t base64 = e820table[i].base_address;
 		uint64_t size64 = e820table[i].size;
-		
+
 #ifdef KARCH_ia32
 		/*
 		 * Restrict the e820 table entries to 32-bits.
 		 */
-		if (base64 >= PHYSMEM_LIMIT32)
+		if (base64 >= 0x100000000ULL)
 			continue;
-		
-		if (base64 + size64 > PHYSMEM_LIMIT32)
-			size64 = PHYSMEM_LIMIT32 - base64;
+		if (base64 + size64 > 0x100000000ULL)
+			size64 -= base64 + size64 - 0x100000000ULL;
 #endif
-		
+
 		uintptr_t base = (uintptr_t) base64;
 		size_t size = (size_t) size64;
Index: kernel/arch/ia64/include/interrupt.h
===================================================================
--- kernel/arch/ia64/include/interrupt.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ kernel/arch/ia64/include/interrupt.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -61,4 +61,5 @@
 #define IRQ_KBD    (0x01 + LEGACY_INTERRUPT_BASE)
 #define IRQ_MOUSE  (0x0c + LEGACY_INTERRUPT_BASE)
+#define IRQ_NE2000 (0x09 + LEGACY_INTERRUPT_BASE)
 
 /** General Exception codes. */
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ kernel/arch/ia64/src/ia64.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -127,6 +127,5 @@
 }
 
-void arch_post_cpu_init(void)
-{
+void arch_post_cpu_init(void){
 }
 
@@ -193,6 +192,5 @@
 	
 #ifdef CONFIG_I8042
-	i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE,
-	    IRQ_KBD);
+	i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
 	if (i8042_instance) {
 		kbrd_instance_t *kbrd_instance = kbrd_init();
@@ -203,6 +201,16 @@
 		}
 	}
-#endif
-	
+	
+	sysinfo_set_item_val("i8042", NULL, true);
+	sysinfo_set_item_val("i8042.inr_a", NULL, IRQ_KBD);
+	sysinfo_set_item_val("i8042.inr_b", NULL, IRQ_MOUSE);
+	sysinfo_set_item_val("i8042.address.physical", NULL,
+	    (uintptr_t) I8042_BASE);
+	sysinfo_set_item_val("i8042.address.kernel", NULL,
+	    (uintptr_t) I8042_BASE);
+#endif
+
+	sysinfo_set_item_val("netif.ne2000.inr", NULL, IRQ_NE2000);
+
 	sysinfo_set_item_val("ia64_iospace", NULL, true);
 	sysinfo_set_item_val("ia64_iospace.address", NULL, true);
Index: tools/autotool.py
===================================================================
--- tools/autotool.py	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ tools/autotool.py	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -184,37 +184,4 @@
 	sys.stderr.write("ok\n")
 
-def check_app_alternatives(alts, args, name, details):
-	"Check whether an application can be executed (use several alternatives)"
-	
-	tried = []
-	found = None
-	
-	for alt in alts:
-		working = True
-		cmdline = [alt] + args
-		tried.append(" ".join(cmdline))
-		
-		try:
-			sys.stderr.write("Checking for %s ... " % alt)
-			subprocess.Popen(cmdline, stdout = subprocess.PIPE, stderr = subprocess.PIPE).wait()
-		except:
-			sys.stderr.write("failed\n")
-			working = False
-		
-		if (working):
-			sys.stderr.write("ok\n")
-			found = alt
-			break
-	
-	if (found is None):
-		print_error(["%s is missing." % name,
-		             "",
-		             "Please make sure that it is installed in your",
-		             "system (%s)." % details,
-		             "",
-		             "The following alternatives were tried:"] + tried)
-	
-	return found
-
 def check_gcc(path, prefix, common, details):
 	"Check for GCC"
@@ -492,8 +459,5 @@
 	
 	for key, value in common.items():
-		if (type(value) is list):
-			outmk.write('%s = %s\n' % (key, " ".join(value)))
-		else:
-			outmk.write('%s = %s\n' % (key, value))
+		outmk.write('%s = %s\n' % (key, value))
 	
 	outmk.close()
@@ -660,5 +624,5 @@
 		# Platform-specific utilities
 		if ((config['BARCH'] == "amd64") or (config['BARCH'] == "ia32") or (config['BARCH'] == "ppc32") or (config['BARCH'] == "sparc64")):
-			common['GENISOIMAGE'] = check_app_alternatives(["mkisofs", "genisoimage"], ["--version"], "ISO 9660 creation utility", "usually part of genisoimage")
+			check_app(["mkisofs", "--version"], "ISO 9660 creation utility", "usually part of genisoimage")
 		
 		probe = probe_compiler(common,
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/app/trace/trace.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -623,4 +623,5 @@
 error:
 	loader_abort(ldr);
+	free(ldr);
 	return NULL;
 }
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/bus/isa/isa.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -401,5 +401,5 @@
 
 	val = skip_spaces(val);
-	irq = (int) strtol(val, &end, 10);
+	irq = (int)strtol(val, &end, 10);
 
 	if (val != end)
Index: uspace/drv/bus/isa/isa.dev
===================================================================
--- uspace/drv/bus/isa/isa.dev	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/bus/isa/isa.dev	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -14,4 +14,5 @@
 	irq 12
 	io_range 060 5
+	
 
 ne2k:
Index: uspace/drv/bus/isa/isa.ma
===================================================================
--- uspace/drv/bus/isa/isa.ma	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/bus/isa/isa.ma	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -1,1 +1,1 @@
-9 pci/class=06&subclass=01
+9 pci/ven=8086&dev=7000
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -92,5 +92,5 @@
 static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
 {
-	/* This is an old ugly way */
+	/* This is an old ugly way, copied from ne2000 driver */
 	assert(fnode);
 	pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -167,5 +167,5 @@
 	return result;
 }
-
+/*----------------------------------------------------------------------------*/
 static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev,
     usb_mouse_t *mouse_dev)
@@ -305,5 +305,5 @@
 	return EOK;
 }
-
+/*----------------------------------------------------------------------------*/
 /** Get highest index of a button mentioned in given report.
  *
Index: uspace/drv/char/i8042/buffer.h
===================================================================
--- uspace/drv/char/i8042/buffer.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/char/i8042/buffer.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -26,10 +26,8 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /**
  * @addtogroup kbd
  * @{
  */
-
 /** @file
  * @brief Cyclic buffer structure.
@@ -48,26 +46,22 @@
  * Attempt to insert byte into the full buffer will block until it can succeed.
  * Attempt to read from empty buffer will block until it can succeed.
- *
  */
 typedef struct {
-	uint8_t *buffer;          /**< Storage space. */
-	uint8_t *buffer_end;      /**< End of storage place. */
-	fibril_mutex_t guard;     /**< Protects buffer structures. */
-	fibril_condvar_t change;  /**< Indicates change (empty/full). */
-	uint8_t *read_head;       /**< Place of the next readable element. */
-	uint8_t *write_head;      /**< Pointer to the next writable place. */
+	uint8_t *buffer;         /**< Storage space. */
+	uint8_t *buffer_end;     /**< End of storage place. */
+	fibril_mutex_t guard;    /**< Protects buffer structures. */
+	fibril_condvar_t change; /**< Indicates change (empty/full). */
+	uint8_t *read_head;      /**< Place of the next readable element. */
+	uint8_t *write_head;     /**< Pointer to the next writable place. */
 } buffer_t;
 
 /** Initialize cyclic buffer using provided memory space.
- *
  * @param buffer Cyclic buffer structure to initialize.
- * @param data   Memory space to use.
- * @param size   Size of the memory place.
- *
+ * @param data Memory space to use.
+ * @param size Size of the memory place.
  */
 static inline void buffer_init(buffer_t *buffer, uint8_t *data, size_t size)
 {
 	assert(buffer);
-	
 	fibril_mutex_initialize(&buffer->guard);
 	fibril_condvar_initialize(&buffer->change);
@@ -80,29 +74,27 @@
 
 /** Write byte to cyclic buffer.
- *
  * @param buffer Cyclic buffer to write to.
- * @param data   Data to write.
- *
+ * @param data Data to write.
  */
 static inline void buffer_write(buffer_t *buffer, uint8_t data)
 {
 	fibril_mutex_lock(&buffer->guard);
-	
+
 	/* Next position. */
 	uint8_t *new_head = buffer->write_head + 1;
 	if (new_head == buffer->buffer_end)
 		new_head = buffer->buffer;
-	
+
 	/* Buffer full. */
 	while (new_head == buffer->read_head)
 		fibril_condvar_wait(&buffer->change, &buffer->guard);
-	
+
 	/* Write data. */
 	*buffer->write_head = data;
-	
+
 	/* Buffer was empty. */
 	if (buffer->write_head == buffer->read_head)
 		fibril_condvar_broadcast(&buffer->change);
-	
+
 	/* Move head */
 	buffer->write_head = new_head;
@@ -111,26 +103,22 @@
 
 /** Read byte from cyclic buffer.
- *
  * @param buffer Cyclic buffer to read from.
- *
  * @return Byte read.
- *
  */
 static inline uint8_t buffer_read(buffer_t *buffer)
 {
 	fibril_mutex_lock(&buffer->guard);
-	
 	/* Buffer is empty. */
 	while (buffer->write_head == buffer->read_head)
 		fibril_condvar_wait(&buffer->change, &buffer->guard);
-	
+
 	/* Next position. */
 	uint8_t *new_head = buffer->read_head + 1;
 	if (new_head == buffer->buffer_end)
 		new_head = buffer->buffer;
-	
+
 	/* Read data. */
 	const uint8_t data = *buffer->read_head;
-	
+
 	/* Buffer was full. */
 	uint8_t *new_write_head = buffer->write_head + 1;
@@ -139,14 +127,12 @@
 	if (new_write_head == buffer->read_head)
 		fibril_condvar_broadcast(&buffer->change);
-	
+
 	/* Move head */
 	buffer->read_head = new_head;
-	
+
 	fibril_mutex_unlock(&buffer->guard);
 	return data;
 }
-
 #endif
-
 /**
  * @}
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/char/i8042/i8042.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -29,10 +29,8 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup kbd_port
  * @ingroup kbd
  * @{
  */
-
 /** @file
  * @brief i8042 PS/2 port driver.
@@ -46,55 +44,11 @@
 #include <str_error.h>
 #include <inttypes.h>
+
 #include <ddf/log.h>
 #include <ddf/interrupt.h>
+
 #include "i8042.h"
 
-/* Interesting bits for status register */
-#define i8042_OUTPUT_FULL  0x01
-#define i8042_INPUT_FULL   0x02
-#define i8042_AUX_DATA     0x20
-
-/* Command constants */
-#define i8042_CMD_WRITE_CMDB  0x60  /**< Write command byte */
-#define i8042_CMD_WRITE_AUX   0xd4  /**< Write aux device */
-
-/* Command byte fields */
-#define i8042_KBD_IE         0x01
-#define i8042_AUX_IE         0x02
-#define i8042_KBD_DISABLE    0x10
-#define i8042_AUX_DISABLE    0x20
-#define i8042_KBD_TRANSLATE  0x40  /* Use this to switch to XT scancodes */
-
-#define CHECK_RET_DESTROY(ret, msg...) \
-	do { \
-		if (ret != EOK) { \
-			ddf_msg(LVL_ERROR, msg); \
-			if (dev->kbd_fun) { \
-				dev->kbd_fun->driver_data = NULL; \
-				ddf_fun_destroy(dev->kbd_fun); \
-			} \
-			if (dev->aux_fun) { \
-				dev->aux_fun->driver_data = NULL; \
-				ddf_fun_destroy(dev->aux_fun); \
-			} \
-		} \
-	} while (0)
-
-#define CHECK_RET_UNBIND_DESTROY(ret, msg...) \
-	do { \
-		if (ret != EOK) { \
-			ddf_msg(LVL_ERROR, msg); \
-			if (dev->kbd_fun) { \
-				ddf_fun_unbind(dev->kbd_fun); \
-				dev->kbd_fun->driver_data = NULL; \
-				ddf_fun_destroy(dev->kbd_fun); \
-			} \
-			if (dev->aux_fun) { \
-				ddf_fun_unbind(dev->aux_fun); \
-				dev->aux_fun->driver_data = NULL; \
-				ddf_fun_destroy(dev->aux_fun); \
-			} \
-		} \
-	} while (0)
+#define NAME       "i8042"
 
 void default_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
@@ -105,9 +59,25 @@
 };
 
+/* Interesting bits for status register */
+#define i8042_OUTPUT_FULL	0x01
+#define i8042_INPUT_FULL	0x02
+#define i8042_AUX_DATA		0x20
+
+/* Command constants */
+#define i8042_CMD_WRITE_CMDB	0x60	/**< write command byte */
+#define i8042_CMD_WRITE_AUX	0xd4	/**< write aux device */
+
+/* Command byte fields */
+#define i8042_KBD_IE		0x01
+#define i8042_AUX_IE		0x02
+#define i8042_KBD_DISABLE	0x10
+#define i8042_AUX_DISABLE	0x20
+#define i8042_KBD_TRANSLATE	0x40 /* Use this to switch to XT scancodes */
+
 /** i8042 Interrupt pseudo-code. */
 static const irq_cmd_t i8042_cmds[] = {
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,  /* will be patched in run-time */
+		.addr = NULL,	/* will be patched in run-time */
 		.dstarg = 1
 	},
@@ -125,5 +95,5 @@
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,  /* will be patched in run-time */
+		.addr = NULL,	/* will be patched in run-time */
 		.dstarg = 2
 	},
@@ -141,40 +111,31 @@
 
 /** Interrupt handler routine.
- *
- * Write new data to the corresponding buffer.
- *
- * @param dev  Device that caued the interrupt.
- * @param iid  Call id.
+ * Writes new data to the corresponding buffer.
+ * @param dev Device that caued the interrupt.
+ * @param iid Call id.
  * @param call pointerr to call data.
- *
- */
-static void i8042_irq_handler(ddf_dev_t *dev, ipc_callid_t iid,
-    ipc_call_t *call)
-{
-	if ((!dev) || (!dev->driver_data))
+ */
+static void i8042_irq_handler(
+    ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	if (!dev || !dev->driver_data)
 		return;
-	
 	i8042_t *controller = dev->driver_data;
-	
+
 	const uint8_t status = IPC_GET_ARG1(*call);
 	const uint8_t data = IPC_GET_ARG2(*call);
-	
 	buffer_t *buffer = (status & i8042_AUX_DATA) ?
 	    &controller->aux_buffer : &controller->kbd_buffer;
-	
 	buffer_write(buffer, data);
 }
 
 /** Initialize i8042 driver structure.
- *
- * @param dev       Driver structure to initialize.
- * @param regs      I/O address of registers.
- * @param reg_size  size of the reserved I/O address space.
- * @param irq_kbd   IRQ for primary port.
+ * @param dev Driver structure to initialize.
+ * @param regs I/O address of registers.
+ * @param reg_size size of the reserved I/O address space.
+ * @param irq_kbd IRQ for primary port.
  * @param irq_mouse IRQ for aux port.
- * @param ddf_dev   DDF device structure of the device.
- *
+ * @param ddf_dev DDF device structure of the device.
  * @return Error code.
- *
  */
 int i8042_init(i8042_t *dev, void *regs, size_t reg_size, int irq_kbd,
@@ -183,15 +144,14 @@
 	assert(ddf_dev);
 	assert(dev);
-	
+
 	if (reg_size < sizeof(i8042_regs_t))
 		return EINVAL;
-	
-	if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0)
+
+	if (pio_enable(regs, sizeof(i8042_regs_t), (void**)&dev->regs) != 0)
 		return -1;
-	
+
 	dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
 	if (!dev->kbd_fun)
 		return ENOMEM;
-	
 	int ret = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
 	if (ret != EOK) {
@@ -199,5 +159,5 @@
 		return ret;
 	}
-	
+
 	dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
 	if (!dev->aux_fun) {
@@ -205,5 +165,5 @@
 		return ENOMEM;
 	}
-	
+
 	ret = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
 	if (ret != EOK) {
@@ -212,22 +172,35 @@
 		return ret;
 	}
-	
+
 	dev->kbd_fun->ops = &ops;
 	dev->aux_fun->ops = &ops;
 	dev->kbd_fun->driver_data = dev;
 	dev->aux_fun->driver_data = dev;
-	
+
 	buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
 	buffer_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE);
 	fibril_mutex_initialize(&dev->write_guard);
-	
+
+#define CHECK_RET_DESTROY(ret, msg...) \
+if  (ret != EOK) { \
+	ddf_msg(LVL_ERROR, msg); \
+	if (dev->kbd_fun) { \
+		dev->kbd_fun->driver_data = NULL; \
+		ddf_fun_destroy(dev->kbd_fun); \
+	} \
+	if (dev->aux_fun) { \
+		dev->aux_fun->driver_data = NULL; \
+		ddf_fun_destroy(dev->aux_fun); \
+	} \
+} else (void)0
+
 	ret = ddf_fun_bind(dev->kbd_fun);
-	CHECK_RET_DESTROY(ret, "Failed to bind keyboard function: %s.",
-	    str_error(ret));
-	
+	CHECK_RET_DESTROY(ret,
+	    "Failed to bind keyboard function: %s.", str_error(ret));
+
 	ret = ddf_fun_bind(dev->aux_fun);
-	CHECK_RET_DESTROY(ret, "Failed to bind mouse function: %s.",
-	    str_error(ret));
-	
+	CHECK_RET_DESTROY(ret,
+	    "Failed to bind mouse function: %s.", str_error(ret));
+
 	/* Disable kbd and aux */
 	wait_ready(dev);
@@ -235,9 +208,24 @@
 	wait_ready(dev);
 	pio_write_8(&dev->regs->data, i8042_KBD_DISABLE | i8042_AUX_DISABLE);
-	
+
 	/* Flush all current IO */
 	while (pio_read_8(&dev->regs->status) & i8042_OUTPUT_FULL)
 		(void) pio_read_8(&dev->regs->data);
-	
+
+#define CHECK_RET_UNBIND_DESTROY(ret, msg...) \
+if  (ret != EOK) { \
+	ddf_msg(LVL_ERROR, msg); \
+	if (dev->kbd_fun) { \
+		ddf_fun_unbind(dev->kbd_fun); \
+		dev->kbd_fun->driver_data = NULL; \
+		ddf_fun_destroy(dev->kbd_fun); \
+	} \
+	if (dev->aux_fun) { \
+		ddf_fun_unbind(dev->aux_fun); \
+		dev->aux_fun->driver_data = NULL; \
+		ddf_fun_destroy(dev->aux_fun); \
+	} \
+} else (void)0
+
 	const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
 	irq_cmd_t cmds[cmd_count];
@@ -245,20 +233,16 @@
 	cmds[0].addr = (void *) &dev->regs->status;
 	cmds[3].addr = (void *) &dev->regs->data;
-	
-	irq_code_t irq_code = {
-		.cmdcount = cmd_count,
-		.cmds = cmds
-	};
-	
+
+	irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = cmds };
 	ret = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
 	    &irq_code);
-	CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for kbd: %s.",
-	    str_error(ret));
-	
+	CHECK_RET_UNBIND_DESTROY(ret,
+	    "Failed set handler for kbd: %s.", str_error(ret));
+
 	ret = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
 	    &irq_code);
-	CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for mouse: %s.",
-	    str_error(ret));
-	
+	CHECK_RET_UNBIND_DESTROY(ret,
+	    "Failed set handler for mouse: %s.", str_error(ret));
+
 	/* Enable interrupts */
 	async_sess_t *parent_sess =
@@ -267,10 +251,10 @@
 	ret = parent_sess ? EOK : ENOMEM;
 	CHECK_RET_UNBIND_DESTROY(ret, "Failed to create parent connection.");
-	
+
 	const bool enabled = hw_res_enable_interrupt(parent_sess);
 	async_hangup(parent_sess);
 	ret = enabled ? EOK : EIO;
 	CHECK_RET_UNBIND_DESTROY(ret, "Failed to enable interrupts: %s.");
-	
+
 	/* Enable port interrupts. */
 	wait_ready(dev);
@@ -279,9 +263,9 @@
 	pio_write_8(&dev->regs->data, i8042_KBD_IE | i8042_KBD_TRANSLATE |
 	    i8042_AUX_IE);
-	
+
 	return EOK;
 }
 
-// FIXME TODO use shared instead this
+// TODO use shared instead this
 enum {
 	IPC_CHAR_READ = DEV_FIRST_CUSTOM_METHOD,
@@ -290,11 +274,8 @@
 
 /** Write data to i8042 port.
- *
- * @param fun    DDF function.
+ * @param fun DDF function.
  * @param buffer Data source.
- * @param size   Data size.
- *
+ * @param size Data size.
  * @return Bytes written.
- *
  */
 static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size)
@@ -302,19 +283,13 @@
 	assert(fun);
 	assert(fun->driver_data);
-	
 	i8042_t *controller = fun->driver_data;
 	fibril_mutex_lock(&controller->write_guard);
-	
 	for (size_t i = 0; i < size; ++i) {
-		if (controller->aux_fun == fun) {
-			wait_ready(controller);
-			pio_write_8(&controller->regs->status,
-			    i8042_CMD_WRITE_AUX);
-		}
-		
 		wait_ready(controller);
+		if (controller->aux_fun == fun)
+			pio_write_8(
+			    &controller->regs->status, i8042_CMD_WRITE_AUX);
 		pio_write_8(&controller->regs->data, buffer[i]);
 	}
-	
 	fibril_mutex_unlock(&controller->write_guard);
 	return size;
@@ -322,11 +297,8 @@
 
 /** Read data from i8042 port.
- *
- * @param fun    DDF function.
+ * @param fun DDF function.
  * @param buffer Data place.
- * @param size   Data place size.
- *
+ * @param size Data place size.
  * @return Bytes read.
- *
  */
 static int i8042_read(ddf_fun_t *fun, char *data, size_t size)
@@ -334,21 +306,18 @@
 	assert(fun);
 	assert(fun->driver_data);
-	
+
 	i8042_t *controller = fun->driver_data;
 	buffer_t *buffer = (fun == controller->aux_fun) ?
 	    &controller->aux_buffer : &controller->kbd_buffer;
-	
-	for (size_t i = 0; i < size; ++i)
+	for (size_t i = 0; i < size; ++i) {
 		*data++ = buffer_read(buffer);
-	
+	}
 	return size;
 }
 
 /** Handle data requests.
- *
- * @param fun  ddf_fun_t function.
- * @param id   callid
+ * @param fun ddf_fun_t function.
+ * @param id callid
  * @param call IPC request.
- *
  */
 void default_handler(ddf_fun_t *fun, ipc_callid_t id, ipc_call_t *call)
@@ -356,35 +325,31 @@
 	const sysarg_t method = IPC_GET_IMETHOD(*call);
 	const size_t size = IPC_GET_ARG1(*call);
-	
 	switch (method) {
 	case IPC_CHAR_READ:
 		if (size <= 4 * sizeof(sysarg_t)) {
 			sysarg_t message[4] = {};
-			
-			i8042_read(fun, (char *) message, size);
+			i8042_read(fun, (char*)message, size);
 			async_answer_4(id, size, message[0], message[1],
 			    message[2], message[3]);
-		} else
+		} else {
 			async_answer_0(id, ELIMIT);
+		}
 		break;
-	
+
 	case IPC_CHAR_WRITE:
 		if (size <= 3 * sizeof(sysarg_t)) {
 			const sysarg_t message[3] = {
-				IPC_GET_ARG2(*call),
-				IPC_GET_ARG3(*call),
-				IPC_GET_ARG4(*call)
-			};
-			
-			i8042_write(fun, (char *) message, size);
+				IPC_GET_ARG2(*call), IPC_GET_ARG3(*call),
+				IPC_GET_ARG4(*call) };
+			i8042_write(fun, (char*)message, size);
 			async_answer_0(id, size);
-		} else
+		} else {
 			async_answer_0(id, ELIMIT);
-	
+		}
+
 	default:
 		async_answer_0(id, EINVAL);
 	}
 }
-
 /**
  * @}
Index: uspace/drv/char/i8042/i8042.h
===================================================================
--- uspace/drv/char/i8042/i8042.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/char/i8042/i8042.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -27,10 +27,8 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup kbd_port
  * @ingroup  kbd
  * @{
  */
-
 /** @file
  * @brief i8042 port driver.
@@ -43,9 +41,8 @@
 #include <fibril_synch.h>
 #include <ddf/driver.h>
+
 #include "buffer.h"
 
-#define NAME  "i8042"
-
-#define BUFFER_SIZE  12
+#define BUFFER_SIZE 12
 
 /** i8042 HW I/O interface */
@@ -58,9 +55,9 @@
 /** i8042 driver structure. */
 typedef struct i8042 {
-	i8042_regs_t *regs;             /**< I/O registers. */
-	ddf_fun_t *kbd_fun;             /**< Pirmary port device function. */
-	ddf_fun_t *aux_fun;             /**< Auxiliary port device function. */
-	buffer_t kbd_buffer;            /**< Primary port buffer. */
-	buffer_t aux_buffer;            /**< Aux. port buffer. */
+	i8042_regs_t *regs;    /**< I/O registers. */
+	ddf_fun_t *kbd_fun;    /**< Pirmary port device function. */
+	ddf_fun_t *aux_fun;  /**< Auxiliary port device function. */
+	buffer_t kbd_buffer;   /**< Primary port buffer. */
+	buffer_t aux_buffer;   /**< Aux. port buffer. */
 	uint8_t aux_data[BUFFER_SIZE];  /**< Primary port buffer space. */
 	uint8_t kbd_data[BUFFER_SIZE];  /**< Aux. port buffer space. */
@@ -69,7 +66,5 @@
 
 int i8042_init(i8042_t *, void *, size_t, int, int, ddf_dev_t *);
-
 #endif
-
 /**
  * @}
Index: uspace/drv/char/i8042/main.c
===================================================================
--- uspace/drv/char/i8042/main.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/char/i8042/main.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -26,9 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup drvi8042
  * @{
  */
-
 /** @file
  * @brief i8042 driver DDF bits.
@@ -43,100 +41,12 @@
 #include <ddf/log.h>
 #include <stdio.h>
+
 #include "i8042.h"
 
-#define CHECK_RET_RETURN(ret, message...) \
-	do { \
-		if (ret != EOK) { \
-			ddf_msg(LVL_ERROR, message); \
-			return ret; \
-		} \
-	} while (0)
+#define NAME "i8042"
 
-/** Get address of I/O registers.
- *
- * @param[in]  dev            Device asking for the addresses.
- * @param[out] io_reg_address Base address of the memory range.
- * @param[out] io_reg_size    Size of the memory range.
- * @param[out] kbd_irq        Primary port IRQ.
- * @param[out] mouse_irq      Auxiliary port IRQ.
- *
- * @return Error code.
- *
- */
-static int get_my_registers(const ddf_dev_t *dev, uintptr_t *io_reg_address,
-    size_t *io_reg_size, int *kbd_irq, int *mouse_irq)
-{
-	assert(dev);
-	
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	hw_res_list_parsed_t hw_resources;
-	hw_res_list_parsed_init(&hw_resources);
-	const int ret = hw_res_get_list_parsed(parent_sess, &hw_resources, 0);
-	async_hangup(parent_sess);
-	if (ret != EOK)
-		return ret;
-	
-	if ((hw_resources.irqs.count != 2) ||
-	    (hw_resources.io_ranges.count != 1)) {
-		hw_res_list_parsed_clean(&hw_resources);
-		return EINVAL;
-	}
-	
-	if (io_reg_address)
-		*io_reg_address = hw_resources.io_ranges.ranges[0].address;
-	
-	if (io_reg_size)
-		*io_reg_size = hw_resources.io_ranges.ranges[0].size;
-	
-	if (kbd_irq)
-		*kbd_irq = hw_resources.irqs.irqs[0];
-	
-	if (mouse_irq)
-		*mouse_irq = hw_resources.irqs.irqs[1];
-	
-	hw_res_list_parsed_clean(&hw_resources);
-	return EOK;
-}
-
-/** Initialize a new ddf driver instance of i8042 driver
- *
- * @param[in] device DDF instance of the device to initialize.
- *
- * @return Error code.
- *
- */
-static int i8042_dev_add(ddf_dev_t *device)
-{
-	if (!device)
-		return EINVAL;
-	
-	uintptr_t io_regs = 0;
-	size_t io_size = 0;
-	int kbd = 0;
-	int mouse = 0;
-	
-	int ret = get_my_registers(device, &io_regs, &io_size, &kbd, &mouse);
-	CHECK_RET_RETURN(ret, "Failed to get registers: %s.",
-	    str_error(ret));
-	ddf_msg(LVL_DEBUG, "I/O regs at %p (size %zuB), IRQ kbd %d, IRQ mouse %d.",
-	    (void *) io_regs, io_size, kbd, mouse);
-	
-	i8042_t *i8042 = ddf_dev_data_alloc(device, sizeof(i8042_t));
-	ret = (i8042 == NULL) ? ENOMEM : EOK;
-	CHECK_RET_RETURN(ret, "Failed to allocate i8042 driver instance.");
-	
-	ret = i8042_init(i8042, (void *) io_regs, io_size, kbd, mouse, device);
-	CHECK_RET_RETURN(ret, "Failed to initialize i8042 driver: %s.",
-	    str_error(ret));
-	
-	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
-	    device->name, device->handle);
-	return EOK;
-}
+static int get_my_registers(const ddf_dev_t *dev,
+    uintptr_t *io_reg_address, size_t *io_reg_size, int *kbd, int *mouse);
+static int i8042_dev_add(ddf_dev_t *device);
 
 /** DDF driver operations. */
@@ -151,11 +61,107 @@
 };
 
+/** Initialize global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
 int main(int argc, char *argv[])
 {
-	printf("%s: HelenOS PS/2 driver.\n", NAME);
+	printf(NAME ": HelenOS ps/2 driver.\n");
 	ddf_log_init(NAME, LVL_NOTE);
 	return ddf_driver_main(&i8042_driver);
 }
 
+/** Initialize a new ddf driver instance of i8042 driver
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+static int i8042_dev_add(ddf_dev_t *device)
+{
+	if (!device)
+		return EINVAL;
+
+#define CHECK_RET_RETURN(ret, message...) \
+if (ret != EOK) { \
+	ddf_msg(LVL_ERROR, message); \
+	return ret; \
+} else (void)0
+
+	uintptr_t io_regs = 0;
+	size_t io_size = 0;
+	int kbd = 0, mouse = 0;
+
+	int ret = get_my_registers(device, &io_regs, &io_size, &kbd, &mouse);
+	CHECK_RET_RETURN(ret,
+	    "Failed to get registers: %s.", str_error(ret));
+	ddf_msg(LVL_DEBUG,
+	    "I/O regs at %p (size %zuB), IRQ kbd %d, IRQ mouse %d.",
+	    (void *) io_regs, io_size, kbd, mouse);
+
+	i8042_t *i8042 = ddf_dev_data_alloc(device, sizeof(i8042_t));
+	ret = (i8042 == NULL) ? ENOMEM : EOK;
+	CHECK_RET_RETURN(ret, "Failed to allocate i8042 driver instance.");
+
+	ret = i8042_init(i8042, (void*)io_regs, io_size, kbd, mouse, device);
+	CHECK_RET_RETURN(ret,
+	    "Failed to initialize i8042 driver: %s.", str_error(ret));
+
+	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
+	    device->name, device->handle);
+	return EOK;
+}
+
+/** Get address of I/O registers.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] io_reg_address Base address of the memory range.
+ * @param[out] io_reg_size Size of the memory range.
+ * @param[out] kbd_irq Primary port IRQ.
+ * @param[out] mouse_irq Auxiliary port IRQ.
+ * @return Error code.
+ */
+int get_my_registers(const ddf_dev_t *dev, uintptr_t *io_reg_address,
+    size_t *io_reg_size, int *kbd_irq, int *mouse_irq)
+{
+	assert(dev);
+
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+
+	hw_res_list_parsed_t hw_resources;
+	hw_res_list_parsed_init(&hw_resources);
+	const int ret = hw_res_get_list_parsed(parent_sess, &hw_resources, 0);
+	async_hangup(parent_sess);
+	if (ret != EOK) {
+		return ret;
+	}
+
+	if (hw_resources.irqs.count != 2 || hw_resources.io_ranges.count != 1) {
+		hw_res_list_parsed_clean(&hw_resources);
+		return EINVAL;
+	}
+
+	if (io_reg_address)
+		*io_reg_address = hw_resources.io_ranges.ranges[0].address;
+
+	if (io_reg_size)
+		*io_reg_size = hw_resources.io_ranges.ranges[0].size;
+
+	if (kbd_irq)
+		*kbd_irq = hw_resources.irqs.irqs[0];
+
+	if (mouse_irq)
+		*mouse_irq = hw_resources.irqs.irqs[1];
+
+	hw_res_list_parsed_clean(&hw_resources);
+	return EOK;
+}
 /**
  * @}
Index: uspace/drv/char/ps2mouse/ps2mouse.c
===================================================================
--- uspace/drv/char/ps2mouse/ps2mouse.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/char/ps2mouse/ps2mouse.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -116,5 +116,5 @@
 	assert(mouse);
 	assert(dev);
-	mouse->client_sess = NULL;
+	mouse->input_sess = NULL;
 	mouse->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
 	    dev->handle, IPC_FLAG_BLOCKING);
@@ -218,8 +218,8 @@
 
 		async_exch_t *exch =
-		    async_exchange_begin(mouse->client_sess);
+		    async_exchange_begin(mouse->input_sess);
 		if (!exch) {
 			ddf_msg(LVL_ERROR,
-			    "Failed creating exchange.");
+			    "Failed to create input exchange.");
 			continue;
 		}
@@ -277,8 +277,8 @@
 
 		async_exch_t *exch =
-		    async_exchange_begin(mouse->client_sess);
+		    async_exchange_begin(mouse->input_sess);
 		if (!exch) {
 			ddf_msg(LVL_ERROR,
-			    "Failed creating exchange.");
+			    "Failed to create input exchange.");
 			continue;
 		}
@@ -386,14 +386,14 @@
 		if (sess == NULL) {
 			ddf_msg(LVL_WARN,
-			    "Failed creating client callback session");
+			    "Failed to create start input session");
 			async_answer_0(icallid, EAGAIN);
 			break;
 		}
-		if (mouse->client_sess == NULL) {
-			mouse->client_sess = sess;
-			ddf_msg(LVL_DEBUG, "Set client session");
+		if (mouse->input_sess == NULL) {
+			mouse->input_sess = sess;
+			ddf_msg(LVL_DEBUG, "Set input session");
 			async_answer_0(icallid, EOK);
 		} else {
-			ddf_msg(LVL_ERROR, "Client session already set");
+			ddf_msg(LVL_ERROR, "Input session already set");
 			async_answer_0(icallid, ELIMIT);
 		}
Index: uspace/drv/char/ps2mouse/ps2mouse.h
===================================================================
--- uspace/drv/char/ps2mouse/ps2mouse.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/char/ps2mouse/ps2mouse.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -43,5 +43,5 @@
 	ddf_fun_t *mouse_fun;      /**< Mouse function. */
 	async_sess_t *parent_sess; /**< Connection to device providing data. */
-	async_sess_t *client_sess;  /**< Callback connection to client. */
+	async_sess_t *input_sess;  /**< Callback connection to consumer. */
 	fid_t polling_fibril;      /**< Fibril retrieving an parsing data. */
 } ps2_mouse_t;
Index: uspace/drv/char/xtkbd/xtkbd.c
===================================================================
--- uspace/drv/char/xtkbd/xtkbd.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/char/xtkbd/xtkbd.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -206,5 +206,5 @@
 	assert(kbd);
 	assert(dev);
-	kbd->client_sess = NULL;
+	kbd->input_sess = NULL;
 	kbd->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
 	    dev->handle, IPC_FLAG_BLOCKING);
@@ -296,8 +296,8 @@
 		if (key != 0) {
 			async_exch_t *exch =
-			    async_exchange_begin(kbd->client_sess);
+			    async_exchange_begin(kbd->input_sess);
 			if (!exch) {
 				ddf_msg(LVL_ERROR,
-				    "Failed creating exchange.");
+				    "Failed to create input exchange.");
 				continue;
 			}
@@ -352,14 +352,14 @@
 		if (sess == NULL) {
 			ddf_msg(LVL_WARN,
-			    "Failed creating callback session");
+			    "Failed to create start input session");
 			async_answer_0(icallid, EAGAIN);
 			break;
 		}
-		if (kbd->client_sess == NULL) {
-			kbd->client_sess = sess;
-			ddf_msg(LVL_DEBUG, "Set client session");
+		if (kbd->input_sess == NULL) {
+			kbd->input_sess = sess;
+			ddf_msg(LVL_DEBUG, "Set input session");
 			async_answer_0(icallid, EOK);
 		} else {
-			ddf_msg(LVL_ERROR, "Client session already set");
+			ddf_msg(LVL_ERROR, "Input session already set");
 			async_answer_0(icallid, ELIMIT);
 		}
Index: uspace/drv/char/xtkbd/xtkbd.h
===================================================================
--- uspace/drv/char/xtkbd/xtkbd.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/char/xtkbd/xtkbd.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -43,5 +43,5 @@
 	ddf_fun_t *kbd_fun;        /**< Keyboard function. */
 	async_sess_t *parent_sess; /**< Connection to device providing data. */
-	async_sess_t *client_sess; /**< Callback connection to client. */
+	async_sess_t *input_sess;  /**< Callback connection to consumer. */
 	fid_t polling_fibril;      /**< Fibril retrieving an parsing data. */
 } xt_kbd_t;
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/nic/e1k/e1k.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -52,4 +52,7 @@
 #include <nil_remote.h>
 #include <ops/nic.h>
+#include <packet_client.h>
+#include <packet_remote.h>
+#include <net/packet_header.h>
 #include "e1k.h"
 
@@ -59,13 +62,13 @@
 
 /* Must be power of 8 */
-#define E1000_RX_FRAME_COUNT  128
-#define E1000_TX_FRAME_COUNT  128
+#define E1000_RX_PACKETS_COUNT  128
+#define E1000_TX_PACKETS_COUNT  128
 
 #define E1000_RECEIVE_ADDRESS  16
 
-/** Maximum sending frame size */
+/** Maximum sending packet size */
 #define E1000_MAX_SEND_FRAME_SIZE  2048
-/** Maximum receiving frame size */
-#define E1000_MAX_RECEIVE_FRAME_SIZE  2048
+/** Maximum receiving packet size */
+#define E1000_MAX_RECEIVE_PACKET_SIZE  2048
 
 /** nic_driver_data_t* -> e1000_t* cast */
@@ -134,13 +137,11 @@
 	void *rx_ring_virt;
 	
-	/** Ring of RX frames, physical address */
-	void **rx_frame_phys;
-	/** Ring of RX frames, virtual address */
-	void **rx_frame_virt;
+	/** Packets in rx ring  */
+	packet_t **rx_ring_packets;
 	
 	/** VLAN tag */
 	uint16_t vlan_tag;
 	
-	/** Add VLAN tag to frame */
+	/** Add VLAN tag to packet */
 	bool vlan_tag_add;
 	
@@ -476,5 +477,5 @@
 }
 
-/** Get state of acceptance of weird frames
+/** Get state of acceptance of weird packets
  *
  * @param      device Device to check
@@ -494,5 +495,5 @@
 };
 
-/** Set acceptance of weird frames
+/** Set acceptance of weird packets
  *
  * @param device Device to update
@@ -678,5 +679,5 @@
 }
 
-/** Disable receiving frames for default address
+/** Disable receiving packets for default address
  *
  * @param e1000 E1000 data structure
@@ -690,5 +691,5 @@
 }
 
-/** Enable receiving frames for default address
+/** Enable receiving packets for default address
  *
  * @param e1000 E1000 data structure
@@ -750,5 +751,5 @@
 }
 
-/** Enable accepting of broadcast frames
+/** Enable accepting of broadcast packets
  *
  * @param e1000 E1000 data structure
@@ -762,5 +763,5 @@
 }
 
-/** Disable accepting of broadcast frames
+/** Disable accepting of broadcast packets
  *
  * @param e1000 E1000 data structure
@@ -798,5 +799,5 @@
 }
 
-/** Set multicast frames acceptance mode
+/** Set multicast packets acceptance mode
  *
  * @param nic      NIC device to update
@@ -852,5 +853,5 @@
 }
 
-/** Set unicast frames acceptance mode
+/** Set unicast packets acceptance mode
  *
  * @param nic      NIC device to update
@@ -910,5 +911,5 @@
 }
 
-/** Set broadcast frames acceptance mode
+/** Set broadcast packets acceptance mode
  *
  * @param nic  NIC device to update
@@ -995,5 +996,5 @@
 	if (vlan_mask) {
 		/*
-		 * Disable receiving, so that frame matching
+		 * Disable receiving, so that packet matching
 		 * partially written VLAN is not received.
 		 */
@@ -1062,7 +1063,7 @@
 }
 
-/** Fill receive descriptor with new empty buffer
- *
- * Store frame in e1000->rx_frame_phys
+/** Fill receive descriptor with new empty packet
+ *
+ * Store packet in e1000->rx_ring_packets
  *
  * @param nic    NIC data stricture
@@ -1073,9 +1074,22 @@
 {
 	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
-	
+	packet_t *packet =
+	    nic_alloc_packet(nic, E1000_MAX_RECEIVE_PACKET_SIZE);
+	
+	assert(packet);
+	
+	*(e1000->rx_ring_packets + offset) = packet;
 	e1000_rx_descriptor_t *rx_descriptor = (e1000_rx_descriptor_t *)
 	    (e1000->rx_ring_virt + offset * sizeof(e1000_rx_descriptor_t));
 	
-	rx_descriptor->phys_addr = PTR_TO_U64(e1000->rx_frame_phys[offset]);
+	void *phys;
+	int rc =
+	    nic_dma_lock_packet(packet, E1000_MAX_RECEIVE_PACKET_SIZE, &phys);
+	
+	if (rc == EOK)
+		rx_descriptor->phys_addr = PTR_TO_U64(phys + packet->data_start);
+	else
+		rx_descriptor->phys_addr = 0;
+	
 	rx_descriptor->length = 0;
 	rx_descriptor->checksum = 0;
@@ -1141,10 +1155,10 @@
 }
 
-/** Receive frames
+/** Receive packets
  *
  * @param nic NIC data
  *
  */
-static void e1000_receive_frames(nic_t *nic)
+static void e1000_receive_packets(nic_t *nic)
 {
 	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
@@ -1153,5 +1167,5 @@
 	
 	uint32_t *tail_addr = E1000_REG_ADDR(e1000, E1000_RDT);
-	uint32_t next_tail = e1000_inc_tail(*tail_addr, E1000_RX_FRAME_COUNT);
+	uint32_t next_tail = e1000_inc_tail(*tail_addr, E1000_RX_PACKETS_COUNT);
 	
 	e1000_rx_descriptor_t *rx_descriptor = (e1000_rx_descriptor_t *)
@@ -1159,18 +1173,16 @@
 	
 	while (rx_descriptor->status & 0x01) {
-		uint32_t frame_size = rx_descriptor->length - E1000_CRC_SIZE;
+		uint32_t packet_size = rx_descriptor->length - E1000_CRC_SIZE;
 		
-		nic_frame_t *frame = nic_alloc_frame(nic, frame_size);
-		if (frame != NULL) {
-			memcpy(frame->data, e1000->rx_frame_virt[next_tail], frame_size);
-			nic_received_frame(nic, frame);
-		} else {
-			ddf_msg(LVL_ERROR, "Memory allocation failed. Frame dropped.");
-		}
+		packet_t *packet = *(e1000->rx_ring_packets + next_tail);
+		packet_suffix(packet, packet_size);
+		
+		nic_dma_unlock_packet(packet, E1000_MAX_RECEIVE_PACKET_SIZE);
+		nic_received_packet(nic, packet);
 		
 		e1000_fill_new_rx_descriptor(nic, next_tail);
 		
-		*tail_addr = e1000_inc_tail(*tail_addr, E1000_RX_FRAME_COUNT);
-		next_tail = e1000_inc_tail(*tail_addr, E1000_RX_FRAME_COUNT);
+		*tail_addr = e1000_inc_tail(*tail_addr, E1000_RX_PACKETS_COUNT);
+		next_tail = e1000_inc_tail(*tail_addr, E1000_RX_PACKETS_COUNT);
 		
 		rx_descriptor = (e1000_rx_descriptor_t *)
@@ -1213,5 +1225,5 @@
 {
 	if (icr & ICR_RXT0)
-		e1000_receive_frames(nic);
+		e1000_receive_packets(nic);
 }
 
@@ -1262,5 +1274,5 @@
 }
 
-/** Force receiving all frames in the receive buffer
+/** Force receiving all packets in the receive buffer
  *
  * @param nic NIC data
@@ -1335,9 +1347,9 @@
 static void e1000_initialize_rx_registers(e1000_t *e1000)
 {
-	E1000_REG_WRITE(e1000, E1000_RDLEN, E1000_RX_FRAME_COUNT * 16);
+	E1000_REG_WRITE(e1000, E1000_RDLEN, E1000_RX_PACKETS_COUNT * 16);
 	E1000_REG_WRITE(e1000, E1000_RDH, 0);
 	
 	/* It is not posible to let HW use all descriptors */
-	E1000_REG_WRITE(e1000, E1000_RDT, E1000_RX_FRAME_COUNT - 1);
+	E1000_REG_WRITE(e1000, E1000_RDT, E1000_RX_PACKETS_COUNT - 1);
 	
 	/* Set Broadcast Enable Bit */
@@ -1359,5 +1371,5 @@
 	
 	int rc = dmamem_map_anonymous(
-	    E1000_RX_FRAME_COUNT * sizeof(e1000_rx_descriptor_t),
+	    E1000_RX_PACKETS_COUNT * sizeof(e1000_rx_descriptor_t),
 	    AS_AREA_READ | AS_AREA_WRITE, 0, &e1000->rx_ring_phys,
 	    &e1000->rx_ring_virt);
@@ -1370,31 +1382,13 @@
 	    (uint32_t) PTR_TO_U64(e1000->rx_ring_phys));
 	
-	e1000->rx_frame_phys =
-	    calloc(E1000_RX_FRAME_COUNT, sizeof(void *));
-	e1000->rx_frame_virt =
-	    calloc(E1000_RX_FRAME_COUNT, sizeof(void *));
-	if (e1000->rx_frame_phys == NULL || e1000->rx_frame_virt == NULL) {
-		rc = ENOMEM;
-		goto error;
-	}
-	
-	size_t i;
-	void *frame_virt;
-	void *frame_phys;
-	
-	for (i = 0; i < E1000_RX_FRAME_COUNT; i++) {
-		rc = dmamem_map_anonymous(
-		    E1000_MAX_SEND_FRAME_SIZE, AS_AREA_READ | AS_AREA_WRITE,
-		    0, &frame_phys, &frame_virt);
-		if (rc != EOK)
-			goto error;
-		
-		e1000->rx_frame_virt[i] = frame_virt;
-		e1000->rx_frame_phys[i] = frame_phys;
-	}
+	e1000->rx_ring_packets =
+	    malloc(E1000_RX_PACKETS_COUNT * sizeof(packet_t *));
+	// FIXME: Check return value
 	
 	/* Write descriptor */
-	for (i = 0; i < E1000_RX_FRAME_COUNT; i++)
-		e1000_fill_new_rx_descriptor(nic, i);
+	for (unsigned int offset = 0;
+	    offset < E1000_RX_PACKETS_COUNT;
+	    offset++)
+		e1000_fill_new_rx_descriptor(nic, offset);
 	
 	e1000_initialize_rx_registers(e1000);
@@ -1402,25 +1396,4 @@
 	fibril_mutex_unlock(&e1000->rx_lock);
 	return EOK;
-	
-error:
-	for (i = 0; i < E1000_RX_FRAME_COUNT; i++) {
-		if (e1000->rx_frame_virt[i] != NULL) {
-			dmamem_unmap_anonymous(e1000->rx_frame_virt[i]);
-			e1000->rx_frame_virt[i] = NULL;
-			e1000->rx_frame_phys[i] = NULL;
-		}
-	}
-	
-	if (e1000->rx_frame_phys != NULL) {
-		free(e1000->rx_frame_phys);
-		e1000->rx_frame_phys = NULL;
-	}
-	
-	if (e1000->rx_frame_virt != NULL) {
-		free(e1000->rx_frame_virt);
-		e1000->rx_frame_phys = NULL;
-	}
-	
-	return rc;
 }
 
@@ -1434,28 +1407,27 @@
 	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
 	
-	/* Write descriptor */
-	for (unsigned int offset = 0; offset < E1000_RX_FRAME_COUNT; offset++) {
-		dmamem_unmap_anonymous(e1000->rx_frame_virt[offset]);
-		e1000->rx_frame_virt[offset] = NULL;
-		e1000->rx_frame_phys[offset] = NULL;
-	}
-	
-	free(e1000->rx_frame_virt);
-	free(e1000->rx_frame_phys);
-	e1000->rx_frame_virt = NULL;
-	e1000->rx_frame_phys = NULL;
-	dmamem_unmap_anonymous(e1000->rx_ring_virt);
-}
-
-/** Clear receive descriptor ring
- *
- * @param e1000 E1000 data
- *
- */
-static void e1000_clear_rx_ring(e1000_t *e1000)
-{
 	/* Write descriptor */
 	for (unsigned int offset = 0;
-	    offset < E1000_RX_FRAME_COUNT;
+	    offset < E1000_RX_PACKETS_COUNT;
+	    offset++) {
+		packet_t *packet = *(e1000->rx_ring_packets + offset);
+		nic_dma_unlock_packet(packet, E1000_MAX_RECEIVE_PACKET_SIZE);
+		nic_release_packet(nic, packet);
+	}
+	
+	free(e1000->rx_ring_packets);
+	dmamem_unmap_anonymous(e1000->rx_ring_virt);
+}
+
+/** Clear receive descriptor ring
+ *
+ * @param e1000 E1000 data
+ *
+ */
+static void e1000_clear_rx_ring(e1000_t *e1000)
+{
+	/* Write descriptor */
+	for (unsigned int offset = 0;
+	    offset < E1000_RX_PACKETS_COUNT;
 	    offset++)
 		e1000_clear_rx_descriptor(e1000, offset);
@@ -1526,5 +1498,5 @@
 static void e1000_initialize_tx_registers(e1000_t *e1000)
 {
-	E1000_REG_WRITE(e1000, E1000_TDLEN, E1000_TX_FRAME_COUNT * 16);
+	E1000_REG_WRITE(e1000, E1000_TDLEN, E1000_TX_PACKETS_COUNT * 16);
 	E1000_REG_WRITE(e1000, E1000_TDH, 0);
 	E1000_REG_WRITE(e1000, E1000_TDT, 0);
@@ -1558,5 +1530,5 @@
 	
 	int rc = dmamem_map_anonymous(
-	    E1000_TX_FRAME_COUNT * sizeof(e1000_tx_descriptor_t),
+	    E1000_TX_PACKETS_COUNT * sizeof(e1000_tx_descriptor_t),
 	    AS_AREA_READ | AS_AREA_WRITE, 0, &e1000->tx_ring_phys,
 	    &e1000->tx_ring_virt);
@@ -1565,8 +1537,8 @@
 	
 	bzero(e1000->tx_ring_virt,
-	    E1000_TX_FRAME_COUNT * sizeof(e1000_tx_descriptor_t));
-	
-	e1000->tx_frame_phys = calloc(E1000_TX_FRAME_COUNT, sizeof(void *));
-	e1000->tx_frame_virt = calloc(E1000_TX_FRAME_COUNT, sizeof(void *));
+	    E1000_TX_PACKETS_COUNT * sizeof(e1000_tx_descriptor_t));
+	
+	e1000->tx_frame_phys = calloc(E1000_TX_PACKETS_COUNT, sizeof(void *));
+	e1000->tx_frame_virt = calloc(E1000_TX_PACKETS_COUNT, sizeof(void *));
 
 	if (e1000->tx_frame_phys == NULL || e1000->tx_frame_virt == NULL) {
@@ -1575,5 +1547,5 @@
 	}
 	
-	for (i = 0; i < E1000_TX_FRAME_COUNT; i++) {
+	for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
 		rc = dmamem_map_anonymous(
 		    E1000_MAX_SEND_FRAME_SIZE, AS_AREA_READ | AS_AREA_WRITE,
@@ -1600,5 +1572,5 @@
 	
 	if (e1000->tx_frame_phys != NULL && e1000->tx_frame_virt != NULL) {
-		for (i = 0; i < E1000_TX_FRAME_COUNT; i++) {
+		for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
 			if (e1000->tx_frame_virt[i] != NULL) {
 				dmamem_unmap_anonymous(e1000->tx_frame_virt[i]);
@@ -1631,5 +1603,5 @@
 	size_t i;
 	
-	for (i = 0; i < E1000_TX_FRAME_COUNT; i++) {
+	for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
 		dmamem_unmap_anonymous(e1000->tx_frame_virt[i]);
 		e1000->tx_frame_virt[i] = NULL;
@@ -1646,5 +1618,4 @@
 		e1000->tx_frame_phys = NULL;
 	}
-	
 	dmamem_unmap_anonymous(e1000->tx_ring_virt);
 }
@@ -1659,5 +1630,5 @@
 	/* Write descriptor */
 	for (unsigned int offset = 0;
-	    offset < E1000_TX_FRAME_COUNT;
+	    offset < E1000_TX_PACKETS_COUNT;
 	    offset++)
 		e1000_clear_tx_descriptor(nic, offset);
@@ -1716,5 +1687,5 @@
 }
 
-/** Activate the device to receive and transmit frames
+/** Activate the device to receive and transmit packets
  *
  * @param nic NIC driver data
@@ -2057,4 +2028,5 @@
 	case E1000_82545:
 	case E1000_82546:
+	case E1000_82572:
 		e1000->info.eerd_start = 0x01;
 		e1000->info.eerd_done = 0x10;
@@ -2063,5 +2035,4 @@
 		break;
 	case E1000_82547:
-	case E1000_82572:
 	case E1000_80003ES2:
 		e1000->info.eerd_start = 0x01;
@@ -2102,5 +2073,4 @@
 int e1000_dev_add(ddf_dev_t *dev)
 {
-	ddf_fun_t *fun;
 	assert(dev);
 	
@@ -2133,14 +2103,11 @@
 	e1000_initialize_vlan(e1000);
 	
-	fun = ddf_fun_create(nic_get_ddf_dev(nic), fun_exposed, "port0");
-	if (fun == NULL)
+	rc = nic_register_as_ddf_fun(nic, &e1000_dev_ops);
+	if (rc != EOK)
 		goto err_tx_structure;
-	nic_set_ddf_fun(nic, fun);
-	fun->ops = &e1000_dev_ops;
-	fun->driver_data = nic;
 	
 	rc = e1000_register_int_handler(nic);
 	if (rc != EOK)
-		goto err_fun_create;
+		goto err_tx_structure;
 	
 	rc = nic_connect_to_services(nic);
@@ -2165,24 +2132,10 @@
 		goto err_rx_structure;
 	
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK)
-		goto err_fun_bind;
-	
-	rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC);
-	if (rc != EOK)
-		goto err_add_to_cat;
-	
 	return EOK;
 	
-err_add_to_cat:
-	ddf_fun_unbind(fun);
-err_fun_bind:
 err_rx_structure:
 	e1000_uninitialize_rx_structure(nic);
 err_irq:
 	unregister_interrupt_handler(dev, DRIVER_DATA_DEV(dev)->irq);
-err_fun_create:
-	ddf_fun_destroy(fun);
-	nic_set_ddf_fun(nic, NULL);
 err_tx_structure:
 	e1000_uninitialize_tx_structure(e1000);
@@ -2330,5 +2283,5 @@
 	
 	if (!descriptor_available) {
-		/* Frame lost */
+		/* Packet lost */
 		fibril_mutex_unlock(&e1000->tx_lock);
 		return;
@@ -2359,5 +2312,5 @@
 	
 	tdt++;
-	if (tdt == E1000_TX_FRAME_COUNT)
+	if (tdt == E1000_TX_PACKETS_COUNT)
 		tdt = 0;
 	
Index: uspace/drv/nic/e1k/e1k.h
===================================================================
--- uspace/drv/nic/e1k/e1k.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/nic/e1k/e1k.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -39,5 +39,5 @@
 #include <stdint.h>
 
-/** Ethernet CRC size after frame received in rx_descriptor */
+/** Ethernet CRC size after packet received in rx_descriptor */
 #define E1000_CRC_SIZE  4
 
@@ -109,5 +109,5 @@
 /** Transmit descriptor COMMAND field bits */
 typedef enum {
-	TXDESCRIPTOR_COMMAND_VLE = (1 << 6),   /**< VLAN frame Enable */
+	TXDESCRIPTOR_COMMAND_VLE = (1 << 6),   /**< VLAN Packet Enable */
 	TXDESCRIPTOR_COMMAND_RS = (1 << 3),    /**< Report Status */
 	TXDESCRIPTOR_COMMAND_IFCS = (1 << 1),  /**< Insert FCS */
Index: uspace/drv/nic/lo/lo.c
===================================================================
--- uspace/drv/nic/lo/lo.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/nic/lo/lo.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -42,4 +42,5 @@
 #include <async.h>
 #include <nic.h>
+#include <packet_client.h>
 
 #define NAME  "lo"
@@ -60,6 +61,17 @@
 static void lo_send_frame(nic_t *nic_data, void *data, size_t size)
 {
+	packet_t *packet;
+	int rc;
+
+	packet = nic_alloc_packet(nic_data, size);
+	if (packet == NULL)
+		return;
+
+	rc = packet_copy_data(packet, data, size);
+	if (rc != EOK)
+		return;
+
 	nic_report_send_ok(nic_data, 1, size);
-	nic_received_noneth_frame(nic_data, data, size);
+	nic_received_noneth_packet(nic_data, packet);
 }
 
@@ -80,61 +92,36 @@
 static int lo_dev_add(ddf_dev_t *dev)
 {
-	ddf_fun_t *fun = NULL;
-	bool bound = false;
-	
-	nic_t *nic = nic_create_and_bind(dev);
-	if (nic == NULL) {
+	nic_t *nic_data = nic_create_and_bind(dev);
+	if (nic_data == NULL) {
 		printf("%s: Failed to initialize\n", NAME);
 		return ENOMEM;
 	}
 	
-	dev->driver_data = nic;
-	nic_set_send_frame_handler(nic, lo_send_frame);
+	dev->driver_data = nic_data;
+	nic_set_send_frame_handler(nic_data, lo_send_frame);
 	
-	int rc = nic_connect_to_services(nic);
+	int rc = nic_connect_to_services(nic_data);
 	if (rc != EOK) {
 		printf("%s: Failed to connect to services\n", NAME);
-		goto error;
+		nic_unbind_and_destroy(dev);
+		return rc;
 	}
 	
-	fun = ddf_fun_create(nic_get_ddf_dev(nic), fun_exposed, "port0");
-	if (fun == NULL) {
-		printf("%s: Failed creating function\n", NAME);
-		rc = ENOMEM;
-		goto error;
+	rc = nic_register_as_ddf_fun(nic_data, &lo_dev_ops);
+	if (rc != EOK) {
+		printf("%s: Failed to register as DDF function\n", NAME);
+		nic_unbind_and_destroy(dev);
+		return rc;
 	}
-	nic_set_ddf_fun(nic, fun);
-	fun->ops = &lo_dev_ops;
-	fun->driver_data = nic;
 	
-	rc = nic_report_address(nic, &lo_addr);
+	rc = nic_report_address(nic_data, &lo_addr);
 	if (rc != EOK) {
 		printf("%s: Failed to setup loopback address\n", NAME);
-		goto error;
+		nic_unbind_and_destroy(dev);
+		return rc;
 	}
-	
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		printf("%s: Failed binding function\n", NAME);
-		goto error;
-	}
-	bound = true;
-	
-	rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC);
-	if (rc != EOK)
-		goto error;
 	
 	printf("%s: Adding loopback device '%s'\n", NAME, dev->name);
 	return EOK;
-	
-error:
-	if (bound)
-		ddf_fun_unbind(fun);
-	
-	if (fun != NULL)
-		ddf_fun_destroy(fun);
-	
-	nic_unbind_and_destroy(dev);
-	return rc;
 }
 
Index: uspace/drv/nic/ne2k/dp8390.c
===================================================================
--- uspace/drv/nic/ne2k/dp8390.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/nic/ne2k/dp8390.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -59,4 +59,6 @@
 #include <stdio.h>
 #include <libarch/ddi.h>
+#include <net/packet.h>
+#include <packet_client.h>
 #include "dp8390.h"
 
@@ -74,5 +76,5 @@
 	uint8_t status;
 	
-	/** Pointer to next frame */
+	/** Pointer to next packet */
 	uint8_t next;
 	
@@ -391,6 +393,6 @@
 	/*
 	 * Reset the transmit ring. If we were transmitting a frame,
-	 * we pretend that the frame is processed. Higher layers will
-	 * retransmit if the frame wasn't actually sent.
+	 * we pretend that the packet is processed. Higher layers will
+	 * retransmit if the packet wasn't actually sent.
 	 */
 	ne2k->sq.dirty = false;
@@ -446,5 +448,6 @@
 		return NULL;
 	
-	bzero(frame->data, length);
+	void *buf = packet_suffix(frame->packet, length);
+	bzero(buf, length);
 	uint8_t last = page + length / DP_PAGE;
 	
@@ -452,10 +455,10 @@
 		size_t left = (ne2k->stop_page - page) * DP_PAGE
 		    - sizeof(recv_header_t);
-		ne2k_download(ne2k, frame->data, page * DP_PAGE + sizeof(recv_header_t),
+		ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
 		    left);
-		ne2k_download(ne2k, frame->data + left, ne2k->start_page * DP_PAGE,
+		ne2k_download(ne2k, buf + left, ne2k->start_page * DP_PAGE,
 		    length - left);
 	} else {
-		ne2k_download(ne2k, frame->data, page * DP_PAGE + sizeof(recv_header_t),
+		ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
 		    length);
 	}
@@ -538,5 +541,5 @@
 		 * Update the boundary pointer
 		 * to the value of the page
-		 * prior to the next frame to
+		 * prior to the next packet to
 		 * be processed.
 		 */
@@ -581,5 +584,5 @@
 		fibril_mutex_lock(&ne2k->sq_mutex);
 		if (ne2k->sq.dirty) {
-			/* Prepare the buffer for next frame */
+			/* Prepare the buffer for next packet */
 			ne2k->sq.dirty = false;
 			ne2k->sq.size = 0;
Index: uspace/drv/nic/ne2k/dp8390.h
===================================================================
--- uspace/drv/nic/ne2k/dp8390.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/nic/ne2k/dp8390.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -264,4 +264,5 @@
 extern void ne2k_send(nic_t *, void *, size_t);
 extern void ne2k_interrupt(nic_t *, uint8_t, uint8_t);
+extern packet_t *ne2k_alloc_packet(nic_t *, size_t);
 
 extern void ne2k_set_accept_mcast(ne2k_t *, int);
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -261,5 +261,5 @@
 	/* Note: some frame with previous physical address may slip to NIL here
 	 * (for a moment the filtering is not exact), but ethernet should be OK with
-	 * that. Some frames may also be lost, but this is not a problem.
+	 * that. Some packet may also be lost, but this is not a problem.
 	 */
 	ne2k_set_physical_address((ne2k_t *) nic_get_specific(nic_data), address);
@@ -338,6 +338,4 @@
 static int ne2k_dev_add(ddf_dev_t *dev)
 {
-	ddf_fun_t *fun;
-	
 	/* Allocate driver data for the device. */
 	nic_t *nic_data = nic_create_and_bind(dev);
@@ -373,4 +371,10 @@
 	}
 	
+	rc = nic_register_as_ddf_fun(nic_data, &ne2k_dev_ops);
+	if (rc != EOK) {
+		ne2k_dev_cleanup(dev);
+		return rc;
+	}
+	
 	rc = nic_connect_to_services(nic_data);
 	if (rc != EOK) {
@@ -379,27 +383,4 @@
 	}
 	
-	fun = ddf_fun_create(nic_get_ddf_dev(nic_data), fun_exposed, "port0");
-	if (fun == NULL) {
-		ne2k_dev_cleanup(dev);
-		return ENOMEM;
-	}
-	nic_set_ddf_fun(nic_data, fun);
-	fun->ops = &ne2k_dev_ops;
-	fun->driver_data = nic_data;
-	
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		ddf_fun_destroy(fun);
-		ne2k_dev_cleanup(dev);
-		return rc;
-	}
-	
-	rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC);
-	if (rc != EOK) {
-		ddf_fun_unbind(fun);
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
 	return EOK;
 }
Index: uspace/drv/nic/rtl8139/defs.h
===================================================================
--- uspace/drv/nic/rtl8139/defs.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/nic/rtl8139/defs.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -29,33 +29,29 @@
 /** @file rtl8139_defs.h
  *
- * Registers, bit positions and masks definition
- * of the RTL8139 network family cards
- */
-
-#ifndef RTL8139_DEFS_H_
-#define RTL8139_DEFS_H_
-
+ *  Registers, bit positions and masks definition of the RTL8139 network family 
+ *  cards
+ */
+
+#ifndef RTL8139_DEFS_H_INCLUDED_
+#define RTL8139_DEFS_H_INCLUDED_
 #include <sys/types.h>
 #include <libarch/ddi.h>
 
-/** Size of RTL8139 registers address space */
-#define RTL8139_IO_SIZE  256
-
-/** Maximal transmitted frame length
- *
- * Maximal transmitted frame length in bytes
- * allowed according to the RTL8139 documentation
- * (see SIZE part of TSD documentation).
- *
- */
-#define RTL8139_FRAME_MAX_LENGTH  1792
+
+/** The size of RTL8139 registers address space */
+#define RTL8139_IO_SIZE 256
+
+/** The maximal transmitted packet length in bytes allowed according to RTL8139
+ *  documentation (see SIZE part of TSD documentation)
+ */
+#define RTL8139_PACKET_MAX_LENGTH 1792
+
 
 /** HW version
  *
- * As can be detected from HWVERID part of TCR
- * (Transmit Configuration Register).
- *
- */
-typedef enum {
+ *  as can be detected from HWVERID part of TCR
+ *  (Transmit Configuration Register)
+ */
+enum rtl8139_version_id {
 	RTL8139 = 0,          /**< RTL8139 */
 	RTL8139A,             /**< RTL8139A */
@@ -70,5 +66,7 @@
 	RTL8101,              /**< RTL8101 */
 	RTL8139_VER_COUNT     /**< Count of known RTL versions, the last value */
-} rtl8139_version_id_t;
+};
+
+extern const char* model_names[RTL8139_VER_COUNT];
 
 /** Registers of RTL8139 family card offsets from the memory address base */
@@ -77,5 +75,5 @@
 	MAC0  = IDR0,    /**< Alias for IDR0 */
 
-	// 0x06 - 0x07 reserved
+	// 0x6 - 0x7 reserved
 
 	MAR0    = 0x08,  /**< Multicast mask registers 8 1b registers sequence */
@@ -96,5 +94,5 @@
 
 	CR      = 0x37,  /**< Command register, 1b */
-	CAPR    = 0x38,  /**< Current address of frame read, 2b */
+	CAPR    = 0x38,  /**< Current address of packet read, 2b */
 	CBA     = 0x3a,  /**< Current buffer address, 2b */
 
@@ -215,5 +213,4 @@
 	pio_write_8(io_base + CR9346, RTL8139_REGS_LOCKED);
 }
-
 /** Allow to change Config0-4 and BMCR register  */
 static inline void rtl8139_regs_unlock(void *io_base)
@@ -285,5 +282,5 @@
 	RCR_MulERINT = 1 << 17,    /**< Multiple early interrupt select */
 
-	/** Minimal error frame length (1 = 8B, 0 = 64B). If AER/AR is set, RER8
+	/** Minimal error packet length (1 = 8B, 0 = 64B). If AER/AR is set, RER8
 	 * is "Don't care"
 	 */
@@ -305,10 +302,10 @@
 
 	RCR_WRAP              = 1 << 7,  /**< Rx buffer wrapped */
-	RCR_ACCEPT_ERROR      = 1 << 5,  /**< Accept error frame */
-	RCR_ACCEPT_RUNT       = 1 << 4,  /**< Accept Runt (8-64 bytes) frames */
+	RCR_ACCEPT_ERROR      = 1 << 5,  /**< Accept error packet */
+	RCR_ACCEPT_RUNT       = 1 << 4,  /**< Accept Runt (8-64 bytes) packets */
 	RCR_ACCEPT_BROADCAST  = 1 << 3,  /**< Accept broadcast */
 	RCR_ACCEPT_MULTICAST  = 1 << 2,  /**< Accept multicast */
 	RCR_ACCEPT_PHYS_MATCH = 1 << 1,  /**< Accept device MAC address match */
-	RCR_ACCEPT_ALL_PHYS   = 1 << 0,  /**< Accept all frames with 
+	RCR_ACCEPT_ALL_PHYS   = 1 << 0,  /**< Accept all packets with 
 	                                  * phys. desticnation 
 									  */
@@ -365,5 +362,5 @@
 	ANAR_ACK          = (1 << 14),  /**< Capability reception acknowledge */
 	ANAR_REMOTE_FAULT = (1 << 13),  /**< Remote fault detection capability */
-	ANAR_PAUSE        = (1 << 10),  /**< Symetric pause frame capability */
+	ANAR_PAUSE        = (1 << 10),  /**< Symetric pause packet capability */
 	ANAR_100T4        = (1 << 9),   /**< T4, not supported by the device */
 	ANAR_100TX_FD     = (1 << 8),   /**< 100BASE_TX full duplex */
@@ -402,5 +399,5 @@
 	CONFIG3_GNT_SELECT = (1 << 7),  /**< Gnt select */
 	CONFIG3_PARM_EN    = (1 << 6),  /**< Parameter enabled (100MBit mode) */
-	CONFIG3_MAGIC      = (1 << 5),  /**< WoL Magic frame enable */
+	CONFIG3_MAGIC      = (1 << 5),  /**< WoL Magic packet enable */
 	CONFIG3_LINK_UP    = (1 << 4),  /**< Wakeup if link is reestablished */
 	CONFIG3_CLKRUN_EN  = (1 << 2),  /**< CLKRUN enabled */ /* TODO: check what does it mean */
@@ -419,9 +416,9 @@
 };
 
-/** Maximal runt frame size + 1 */
-#define RTL8139_RUNT_MAX_SIZE  64
-
-/** Bits in frame header */
-enum rtl8139_frame_header {
+/** Maximal runt packet size + 1 */
+#define RTL8139_RUNT_MAX_SIZE 64
+
+/** Bits in packet header */
+enum rtl8139_packet_header {
 	RSR_MAR  = (1 << 15),  /**< Multicast received */
 	RSR_PAM  = (1 << 14),  /**< Physical address match */
@@ -429,10 +426,10 @@
 
 	RSR_ISE  = (1 << 5),   /**< Invalid symbol error, 100BASE-TX only */
-	RSR_RUNT = (1 << 4),   /**< Runt frame (< RTL8139_RUNT_MAX_SIZE bytes) */
-
-	RSR_LONG = (1 << 3),   /**< Long frame (size > 4k bytes) */
+	RSR_RUNT = (1 << 4),   /**< Runt packet (< RTL8139_RUNT_MAX_SIZE bytes) */
+
+	RSR_LONG = (1 << 3),   /**< Long packet (size > 4k bytes) */
 	RSR_CRC  = (1 << 2),   /**< CRC error */
 	RSR_FAE  = (1 << 1),   /**< Frame alignment error */
-	RSR_ROK  = (1 << 0)    /**< Good frame received */
+	RSR_ROK  = (1 << 0)    /**< Good packet received */
 };
 
@@ -454,5 +451,5 @@
 									  */
 
-	APPEND_CRC = 1 << 16,        /**< Append CRC at the end of a frame */
+	APPEND_CRC = 1 << 16,        /**< Append CRC at the end of a packet */
 
 	MXTxDMA_SHIFT = 8,  /**< Max. DMA Burst per TxDMA shift, burst = 16^value */
@@ -462,5 +459,5 @@
 	TX_RETRY_COUNT_SIZE  = 4,            /**< Retries before aborting size */
 
-	CLEAR_ABORT = 1 << 0    /**< Retransmit aborted frame at the last 
+	CLEAR_ABORT = 1 << 0    /**< Retransmit aborted packet at the last 
 	                          *  transmitted descriptor 
 							  */
@@ -473,21 +470,19 @@
 
 /** Mapping of HW version -> version ID */
-struct rtl8139_hwver_map {
-	uint32_t hwverid;             /**< HW version value in the register */
-	rtl8139_version_id_t ver_id;  /**< appropriate version id */
+struct rtl8139_hwver_map { 
+	uint32_t hwverid;                /**< HW version value in the register */
+	enum rtl8139_version_id ver_id;  /**< appropriate version id */
 };
 
 /** Mapping of HW version -> version ID */
 extern const struct rtl8139_hwver_map rtl8139_versions[RTL8139_VER_COUNT + 1];
-extern const char* model_names[RTL8139_VER_COUNT];
-
-/** Size in the frame header while copying from RxFIFO to Rx buffer */
-#define RTL8139_EARLY_SIZE  UINT16_C(0xfff0)
-
-/** The only supported pause frame time value */
-#define RTL8139_PAUSE_VAL  UINT16_C(0xFFFF)
-
-/** Size of the frame header in front of the received frame */
-#define RTL_FRAME_HEADER_SIZE  4
+
+/** Size in the packet header while copying from RxFIFO to Rx buffer */
+#define RTL8139_EARLY_SIZE UINT16_C(0xfff0)
+/** The only supported pause packet time value */
+#define RTL8139_PAUSE_VAL UINT16_C(0xFFFF)
+
+/** Size of the packet header in front of the received frame */
+#define RTL_PACKET_HEADER_SIZE 4
 
 /** 8k buffer */
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -39,4 +39,5 @@
 #include <io/log.h>
 #include <nic.h>
+#include <packet_client.h>
 #include <device/pci.h>
 
@@ -55,28 +56,21 @@
 /** Global mutex for work with shared irq structure */
 FIBRIL_MUTEX_INITIALIZE(irq_reg_lock);
-
 /** Lock interrupt structure mutex */
-#define RTL8139_IRQ_STRUCT_LOCK() \
-	fibril_mutex_lock(&irq_reg_lock)
-
+#define RTL8139_IRQ_STRUCT_LOCK() fibril_mutex_lock(&irq_reg_lock)
 /** Unlock interrupt structure mutex */
-#define RTL8139_IRQ_STRUCT_UNLOCK() \
-	fibril_mutex_unlock(&irq_reg_lock)
+#define RTL8139_IRQ_STRUCT_UNLOCK() fibril_mutex_unlock(&irq_reg_lock)
 
 /** PCI clock frequency in kHz */
-#define RTL8139_PCI_FREQ_KHZ  33000
-
-#define RTL8139_AUTONEG_CAPS (ETH_AUTONEG_10BASE_T_HALF | \
-	ETH_AUTONEG_10BASE_T_FULL | ETH_AUTONEG_100BASE_TX_HALF | \
-	ETH_AUTONEG_100BASE_TX_FULL | ETH_AUTONEG_PAUSE_SYMETRIC)
+#define RTL8139_PCI_FREQ_KHZ 33000
+
+#define RTL8139_AUTONEG_CAPS (ETH_AUTONEG_10BASE_T_HALF \
+    | ETH_AUTONEG_10BASE_T_FULL | ETH_AUTONEG_100BASE_TX_HALF \
+    | ETH_AUTONEG_100BASE_TX_FULL | ETH_AUTONEG_PAUSE_SYMETRIC)
 
 /** Lock transmitter and receiver data
- *
- * This function shall be called whenever
- * both transmitter and receiver locking
- * to force safe lock ordering (deadlock prevention)
- *
- * @param rtl8139 RTL8139 private data
- *
+ *  This function shall be called whenever both transmitter and receiver locking
+ *  to force safe lock ordering (deadlock prevention)
+ *
+ *  @param rtl8139  RTL8139 private data
  */
 inline static void rtl8139_lock_all(rtl8139_t *rtl8139)
@@ -89,6 +83,5 @@
 /** Unlock transmitter and receiver data
  *
- * @param rtl8139 RTL8139 private data
- *
+ *  @param rtl8139  RTL8139 private data
  */
 inline static void rtl8139_unlock_all(rtl8139_t *rtl8139)
@@ -159,5 +152,5 @@
 }
 
-/** Update the mask of accepted frames in the RCR register according to
+/** Update the mask of accepted packets in the RCR register according to
  * rcr_accept_mode value in rtl8139_t
  *
@@ -177,5 +170,5 @@
 }
 
-/** Fill the mask of accepted multicast frames in the card registers
+/** Fill the mask of accepted multicast packets in the card registers
  *
  *  @param rtl8139  The rtl8139 private data
@@ -401,5 +394,5 @@
 #define rtl8139_tbuf_busy(tsd) ((pio_read_32(tsd) & TSD_OWN) == 0)
 
-/** Send frame with the hardware
+/** Send packet with the hardware
  *
  * note: the main_lock is locked when framework calls this function
@@ -419,5 +412,5 @@
 	ddf_msg(LVL_DEBUG, "Sending frame");
 
-	if (size > RTL8139_FRAME_MAX_LENGTH) {
+	if (size > RTL8139_PACKET_MAX_LENGTH) {
 		ddf_msg(LVL_ERROR, "Send frame: frame too long, %zu bytes",
 		    size);
@@ -444,5 +437,5 @@
 	fibril_mutex_unlock(&rtl8139->tx_lock);
 
-	/* Get address of the buffer descriptor and frame data */
+	/* Get address of the buffer descriptor and packet data */
 	void *tsd = rtl8139->io_port + TSD0 + tx_curr * 4;
 	void *buf_addr = rtl8139->tx_buff[tx_curr];
@@ -465,5 +458,5 @@
 	pio_write_32(tsd, tsd_value);
 	return;
-	
+
 err_busy_no_inc:
 err_size:
@@ -512,26 +505,32 @@
 }
 
-/** Create frame structure from the buffer data
+/** Create packet structure from the buffer data
  *
  * @param nic_data      NIC driver data
  * @param rx_buffer     The receiver buffer
  * @param rx_size       The buffer size
- * @param frame_start   The offset where packet data start
- * @param frame_size    The size of the frame data
- *
- * @return The frame list node (not connected)
- *
- */
-static nic_frame_t *rtl8139_read_frame(nic_t *nic_data,
-    void *rx_buffer, size_t rx_size, size_t frame_start, size_t frame_size)
-{
-	nic_frame_t *frame = nic_alloc_frame(nic_data, frame_size);
+ * @param packet_start  The offset where packet data start
+ * @param packet_size   The size of the packet data
+ *
+ * @return The packet   list node (not connected)
+ */
+static nic_frame_t *rtl8139_read_packet(nic_t *nic_data,
+    void *rx_buffer, size_t rx_size, size_t packet_start, size_t packet_size)
+{
+	nic_frame_t *frame = nic_alloc_frame(nic_data, packet_size);
 	if (! frame) {
-		ddf_msg(LVL_ERROR, "Can not allocate frame for received frame.");
+		ddf_msg(LVL_ERROR, "Can not allocate frame for received packet.");
 		return NULL;
 	}
 
-	void *ret = rtl8139_memcpy_wrapped(frame->data, rx_buffer, frame_start,
-	    RxBUF_SIZE, frame_size);
+	void *packet_data = packet_suffix(frame->packet, packet_size);
+	if (!packet_data) {
+		ddf_msg(LVL_ERROR, "Can not get the packet suffix.");
+		nic_release_frame(nic_data, frame);
+		return NULL;
+	}
+
+	void *ret = rtl8139_memcpy_wrapped(packet_data, rx_buffer, packet_start,
+	    RxBUF_SIZE, packet_size);
 	if (ret == NULL) {
 		nic_release_frame(nic_data, frame);
@@ -569,10 +568,10 @@
 }
 
-/** Receive all frames in queue
+/** Receive all packets in queue
  *
  *  @param nic_data  The controller data
- *  @return The linked list of nic_frame_list_t nodes, each containing one frame
- */
-static nic_frame_list_t *rtl8139_frame_receive(nic_t *nic_data)
+ *  @return The linked list of packet_list_t nodes, each containing one packet
+ */
+static nic_frame_list_t *rtl8139_packet_receive(nic_t *nic_data)
 {
 	rtl8139_t *rtl8139 = nic_get_specific(nic_data);
@@ -582,5 +581,5 @@
 	nic_frame_list_t *frames = nic_alloc_frame_list();
 	if (!frames)
-		ddf_msg(LVL_ERROR, "Can not allocate frame list for received frames.");
+		ddf_msg(LVL_ERROR, "Can not allocate frame list for received packets.");
 
 	void *rx_buffer = rtl8139->rx_buff_virt;
@@ -606,12 +605,12 @@
 	while (!rtl8139_hw_buffer_empty(rtl8139)) {
 		void *rx_ptr = rx_buffer + rx_offset % RxBUF_SIZE;
-		uint32_t frame_header = uint32_t_le2host( *((uint32_t*)rx_ptr) );
-		uint16_t size = frame_header >> 16;
-		uint16_t frame_size = size - RTL8139_CRC_SIZE;
-		/* received frame flags in frame header */
-		uint16_t rcs = (uint16_t) frame_header;
+		uint32_t packet_header = uint32_t_le2host( *((uint32_t*)rx_ptr) );
+		uint16_t size = packet_header >> 16;
+		uint16_t packet_size = size - RTL8139_CRC_SIZE;
+		/* received packet flags in packet header */
+		uint16_t rcs = (uint16_t) packet_header;
 
 		if (size == RTL8139_EARLY_SIZE) {
-			/* The frame copying is still in progress, break receiving */
+			/* The packet copying is still in progress, break receiving */
 			ddf_msg(LVL_DEBUG, "Early threshold reached, not completely coppied");
 			break;
@@ -619,7 +618,7 @@
 
 		/* Check if the header is valid, otherwise we are lost in the buffer */
-		if (size == 0 || size > RTL8139_FRAME_MAX_LENGTH) {
+		if (size == 0 || size > RTL8139_PACKET_MAX_LENGTH) {
 			ddf_msg(LVL_ERROR, "Receiver error -> receiver reset (size: %4"PRIu16", "
-			    "header 0x%4"PRIx16". Offset: %zu)", size, frame_header, 
+			    "header 0x%4"PRIx16". Offset: %zu)", size, packet_header, 
 			    rx_offset);
 			goto rx_err;
@@ -630,11 +629,11 @@
 		}
 
-		cur_read += size + RTL_FRAME_HEADER_SIZE;
+		cur_read += size + RTL_PACKET_HEADER_SIZE;
 		if (cur_read > max_read)
 			break;
 
 		if (frames) {
-			nic_frame_t *frame = rtl8139_read_frame(nic_data, rx_buffer,
-			    RxBUF_SIZE, rx_offset + RTL_FRAME_HEADER_SIZE, frame_size);
+			nic_frame_t *frame = rtl8139_read_packet(nic_data, rx_buffer,
+			    RxBUF_SIZE, rx_offset + RTL_PACKET_HEADER_SIZE, packet_size);
 
 			if (frame)
@@ -643,7 +642,7 @@
 
 		/* Update offset */
-		rx_offset = ALIGN_UP(rx_offset + size + RTL_FRAME_HEADER_SIZE, 4);
-
-		/* Write lesser value to prevent overflow into unread frame
+		rx_offset = ALIGN_UP(rx_offset + size + RTL_PACKET_HEADER_SIZE, 4);
+
+		/* Write lesser value to prevent overflow into unread packet
 		 * (the recomendation from the RealTech rtl8139 programming guide)
 		 */
@@ -728,5 +727,5 @@
 		tx_used++;
 
-		/* If the frame was sent */
+		/* If the packet was sent */
 		if (tsd_value & TSD_TOK) {
 			size_t size = REG_GET_VAL(tsd_value, TSD_SIZE);
@@ -758,9 +757,9 @@
 }
 
-/** Receive all frames from the buffer
+/** Receive all packets from the buffer
  *
  *  @param rtl8139  driver private data
  */
-static void rtl8139_receive_frames(nic_t *nic_data)
+static void rtl8139_receive_packets(nic_t *nic_data)
 {
 	assert(nic_data);
@@ -770,5 +769,5 @@
 
 	fibril_mutex_lock(&rtl8139->rx_lock);
-	nic_frame_list_t *frames = rtl8139_frame_receive(nic_data);
+	nic_frame_list_t *frames = rtl8139_packet_receive(nic_data);
 	fibril_mutex_unlock(&rtl8139->rx_lock);
 
@@ -826,5 +825,5 @@
 	}
 
-	/* Check transmittion interrupts first to allow transmit next frames
+	/* Check transmittion interrupts first to allow transmit next packets
 	 * sooner
 	 */
@@ -833,5 +832,5 @@
 	}
 	if (isr & INT_ROK) {
-		rtl8139_receive_frames(nic_data);
+		rtl8139_receive_packets(nic_data);
 	}
 	if (isr & (INT_RER | INT_RXOVW | INT_FIFOOVW)) {
@@ -934,5 +933,5 @@
 }
 
-/** Activate the device to receive and transmit frames
+/** Activate the device to receive and transmit packets
  *
  *  @param nic_data  The nic driver data
@@ -1214,15 +1213,15 @@
 		goto failed;
 
-	/* Set default frame acceptance */
+	/* Set default packet acceptance */
 	rtl8139->rcr_data.ucast_mask = RTL8139_RCR_UCAST_DEFAULT;
 	rtl8139->rcr_data.mcast_mask = RTL8139_RCR_MCAST_DEFAULT;
 	rtl8139->rcr_data.bcast_mask = RTL8139_RCR_BCAST_DEFAULT;
 	rtl8139->rcr_data.defect_mask = RTL8139_RCR_DEFECT_DEFAULT;
-	/* Set receiver early treshold to 8/16 of frame length */
+	/* Set receiver early treshold to 8/16 of packet length */
 	rtl8139->rcr_data.rcr_base = (0x8 << RCR_ERTH_SHIFT);
 
 	ddf_msg(LVL_DEBUG, "The device is initialized");
 	return ret;
-	
+
 failed:
 	ddf_msg(LVL_ERROR, "The device initialization failed");
@@ -1289,6 +1288,4 @@
 int rtl8139_dev_add(ddf_dev_t *dev)
 {
-	ddf_fun_t *fun;
-
 	assert(dev);
 	ddf_msg(LVL_NOTE, "RTL8139_dev_add %s (handle = %d)", dev->name, dev->handle);
@@ -1327,22 +1324,8 @@
 	}
 
-	fun = ddf_fun_create(nic_get_ddf_dev(nic_data), fun_exposed, "port0");
-	if (fun == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating device function");
-		goto err_srv;
-	}
-	nic_set_ddf_fun(nic_data, fun);
-	fun->ops = &rtl8139_dev_ops;
-	fun->driver_data = nic_data;
-
-	rc = ddf_fun_bind(fun);
+	rc = nic_register_as_ddf_fun(nic_data, &rtl8139_dev_ops);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding device function");
-		goto err_fun_create;
-	}
-	rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed adding function to category");
-		goto err_fun_bind;
+		ddf_msg(LVL_ERROR, "Failed to register as DDF function - error %d", rc);
+		goto err_irq;
 	}
 
@@ -1351,11 +1334,5 @@
 
 	return EOK;
-	
-err_fun_bind:
-	ddf_fun_unbind(fun);
-err_fun_create:
-	ddf_fun_destroy(fun);
-err_srv:
-	/* XXX Disconnect from services */
+
 err_irq:
 	unregister_interrupt_handler(dev, rtl8139->irq);
@@ -1500,5 +1477,5 @@
 };
 
-/** Check if pause frame operations are valid in current situation 
+/** Check if pause packet operations are valid in current situation 
  *
  *  @param rtl8139  RTL8139 private structure
@@ -1525,5 +1502,5 @@
 }
 
-/** Get current pause frame configuration
+/** Get current pause packet configuration
  *
  *  Values are filled with NIC_RESULT_NOT_AVAILABLE if the value has no sense in
@@ -1531,7 +1508,7 @@
  *
  *  @param[in]  fun         The DDF structure of the RTL8139
- *  @param[out] we_send     Sign if local constroller sends pause frame
- *  @param[out] we_receive  Sign if local constroller receives pause frame
- *  @param[out] time        Time filled in pause frames. 0xFFFF in rtl8139
+ *  @param[out] we_send     Sign if local constroller sends pause packets
+ *  @param[out] we_receive  Sign if local constroller receives pause packets
+ *  @param[out] time        Time filled in pause packets. 0xFFFF in rtl8139
  *
  *  @return EOK if succeed
@@ -1563,12 +1540,12 @@
 };
 
-/** Set current pause frame configuration
+/** Set current pause packet configuration
  *
  *  @param fun            The DDF structure of the RTL8139
- *  @param allow_send     Sign if local constroller sends pause frame
- *  @param allow_receive  Sign if local constroller receives pause frames
+ *  @param allow_send     Sign if local constroller sends pause packets
+ *  @param allow_receive  Sign if local constroller receives pause packets
  *  @param time           Time to use, ignored (not supported by device)
  *
- *  @return EOK if succeed, INVAL if the pause frame has no sence
+ *  @return EOK if succeed, INVAL if the pause packet has no sence
  */
 static int rtl8139_pause_set(ddf_fun_t *fun, int allow_send, int allow_receive, 
@@ -1819,5 +1796,5 @@
 }
 
-/** Set unicast frames acceptance mode
+/** Set unicast packets acceptance mode
  *
  *  @param nic_data  The nic device to update
@@ -1877,5 +1854,5 @@
 }
 
-/** Set multicast frames acceptance mode
+/** Set multicast packets acceptance mode
  *
  *  @param nic_data  The nic device to update
@@ -1922,5 +1899,5 @@
 }
 
-/** Set broadcast frames acceptance mode
+/** Set broadcast packets acceptance mode
  *
  *  @param nic_data  The nic device to update
@@ -1952,5 +1929,5 @@
 }
 
-/** Get state of acceptance of weird frames
+/** Get state of acceptance of weird packets
  *
  *  @param[in]  device  The device to check
@@ -1974,5 +1951,5 @@
 };
 
-/** Set acceptance of weird frames
+/** Set acceptance of weird packets
  *
  *  @param device  The device to update
@@ -2150,5 +2127,5 @@
 }
 
-/** Force receiving all frames in the receive buffer
+/** Force receiving all packets in the receive buffer
  *
  *  @param device  The device to receive
Index: uspace/drv/nic/rtl8139/driver.h
===================================================================
--- uspace/drv/nic/rtl8139/driver.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/nic/rtl8139/driver.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -30,40 +30,36 @@
 #define RTL8139_DRIVER_H_
 
+#include "defs.h"
+#include "general.h"
 #include <sys/types.h>
 #include <stdint.h>
-#include "defs.h"
-#include "general.h"
 
 /** The driver name */
-#define NAME  "rtl8139"
-
+#define NAME "rtl8139"
 /** Transmittion buffers count */
-#define TX_BUFF_COUNT  4
-
-/** Size of buffer for one frame (2kB) */
-#define TX_BUFF_SIZE  (2 * 1024)
-
-/** Number of pages to allocate for TxBuffers */
-#define TX_PAGES  2
+#define TX_BUFF_COUNT 4
+/** Size of buffer for one packet
+ *  - 2kB
+ */
+#define TX_BUFF_SIZE (2 * 1024)
+/** Count of pages to allocate for TxBuffers */
+#define TX_PAGES 2
 
 /** Size of the CRC after the received frame in the receiver buffer */
-#define RTL8139_CRC_SIZE  4
-
-/** The default mode of accepting unicast frames */
-#define RTL8139_RCR_UCAST_DEFAULT  RCR_ACCEPT_PHYS_MATCH
-
-/** The default mode of accepting multicast frames */
-#define RTL8139_RCR_MCAST_DEFAULT  0
-
-/** The default mode of accepting broadcast frames */
-#define RTL8139_RCR_BCAST_DEFAULT  RCR_ACCEPT_BROADCAST
-
-/** The default mode of accepting defect frames */
-#define RTL8139_RCR_DEFECT_DEFAULT  0
+#define RTL8139_CRC_SIZE 4
+
+/** The default mode of accepting unicast packets */
+#define RTL8139_RCR_UCAST_DEFAULT RCR_ACCEPT_PHYS_MATCH
+/** The default mode of accepting multicast packets */
+#define RTL8139_RCR_MCAST_DEFAULT 0
+/** The default mode of accepting broadcast packets */
+#define RTL8139_RCR_BCAST_DEFAULT RCR_ACCEPT_BROADCAST
+/** The default mode of accepting defect packets */
+#define RTL8139_RCR_DEFECT_DEFAULT 0
 
 /** Mask for accepting all multicast */
-#define RTL8139_MCAST_MASK_PROMISC  UINT64_MAX
-
-/** Data */
+#define RTL8139_MCAST_MASK_PROMISC UINT64_MAX
+
+/** Data  */
 struct rtl8139_rcr_data {
 	/** Configuration part of RCR */
@@ -116,5 +112,5 @@
 	size_t tx_used;
 
-	/** Buffer for receiving frames */
+	/** Buffer for receiving packets */
 	void *rx_buff_phys;
 	void *rx_buff_virt;
@@ -138,6 +134,7 @@
 
 	/** Version of RT8139 controller */
-	rtl8139_version_id_t hw_version;
+	enum rtl8139_version_id hw_version;
 } rtl8139_t;
+
 
 /* ***** Pointers casting - for both amd64 and ia32 ***** */
@@ -163,4 +160,6 @@
  */
 #define IOADDR_TO_PTR(ioaddr) ((void*)((size_t)(ioaddr)))
+
+
 
 /* ***** Bit operation macros ***** */
@@ -178,5 +177,5 @@
  * @return New value
  */
-#define bit_set_part_g(src, value, mask, type) \
+#define bit_set_part_g( src, value, mask, type ) \
 	((type)(((src) & ~((type)(mask))) | ((value) & (type)(mask))))
 
@@ -238,3 +237,4 @@
 	bit_set_part_32(tsd_value, (size) << TSD_SIZE_SHIFT, TSD_SIZE_MASK << TSD_SIZE_SHIFT)
 
+
 #endif
Index: uspace/drv/nic/rtl8139/general.h
===================================================================
--- uspace/drv/nic/rtl8139/general.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/drv/nic/rtl8139/general.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -29,5 +29,5 @@
 /** @file
  *
- * General functions and structures used in rtl8139 driver
+ *  General functions and structures used in rtl8139 driver
  */
 
@@ -37,30 +37,30 @@
 #include <unistd.h>
 
-/** Number of microseconds in second */
-#define RTL8139_USEC_IN_SEC  1000000
+extern void* rtl8139_memcpy_wrapped(void *dest, const void *src_buf,
+    size_t src_offset, size_t src_size, size_t data_size);
+
 
 /** Structure for HW timer control */
-typedef struct {
+typedef struct rtl8139_timer_act {
 	/** Register value set in the last timer period */
 	uint32_t last_val;
-	
 	/** Register value set in the common timer period */
 	uint32_t full_val;
-	
+
 	/** Amount of full register periods in timer period */
 	size_t full_skips;
-	
 	/** Remaining full register periods to the next period end */
 	size_t full_skips_remains;
-	
 	/** Mark if there is a last run */
 	int last_run;
 } rtl8139_timer_act_t;
 
-extern void *rtl8139_memcpy_wrapped(void *, const void *, size_t, size_t,
-    size_t);
-extern int rtl8139_timer_act_init(rtl8139_timer_act_t *, uint32_t,
-    const struct timeval *);
-extern int rtl8139_timer_act_step(rtl8139_timer_act_t *, uint32_t *);
+/** Count of microseconds in second */
+#define RTL8139_USEC_IN_SEC 1000000
+
+extern int rtl8139_timer_act_init(rtl8139_timer_act_t *ta, uint32_t timer_freq,
+    const struct timeval *time);
+extern int rtl8139_timer_act_step(rtl8139_timer_act_t *ta, uint32_t *new_reg);
+
 
 #endif
Index: uspace/lib/c/generic/device/nic.c
===================================================================
--- uspace/lib/c/generic/device/nic.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/c/generic/device/nic.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -73,7 +73,8 @@
 }
 
-/** Create callback connection from NIC service
- *
- * @param[in] dev_sess
+/** 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
  *
@@ -81,24 +82,13 @@
  *
  */
-int nic_callback_create(async_sess_t *dev_sess, async_client_conn_t cfun,
-    void *carg)
-{
-	ipc_call_t answer;
-	int rc;
-	sysarg_t retval;
-	
-	async_exch_t *exch = async_exchange_begin(dev_sess);
-	aid_t req = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
-	    NIC_CALLBACK_CREATE, &answer);
-	
-	rc = async_connect_to_me(exch, 0, 0, 0, cfun, carg);
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	async_exchange_end(exch);
-	
-	async_wait_for(req, &retval);
-	return (int) retval;
+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;
 }
 
@@ -345,5 +335,5 @@
  * it can never force the NIC to advertise unsupported modes.
  *
- * The allowed modes are defined in "nic/eth_phys.h" in the C library.
+ * The allowed modes are defined in "net/eth_phys.h" in the C library.
  *
  * @param[in] dev_sess
@@ -382,5 +372,5 @@
 /** Probe current state of auto-negotiation.
  *
- * Modes are defined in the "nic/eth_phys.h" in the C library.
+ * Modes are defined in the "net/eth_phys.h" in the C library.
  *
  * @param[in]  dev_sess
Index: uspace/lib/c/generic/loc.c
===================================================================
--- uspace/lib/c/generic/loc.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/c/generic/loc.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -47,5 +47,4 @@
 static FIBRIL_MUTEX_INITIALIZE(loc_callback_mutex);
 static bool loc_callback_created = false;
-static loc_cat_change_cb_t cat_change_cb = NULL;
 
 static async_sess_t *loc_supp_block_sess = NULL;
@@ -55,6 +54,10 @@
 static async_sess_t *loc_consumer_sess = NULL;
 
+static loc_cat_change_cb_t cat_change_cb = NULL;
+
 static void loc_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
+	loc_cat_change_cb_t cb_fun;
+	
 	while (true) {
 		ipc_call_t call;
@@ -66,19 +69,21 @@
 		}
 		
+		int retval;
+		
 		switch (IPC_GET_IMETHOD(call)) {
 		case LOC_EVENT_CAT_CHANGE:
 			fibril_mutex_lock(&loc_callback_mutex);
-			loc_cat_change_cb_t cb_fun = cat_change_cb;
+			cb_fun = cat_change_cb;
+			if (cb_fun != NULL) {
+				(*cb_fun)();
+			}
 			fibril_mutex_unlock(&loc_callback_mutex);
-			
-			async_answer_0(callid, EOK);
-			
-			if (cb_fun != NULL)
-				(*cb_fun)();
-			
+			retval = 0;
 			break;
 		default:
-			async_answer_0(callid, ENOTSUP);
+			retval = ENOTSUP;
 		}
+		
+		async_answer_0(callid, retval);
 	}
 }
@@ -96,34 +101,36 @@
 }
 
-/** Create callback
- *
- * Must be called with loc_callback_mutex locked.
- *
- * @return EOK on success.
- *
- */
 static int loc_callback_create(void)
 {
+	async_exch_t *exch;
+	sysarg_t retval;
+	int rc = EOK;
+
+	fibril_mutex_lock(&loc_callback_mutex);
+	
 	if (!loc_callback_created) {
-		async_exch_t *exch =
-		    loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
 		
 		ipc_call_t answer;
 		aid_t req = async_send_0(exch, LOC_CALLBACK_CREATE, &answer);
-		int rc = async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);
+		async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);
 		loc_exchange_end(exch);
 		
+		async_wait_for(req, &retval);
 		if (rc != EOK)
-			return rc;
-		
-		sysarg_t retval;
-		async_wait_for(req, &retval);
-		if (retval != EOK)
-			return retval;
+			goto done;
+		
+		if (retval != EOK) {
+			rc = retval;
+			goto done;
+		}
 		
 		loc_callback_created = true;
 	}
 	
-	return EOK;
+	rc = EOK;
+done:
+	fibril_mutex_unlock(&loc_callback_mutex);
+	return rc;
 }
 
@@ -788,18 +795,22 @@
     sysarg_t **data, size_t *count)
 {
+	service_id_t *ids;
+	size_t act_size;
+	size_t alloc_size;
+	int rc;
+
 	*data = NULL;
-	*count = 0;
-	
-	size_t act_size = 0;
-	int rc = loc_category_get_ids_once(method, arg1, NULL, 0,
+	act_size = 0;	/* silence warning */
+
+	rc = loc_category_get_ids_once(method, arg1, NULL, 0,
 	    &act_size);
 	if (rc != EOK)
 		return rc;
-	
-	size_t alloc_size = act_size;
-	service_id_t *ids = malloc(alloc_size);
+
+	alloc_size = act_size;
+	ids = malloc(alloc_size);
 	if (ids == NULL)
 		return ENOMEM;
-	
+
 	while (true) {
 		rc = loc_category_get_ids_once(method, arg1, ids, alloc_size,
@@ -807,14 +818,16 @@
 		if (rc != EOK)
 			return rc;
-		
+
 		if (act_size <= alloc_size)
 			break;
-		
-		alloc_size = act_size;
-		ids = realloc(ids, alloc_size);
+
+		alloc_size *= 2;
+		free(ids);
+
+		ids = malloc(alloc_size);
 		if (ids == NULL)
 			return ENOMEM;
 	}
-	
+
 	*count = act_size / sizeof(category_id_t);
 	*data = ids;
@@ -854,13 +867,8 @@
 int loc_register_cat_change_cb(loc_cat_change_cb_t cb_fun)
 {
-	fibril_mutex_lock(&loc_callback_mutex);
-	if (loc_callback_create() != EOK) {
-		fibril_mutex_unlock(&loc_callback_mutex);
+	if (loc_callback_create() != EOK)
 		return EIO;
-	}
-	
+
 	cat_change_cb = cb_fun;
-	fibril_mutex_unlock(&loc_callback_mutex);
-	
 	return EOK;
 }
Index: uspace/lib/c/include/device/nic.h
===================================================================
--- uspace/lib/c/include/device/nic.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/c/include/device/nic.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -37,10 +37,11 @@
 
 #include <async.h>
-#include <nic/nic.h>
-#include <ipc/common.h>
+#include <net/device.h>
+#include <net/packet.h>
+#include <ipc/services.h>
 
 typedef enum {
 	NIC_SEND_MESSAGE = 0,
-	NIC_CALLBACK_CREATE,
+	NIC_CONNECT_TO_NIL,
 	NIC_GET_STATE,
 	NIC_SET_STATE,
@@ -84,12 +85,6 @@
 } nic_funcs_t;
 
-typedef enum {
-	NIC_EV_ADDR_CHANGED = IPC_FIRST_USER_METHOD,
-	NIC_EV_RECEIVED,
-	NIC_EV_DEVICE_STATE
-} nic_event_t;
-
 extern int nic_send_frame(async_sess_t *, void *, size_t);
-extern int nic_callback_create(async_sess_t *, async_client_conn_t, void *);
+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);
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/c/include/ipc/devman.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -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/net.h
===================================================================
--- uspace/lib/c/include/ipc/net.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/c/include/ipc/net.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -305,5 +305,5 @@
  *
  */
-#define IPC_GET_DEVICE_HANDLE(call)  ((service_id_t) IPC_GET_ARG2(call))
+#define IPC_GET_DEVICE_HANDLE(call)  ((devman_handle_t) IPC_GET_ARG2(call))
 
 /** Return the device driver service message argument.
Index: uspace/lib/c/include/ipc/net_net.h
===================================================================
--- uspace/lib/c/include/ipc/net_net.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/c/include/ipc/net_net.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -54,5 +54,7 @@
 	NET_NET_GET_DEVICES_COUNT,
 	/** Return names and device IDs of all devices */
-	NET_NET_GET_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 e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/c/include/ipc/nil.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -46,4 +46,12 @@
 	 */
 	NET_NIL_DEVICE = NET_NIL_FIRST,
+	/** New device state message.
+	 * @see nil_device_state_msg()
+	 */
+	NET_NIL_DEVICE_STATE,
+	/** Received packet queue message.
+	 * @see nil_received_msg()
+	 */
+	NET_NIL_RECEIVED,
 	/** Send packet queue message.
 	 * @see nil_send_msg()
@@ -61,5 +69,9 @@
 	 * @see nil_get_broadcast_addr()
 	 */
-	NET_NIL_BROADCAST_ADDR
+	NET_NIL_BROADCAST_ADDR,
+	/** Device has changed address
+	 * @see nil_addr_changed_msg()
+	 */
+	NET_NIL_ADDR_CHANGED
 } nil_messages;
 
Index: uspace/lib/c/include/net/device.h
===================================================================
--- uspace/lib/c/include/net/device.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/c/include/net/device.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Lukas Mejdrech
+ * Copyright (c) 2011 Radim Vansa
  * All rights reserved.
  *
@@ -32,12 +33,31 @@
 
 /** @file
- * Network device.
- */
-
-#ifndef LIBC_NET_DEVICE_H_
-#define LIBC_NET_DEVICE_H_
+ * Device identifier, state and usage statistics.
+ */
+
+#ifndef LIBC_DEVICE_ID_TYPE_H_
+#define LIBC_DEVICE_ID_TYPE_H_
 
 #include <adt/int_map.h>
-#include <nic/nic.h>
+#include <net/eth_phys.h>
+#include <bool.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]
+
+/* Compare MAC address with specific value */
+#define MAC_EQUALS_VALUE(__a, __a0, __a1, __a2, __a3, __a4, __a5) \
+	((__a)[0] == (__a0) && (__a)[1] == (__a1) && (__a)[2] == (__a2) \
+	&& (__a)[3] == (__a3) && (__a)[4] == (__a4) && (__a)[5] == (__a5))
+
+#define MAC_IS_ZERO(__x) \
+	MAC_EQUALS_VALUE(__x, 0, 0, 0, 0, 0, 0)
 
 /** Device identifier to generic type map declaration. */
@@ -47,9 +67,419 @@
 #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 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
+
+#define NIC_DEFECTIVE_LONG               0x0001
+#define NIC_DEFECTIVE_SHORT              0x0002
+#define NIC_DEFECTIVE_BAD_CRC            0x0010
+#define NIC_DEFECTIVE_BAD_IPV4_CHECKSUM  0x0020
+#define NIC_DEFECTIVE_BAD_IPV6_CHECKSUM  0x0040
+#define NIC_DEFECTIVE_BAD_TCP_CHECKSUM   0x0080
+#define NIC_DEFECTIVE_BAD_UDP_CHECKSUM   0x0100
+
+/**
+ * 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 nic_device_id_t;
 
-/** Invalid device identifier. */
-#define NIC_DEVICE_INVALID_ID  (-1)
+/**
+ * Structure covering the MAC address.
+ */
+typedef struct nic_address {
+	uint8_t address[ETH_ADDR];
+} nic_address_t;
+
+/** Device state. */
+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. */
+typedef struct nic_device_stats {
+	/** Total packets received (accepted). */
+	unsigned long receive_packets;
+	/** Total packets transmitted. */
+	unsigned long send_packets;
+	/** Total bytes received (accepted). */
+	unsigned long receive_bytes;
+	/** Total bytes transmitted. */
+	unsigned long send_bytes;
+	/** Bad packets received counter. */
+	unsigned long receive_errors;
+	/** Packet transmition problems counter. */
+	unsigned long send_errors;
+	/** Number of frames dropped due to insufficient space in RX buffers */
+	unsigned long receive_dropped;
+	/** Number of frames dropped due to insufficient space in TX buffers */
+	unsigned long send_dropped;
+	/** 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 */
+
+	/** Received packet length error counter. */
+	unsigned long receive_length_errors;
+	/** Receiver buffer overflow counter. */
+	unsigned long receive_over_errors;
+	/** Received packet with crc error counter. */
+	unsigned long receive_crc_errors;
+	/** Received frame alignment error counter. */
+	unsigned long receive_frame_errors;
+	/** Receiver fifo overrun counter. */
+	unsigned long receive_fifo_errors;
+	/** Receiver missed packet counter. */
+	unsigned long receive_missed_errors;
+
+	/* detailed send_errors */
+
+	/** Transmitter aborted counter. */
+	unsigned long send_aborted_errors;
+	/** Transmitter carrier errors counter. */
+	unsigned long send_carrier_errors;
+	/** Transmitter fifo overrun counter. */
+	unsigned long send_fifo_errors;
+	/** Transmitter carrier errors counter. */
+	unsigned long send_heartbeat_errors;
+	/** Transmitter window errors counter. */
+	unsigned long send_window_errors;
+
+	/* for cslip etc */
+	
+	/** Total compressed packets received. */
+	unsigned long receive_compressed;
+	/** Total compressed packet transmitted. */
+	unsigned long send_compressed;
+} nic_device_stats_t;
+
+/** Errors corresponding to those in the nic_device_stats_t */
+typedef enum {
+	NIC_SEC_BUFFER_FULL,
+	NIC_SEC_ABORTED,
+	NIC_SEC_CARRIER_LOST,
+	NIC_SEC_FIFO_OVERRUN,
+	NIC_SEC_HEARTBEAT,
+	NIC_SEC_WINDOW_ERROR,
+	/* Error encountered during TX but with other type of error */
+	NIC_SEC_OTHER
+} nic_send_error_cause_t;
+
+/** Errors corresponding to those in the nic_device_stats_t */
+typedef enum {
+	NIC_REC_BUFFER_FULL,
+	NIC_REC_LENGTH,
+	NIC_REC_BUFFER_OVERFLOW,
+	NIC_REC_CRC,
+	NIC_REC_FRAME_ALIGNMENT,
+	NIC_REC_FIFO_OVERRUN,
+	NIC_REC_MISSED,
+	/* Error encountered during RX but with other type of error */
+	NIC_REC_OTHER
+} nic_receive_error_cause_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;
+
+/**
+ * Type of the ethernet frame
+ */
+typedef enum nic_frame_type {
+	NIC_FRAME_UNICAST,
+	NIC_FRAME_MULTICAST,
+	NIC_FRAME_BROADCAST
+} nic_frame_type_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;
+
+/**
+ * Structure passed as argument for virtue NIC_WV_MAGIC_PACKET.
+ */
+typedef struct nic_wv_magic_packet_data {
+	uint8_t password[6];
+} nic_wv_magic_packet_data_t;
+
+/**
+ * Structure passed as argument for virtue NIC_WV_DIRECTED_IPV4
+ */
+typedef struct nic_wv_ipv4_data {
+	uint8_t address[4];
+} nic_wv_ipv4_data_t;
+
+/**
+ * Structure passed as argument for virtue NIC_WV_DIRECTED_IPV6
+ */
+typedef struct nic_wv_ipv6_data {
+	uint8_t address[16];
+} nic_wv_ipv6_data_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;
+
+/**
+ * Says if this virtue type is a multi-virtue (there can be multiple virtues of
+ * this type at once).
+ *
+ * @param type
+ *
+ * @return true or false
+ */
+static inline int nic_wv_is_multi(nic_wv_type_t type) {
+	switch (type) {
+	case NIC_WV_FULL_MATCH:
+	case NIC_WV_DESTINATION:
+	case NIC_WV_DIRECTED_IPV4:
+	case NIC_WV_DIRECTED_IPV6:
+		return true;
+	default:
+		return false;
+	}
+}
+
+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 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
+++ uspace/lib/c/include/net/eth_phys.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -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: pace/lib/c/include/nic/eth_phys.h
===================================================================
--- uspace/lib/c/include/nic/eth_phys.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ 	(revision )
@@ -1,142 +1,0 @@
-/*
- * 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_NIC_ETH_PHYS_H_
-#define LIBC_NIC_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: pace/lib/c/include/nic/nic.h
===================================================================
--- uspace/lib/c/include/nic/nic.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ 	(revision )
@@ -1,475 +1,0 @@
-/*
- * 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 libc
- * @{
- */
-
-/** @file
- * NIC interface definitions.
- */
-
-#ifndef LIBC_NIC_H_
-#define LIBC_NIC_H_
-
-#include <nic/eth_phys.h>
-#include <bool.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]
-
-/* Compare MAC address with specific value */
-#define MAC_EQUALS_VALUE(__a, __a0, __a1, __a2, __a3, __a4, __a5) \
-	((__a)[0] == (__a0) && (__a)[1] == (__a1) && (__a)[2] == (__a2) \
-	&& (__a)[3] == (__a3) && (__a)[4] == (__a4) && (__a)[5] == (__a5))
-
-#define MAC_IS_ZERO(__x) \
-	MAC_EQUALS_VALUE(__x, 0, 0, 0, 0, 0, 0)
-
-/** Max length of any hw nic address (currently only eth) */
-#define NIC_MAX_ADDRESS_LENGTH  16
-
-#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
-
-#define NIC_DEFECTIVE_LONG               0x0001
-#define NIC_DEFECTIVE_SHORT              0x0002
-#define NIC_DEFECTIVE_BAD_CRC            0x0010
-#define NIC_DEFECTIVE_BAD_IPV4_CHECKSUM  0x0020
-#define NIC_DEFECTIVE_BAD_IPV6_CHECKSUM  0x0040
-#define NIC_DEFECTIVE_BAD_TCP_CHECKSUM   0x0080
-#define NIC_DEFECTIVE_BAD_UDP_CHECKSUM   0x0100
-
-/**
- * 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"
-
-/**
- * Structure covering the MAC address.
- */
-typedef struct nic_address {
-	uint8_t address[ETH_ADDR];
-} nic_address_t;
-
-/** Device state. */
-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. */
-typedef struct nic_device_stats {
-	/** Total packets received (accepted). */
-	unsigned long receive_packets;
-	/** Total packets transmitted. */
-	unsigned long send_packets;
-	/** Total bytes received (accepted). */
-	unsigned long receive_bytes;
-	/** Total bytes transmitted. */
-	unsigned long send_bytes;
-	/** Bad packets received counter. */
-	unsigned long receive_errors;
-	/** Packet transmition problems counter. */
-	unsigned long send_errors;
-	/** Number of frames dropped due to insufficient space in RX buffers */
-	unsigned long receive_dropped;
-	/** Number of frames dropped due to insufficient space in TX buffers */
-	unsigned long send_dropped;
-	/** 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 */
-
-	/** Received packet length error counter. */
-	unsigned long receive_length_errors;
-	/** Receiver buffer overflow counter. */
-	unsigned long receive_over_errors;
-	/** Received packet with crc error counter. */
-	unsigned long receive_crc_errors;
-	/** Received frame alignment error counter. */
-	unsigned long receive_frame_errors;
-	/** Receiver fifo overrun counter. */
-	unsigned long receive_fifo_errors;
-	/** Receiver missed packet counter. */
-	unsigned long receive_missed_errors;
-
-	/* detailed send_errors */
-
-	/** Transmitter aborted counter. */
-	unsigned long send_aborted_errors;
-	/** Transmitter carrier errors counter. */
-	unsigned long send_carrier_errors;
-	/** Transmitter fifo overrun counter. */
-	unsigned long send_fifo_errors;
-	/** Transmitter carrier errors counter. */
-	unsigned long send_heartbeat_errors;
-	/** Transmitter window errors counter. */
-	unsigned long send_window_errors;
-
-	/* for cslip etc */
-	
-	/** Total compressed packets received. */
-	unsigned long receive_compressed;
-	/** Total compressed packet transmitted. */
-	unsigned long send_compressed;
-} nic_device_stats_t;
-
-/** Errors corresponding to those in the nic_device_stats_t */
-typedef enum {
-	NIC_SEC_BUFFER_FULL,
-	NIC_SEC_ABORTED,
-	NIC_SEC_CARRIER_LOST,
-	NIC_SEC_FIFO_OVERRUN,
-	NIC_SEC_HEARTBEAT,
-	NIC_SEC_WINDOW_ERROR,
-	/* Error encountered during TX but with other type of error */
-	NIC_SEC_OTHER
-} nic_send_error_cause_t;
-
-/** Errors corresponding to those in the nic_device_stats_t */
-typedef enum {
-	NIC_REC_BUFFER_FULL,
-	NIC_REC_LENGTH,
-	NIC_REC_BUFFER_OVERFLOW,
-	NIC_REC_CRC,
-	NIC_REC_FRAME_ALIGNMENT,
-	NIC_REC_FIFO_OVERRUN,
-	NIC_REC_MISSED,
-	/* Error encountered during RX but with other type of error */
-	NIC_REC_OTHER
-} nic_receive_error_cause_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 nic/eth_phys.h of libc
-	 */
-	uint32_t autoneg_support;
-} nic_device_info_t;
-
-/**
- * Type of the ethernet frame
- */
-typedef enum nic_frame_type {
-	NIC_FRAME_UNICAST,
-	NIC_FRAME_MULTICAST,
-	NIC_FRAME_BROADCAST
-} nic_frame_type_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;
-
-/**
- * Structure passed as argument for virtue NIC_WV_MAGIC_PACKET.
- */
-typedef struct nic_wv_magic_packet_data {
-	uint8_t password[6];
-} nic_wv_magic_packet_data_t;
-
-/**
- * Structure passed as argument for virtue NIC_WV_DIRECTED_IPV4
- */
-typedef struct nic_wv_ipv4_data {
-	uint8_t address[4];
-} nic_wv_ipv4_data_t;
-
-/**
- * Structure passed as argument for virtue NIC_WV_DIRECTED_IPV6
- */
-typedef struct nic_wv_ipv6_data {
-	uint8_t address[16];
-} nic_wv_ipv6_data_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;
-
-/**
- * Says if this virtue type is a multi-virtue (there can be multiple virtues of
- * this type at once).
- *
- * @param type
- *
- * @return true or false
- */
-static inline int nic_wv_is_multi(nic_wv_type_t type) {
-	switch (type) {
-	case NIC_WV_FULL_MATCH:
-	case NIC_WV_DESTINATION:
-	case NIC_WV_DIRECTED_IPV4:
-	case NIC_WV_DIRECTED_IPV6:
-		return true;
-	default:
-		return false;
-	}
-}
-
-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/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/drv/Makefile	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -35,5 +35,4 @@
 	generic/driver.c \
 	generic/dev_iface.c \
-	generic/interrupt.c \
 	generic/log.c \
 	generic/logbuf.c \
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/drv/generic/driver.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -70,4 +70,18 @@
 FIBRIL_MUTEX_INITIALIZE(functions_mutex);
 
+/** Interrupts */
+static interrupt_context_list_t interrupt_contexts;
+
+static irq_cmd_t default_cmds[] = {
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static irq_code_t default_pseudocode = {
+	sizeof(default_cmds) / sizeof(irq_cmd_t),
+	default_cmds
+};
+
 static ddf_dev_t *create_device(void);
 static void delete_device(ddf_dev_t *);
@@ -79,4 +93,132 @@
 static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t);
 
+static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall)
+{
+	int id = (int)IPC_GET_IMETHOD(*icall);
+	interrupt_context_t *ctx;
+	
+	ctx = find_interrupt_context_by_id(&interrupt_contexts, id);
+	if (ctx != NULL && ctx->handler != NULL)
+		(*ctx->handler)(ctx->dev, iid, icall);
+}
+
+interrupt_context_t *create_interrupt_context(void)
+{
+	interrupt_context_t *ctx;
+	
+	ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t));
+	if (ctx != NULL)
+		memset(ctx, 0, sizeof(interrupt_context_t));
+	
+	return ctx;
+}
+
+void delete_interrupt_context(interrupt_context_t *ctx)
+{
+	if (ctx != NULL)
+		free(ctx);
+}
+
+void init_interrupt_context_list(interrupt_context_list_t *list)
+{
+	memset(list, 0, sizeof(interrupt_context_list_t));
+	fibril_mutex_initialize(&list->mutex);
+	list_initialize(&list->contexts);
+}
+
+void
+add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)
+{
+	fibril_mutex_lock(&list->mutex);
+	ctx->id = list->curr_id++;
+	list_append(&ctx->link, &list->contexts);
+	fibril_mutex_unlock(&list->mutex);
+}
+
+void remove_interrupt_context(interrupt_context_list_t *list,
+    interrupt_context_t *ctx)
+{
+	fibril_mutex_lock(&list->mutex);
+	list_remove(&ctx->link);
+	fibril_mutex_unlock(&list->mutex);
+}
+
+interrupt_context_t *
+find_interrupt_context_by_id(interrupt_context_list_t *list, int id)
+{
+	interrupt_context_t *ctx;
+	
+	fibril_mutex_lock(&list->mutex);
+	
+	list_foreach(list->contexts, link) {
+		ctx = list_get_instance(link, interrupt_context_t, link);
+		if (ctx->id == id) {
+			fibril_mutex_unlock(&list->mutex);
+			return ctx;
+		}
+	}
+	
+	fibril_mutex_unlock(&list->mutex);
+	return NULL;
+}
+
+interrupt_context_t *
+find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
+{
+	interrupt_context_t *ctx;
+	
+	fibril_mutex_lock(&list->mutex);
+	
+	list_foreach(list->contexts, link) {
+		ctx = list_get_instance(link, interrupt_context_t, link);
+		if (ctx->irq == irq && ctx->dev == dev) {
+			fibril_mutex_unlock(&list->mutex);
+			return ctx;
+		}
+	}
+	
+	fibril_mutex_unlock(&list->mutex);
+	return NULL;
+}
+
+
+int
+register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler,
+    irq_code_t *pseudocode)
+{
+	interrupt_context_t *ctx = create_interrupt_context();
+	
+	ctx->dev = dev;
+	ctx->irq = irq;
+	ctx->handler = handler;
+	
+	add_interrupt_context(&interrupt_contexts, ctx);
+	
+	if (pseudocode == NULL)
+		pseudocode = &default_pseudocode;
+	
+	int res = irq_register(irq, dev->handle, ctx->id, pseudocode);
+	if (res != EOK) {
+		remove_interrupt_context(&interrupt_contexts, ctx);
+		delete_interrupt_context(ctx);
+	}
+
+	return res;
+}
+
+int unregister_interrupt_handler(ddf_dev_t *dev, int irq)
+{
+	interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
+	    dev, irq);
+	int res = irq_unregister(irq, dev->handle);
+	
+	if (ctx != NULL) {
+		remove_interrupt_context(&interrupt_contexts, ctx);
+		delete_interrupt_context(ctx);
+	}
+	
+	return res;
+}
+
 static void add_to_functions_list(ddf_fun_t *fun)
 {
@@ -159,4 +301,14 @@
 	
 	async_answer_0(iid, res);
+}
+
+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);
 }
 
@@ -308,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:
@@ -595,5 +751,5 @@
 
 /** Allocate driver-specific device data. */
-void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)
+extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)
 {
 	void *data;
@@ -657,5 +813,5 @@
 
 /** Allocate driver-specific function data. */
-void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)
+extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)
 {
 	void *data;
@@ -850,6 +1006,9 @@
 	driver = drv;
 	
-	/* Initialize interrupt module */
-	interrupt_init();
+	/* Initialize the list of interrupt contexts. */
+	init_interrupt_context_list(&interrupt_contexts);
+	
+	/* Set generic interrupt handler. */
+	async_set_interrupt_received(driver_irq_handler);
 	
 	/*
Index: pace/lib/drv/generic/interrupt.c
===================================================================
--- uspace/lib/drv/generic/interrupt.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ 	(revision )
@@ -1,213 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @defgroup libdrv generic device driver support.
- * @brief HelenOS generic device driver support.
- * @{
- */
-
-/** @file
- */
-
-#include <async.h>
-#include <errno.h>
-#include <sys/types.h>
-
-#include "ddf/interrupt.h"
-
-static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall);
-static interrupt_context_t *create_interrupt_context(void);
-static void delete_interrupt_context(interrupt_context_t *ctx);
-static void init_interrupt_context_list(interrupt_context_list_t *list);
-static void add_interrupt_context(interrupt_context_list_t *list,
-    interrupt_context_t *ctx);
-static void remove_interrupt_context(interrupt_context_list_t *list,
-    interrupt_context_t *ctx);
-static interrupt_context_t *find_interrupt_context_by_id(
-    interrupt_context_list_t *list, int id);
-static interrupt_context_t *find_interrupt_context(
-    interrupt_context_list_t *list, ddf_dev_t *dev, int irq);
-int register_interrupt_handler(ddf_dev_t *dev, int irq,
-    interrupt_handler_t *handler, irq_code_t *pseudocode);
-int unregister_interrupt_handler(ddf_dev_t *dev, int irq);
-
-/** Interrupts */
-static interrupt_context_list_t interrupt_contexts;
-
-static irq_cmd_t default_cmds[] = {
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-static irq_code_t default_pseudocode = {
-	sizeof(default_cmds) / sizeof(irq_cmd_t),
-	default_cmds
-};
-
-void interrupt_init(void)
-{
-	/* Initialize the list of interrupt contexts. */
-	init_interrupt_context_list(&interrupt_contexts);
-	
-	/* Set generic interrupt handler. */
-	async_set_interrupt_received(driver_irq_handler);
-}
-
-static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall)
-{
-	int id = (int)IPC_GET_IMETHOD(*icall);
-	interrupt_context_t *ctx;
-	
-	ctx = find_interrupt_context_by_id(&interrupt_contexts, id);
-	if (ctx != NULL && ctx->handler != NULL)
-		(*ctx->handler)(ctx->dev, iid, icall);
-}
-
-static interrupt_context_t *create_interrupt_context(void)
-{
-	interrupt_context_t *ctx;
-	
-	ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t));
-	if (ctx != NULL)
-		memset(ctx, 0, sizeof(interrupt_context_t));
-	
-	return ctx;
-}
-
-static void delete_interrupt_context(interrupt_context_t *ctx)
-{
-	if (ctx != NULL)
-		free(ctx);
-}
-
-static void init_interrupt_context_list(interrupt_context_list_t *list)
-{
-	memset(list, 0, sizeof(interrupt_context_list_t));
-	fibril_mutex_initialize(&list->mutex);
-	list_initialize(&list->contexts);
-}
-
-static void
-add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)
-{
-	fibril_mutex_lock(&list->mutex);
-	ctx->id = list->curr_id++;
-	list_append(&ctx->link, &list->contexts);
-	fibril_mutex_unlock(&list->mutex);
-}
-
-static void remove_interrupt_context(interrupt_context_list_t *list,
-    interrupt_context_t *ctx)
-{
-	fibril_mutex_lock(&list->mutex);
-	list_remove(&ctx->link);
-	fibril_mutex_unlock(&list->mutex);
-}
-
-static interrupt_context_t *
-find_interrupt_context_by_id(interrupt_context_list_t *list, int id)
-{
-	interrupt_context_t *ctx;
-	
-	fibril_mutex_lock(&list->mutex);
-	
-	list_foreach(list->contexts, link) {
-		ctx = list_get_instance(link, interrupt_context_t, link);
-		if (ctx->id == id) {
-			fibril_mutex_unlock(&list->mutex);
-			return ctx;
-		}
-	}
-	
-	fibril_mutex_unlock(&list->mutex);
-	return NULL;
-}
-
-static interrupt_context_t *
-find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
-{
-	interrupt_context_t *ctx;
-	
-	fibril_mutex_lock(&list->mutex);
-	
-	list_foreach(list->contexts, link) {
-		ctx = list_get_instance(link, interrupt_context_t, link);
-		if (ctx->irq == irq && ctx->dev == dev) {
-			fibril_mutex_unlock(&list->mutex);
-			return ctx;
-		}
-	}
-	
-	fibril_mutex_unlock(&list->mutex);
-	return NULL;
-}
-
-
-int
-register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler,
-    irq_code_t *pseudocode)
-{
-	interrupt_context_t *ctx = create_interrupt_context();
-	
-	ctx->dev = dev;
-	ctx->irq = irq;
-	ctx->handler = handler;
-	
-	add_interrupt_context(&interrupt_contexts, ctx);
-	
-	if (pseudocode == NULL)
-		pseudocode = &default_pseudocode;
-	
-	int res = irq_register(irq, dev->handle, ctx->id, pseudocode);
-	if (res != EOK) {
-		remove_interrupt_context(&interrupt_contexts, ctx);
-		delete_interrupt_context(ctx);
-	}
-
-	return res;
-}
-
-int unregister_interrupt_handler(ddf_dev_t *dev, int irq)
-{
-	interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
-	    dev, irq);
-	int res = irq_unregister(irq, dev->handle);
-	
-	if (ctx != NULL) {
-		remove_interrupt_context(&interrupt_contexts, ctx);
-		delete_interrupt_context(ctx);
-	}
-	
-	return res;
-}
-
-/**
- * @}
- */
Index: uspace/lib/drv/generic/remote_nic.c
===================================================================
--- uspace/lib/drv/generic/remote_nic.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/drv/generic/remote_nic.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -63,11 +63,14 @@
 }
 
-static void remote_nic_callback_create(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->callback_create);
-	
-	int rc = nic_iface->callback_create(dev);
+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);
 }
@@ -1200,5 +1203,5 @@
 static remote_iface_func_ptr_t remote_nic_iface_ops[] = {
 	&remote_nic_send_frame,
-	&remote_nic_callback_create,
+	&remote_nic_connect_to_nil,
 	&remote_nic_get_state,
 	&remote_nic_set_state,
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/drv/include/ddf/driver.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -145,4 +145,13 @@
 	/** Ask driver to offline a specific function */
 	int (*fun_offline)(ddf_fun_t *);
+
+	/**
+	 * Notification that the device was succesfully added.
+	 * The driver can do any blocking operation without
+	 * blocking the device manager.
+	 *
+	 * XXX REMOVE THIS
+	 */
+	void (*device_added)(ddf_dev_t *dev);
 } driver_ops_t;
 
Index: uspace/lib/drv/include/ddf/interrupt.h
===================================================================
--- uspace/lib/drv/include/ddf/interrupt.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/drv/include/ddf/interrupt.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -64,5 +64,16 @@
 } interrupt_context_list_t;
 
-extern void interrupt_init(void);
+extern interrupt_context_t *create_interrupt_context(void);
+extern void delete_interrupt_context(interrupt_context_t *);
+extern void init_interrupt_context_list(interrupt_context_list_t *);
+extern void add_interrupt_context(interrupt_context_list_t *,
+    interrupt_context_t *);
+extern void remove_interrupt_context(interrupt_context_list_t *,
+    interrupt_context_t *);
+extern interrupt_context_t *find_interrupt_context_by_id(
+    interrupt_context_list_t *, int);
+extern interrupt_context_t *find_interrupt_context(
+    interrupt_context_list_t *, ddf_dev_t *, int);
+
 extern int register_interrupt_handler(ddf_dev_t *, int, interrupt_handler_t *,
     irq_code_t *);
Index: uspace/lib/drv/include/ops/nic.h
===================================================================
--- uspace/lib/drv/include/ops/nic.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/drv/include/ops/nic.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -38,5 +38,5 @@
 
 #include <ipc/services.h>
-#include <nic/nic.h>
+#include <net/device.h>
 #include <sys/time.h>
 
@@ -46,5 +46,5 @@
 	/** Mandatory methods */
 	int (*send_frame)(ddf_fun_t *, void *, size_t);
-	int (*callback_create)(ddf_fun_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);
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -27,10 +27,8 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup libdrv
  * @addtogroup usb
  * @{
  */
-
 /** @file
  * @brief USB host controller interface definition.
Index: uspace/lib/net/generic/net_checksum.c
===================================================================
--- uspace/lib/net/generic/net_checksum.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/net/generic/net_checksum.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -45,4 +45,7 @@
 #define CRC_DIVIDER_LE  0xedb88320
 
+/** Polynomial used in multicast address hashing */
+#define CRC_MCAST_POLYNOMIAL  0x04c11db6
+
 /** Compacts the computed checksum to the 16 bit number adding the carries.
  *
@@ -221,4 +224,39 @@
 }
 
+/** Compute the standard hash from MAC
+ *
+ * Hashing MAC into 64 possible values and using the value as index to
+ * 64bit number.
+ *
+ * The code is copied from qemu-0.13's implementation of ne2000 and rt8139
+ * drivers, but according to documentation there it originates in FreeBSD.
+ *
+ * @param[in] addr The 6-byte MAC address to be hashed
+ *
+ * @return 64-bit number with only single bit set to 1
+ *
+ */
+uint64_t multicast_hash(const uint8_t addr[6])
+{
+	uint32_t crc;
+    int carry, i, j;
+    uint8_t b;
+
+    crc = 0xffffffff;
+    for (i = 0; i < 6; i++) {
+        b = addr[i];
+        for (j = 0; j < 8; j++) {
+            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
+            crc <<= 1;
+            b >>= 1;
+            if (carry)
+                crc = ((crc ^ CRC_MCAST_POLYNOMIAL) | carry);
+        }
+    }
+	
+    uint64_t one64 = 1;
+    return one64 << (crc >> 26);
+}
+
 /** @}
  */
Index: uspace/lib/net/generic/net_remote.c
===================================================================
--- uspace/lib/net/generic/net_remote.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/net/generic/net_remote.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -167,4 +167,13 @@
 }
 
+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/include/net_checksum.h
===================================================================
--- uspace/lib/net/include/net_checksum.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/net/include/net_checksum.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -67,4 +67,5 @@
 extern uint16_t flip_checksum(uint16_t);
 extern uint16_t ip_checksum(uint8_t *, size_t);
+extern uint64_t multicast_hash(const uint8_t addr[6]);
 
 #endif
Index: uspace/lib/net/include/net_interface.h
===================================================================
--- uspace/lib/net/include/net_interface.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/net/include/net_interface.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -52,4 +52,5 @@
 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: uspace/lib/net/include/nil_remote.h
===================================================================
--- uspace/lib/net/include/nil_remote.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/net/include/nil_remote.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -34,5 +34,4 @@
 #define __NET_NIL_REMOTE_H__
 
-#include <ipc/loc.h>
 #include <net/device.h>
 #include <net/packet.h>
@@ -40,5 +39,4 @@
 #include <generic.h>
 #include <async.h>
-#include <sys/types.h>
 
 #define nil_bind_service(service, device_id, me, receiver) \
@@ -62,4 +60,8 @@
 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/nil/nil_remote.c
===================================================================
--- uspace/lib/net/nil/nil_remote.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/net/nil/nil_remote.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -36,5 +36,4 @@
  */
 
-#include <ipc/loc.h>
 #include <nil_remote.h>
 #include <generic.h>
@@ -44,10 +43,75 @@
 #include <ipc/nil.h>
 
+/** Notify the network interface layer about the device state change.
+ *
+ * @param[in] sess      Network interface layer session.
+ * @param[in] device_id Device identifier.
+ * @param[in] state     New device state.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for each specific module
+ *         device state function.
+ *
+ */
+int nil_device_state_msg(async_sess_t *sess, nic_device_id_t device_id,
+    sysarg_t state)
+{
+	return generic_device_state_msg_remote(sess, NET_NIL_DEVICE_STATE,
+	    device_id, state, 0);
+}
+
+/** Pass the packet queue to the network interface layer.
+ *
+ * Process and redistribute the received packet queue to the registered
+ * upper layers.
+ *
+ * @param[in] sess      Network interface layer session.
+ * @param[in] device_id Source device identifier.
+ * @param[in] packet    Received packet or the received packet queue.
+ * @param[in] target    Target service. Ignored parameter.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for each specific module
+ *         received function.
+ *
+ */
+int nil_received_msg(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_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,
-    service_id_t sid, size_t mtu)
+    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) sid, (sysarg_t) mtu);
+	    (sysarg_t) handle, (sysarg_t) mtu);
 	async_exchange_end(exch);
 	return rc;
Index: uspace/lib/nic/Makefile
===================================================================
--- uspace/lib/nic/Makefile	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/nic/Makefile	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -29,9 +29,9 @@
 USPACE_PREFIX = ../..
 LIBRARY = libnic
-EXTRA_CFLAGS += -DLIBNIC_INTERNAL -Iinclude -I$(LIBDRV_PREFIX)/include
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNET_PREFIX)/libnet.a
+EXTRA_CFLAGS += -DLIBNIC_INTERNAL -Iinclude -I$(LIBDRV_PREFIX)/include -I$(LIBNET_PREFIX)/include
 
 SOURCES = \
 	src/nic_driver.c \
-	src/nic_ev.c \
 	src/nic_addr_db.c \
 	src/nic_rx_control.c \
Index: uspace/lib/nic/include/nic.h
===================================================================
--- uspace/lib/nic/include/nic.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/nic/include/nic.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -42,7 +42,6 @@
 #include <ddf/driver.h>
 #include <device/hw_res_parsed.h>
+#include <net/packet.h>
 #include <ops/nic.h>
-
-#define DEVICE_CATEGORY_NIC "nic"
 
 struct nic;
@@ -62,10 +61,9 @@
 
 /**
- * Simple structure for sending lists of frames.
+ * Simple structure for sending the allocated frames (packets) in a list.
  */
 typedef struct {
 	link_t link;
-	void *data;
-	size_t size;
+	packet_t *packet;
 } nic_frame_t;
 
@@ -73,6 +71,6 @@
 
 /**
- * Handler for writing frame data to the NIC device.
- * The function is responsible for releasing the frame.
+ * Handler for writing packet data to the NIC device.
+ * The function is responsible for releasing the packet.
  * It does not return anything, if some error is detected the function just
  * silently fails (logging on debug level is suggested).
@@ -160,5 +158,5 @@
  * @return ENOTSUP	If this filter cannot work on this NIC (e.g. the NIC
  * 					cannot run in promiscuous node or the limit of WOL
- * 					frames' specifications was reached).
+ * 					packets' specifications was reached).
  * @return ELIMIT	If this filter must implemented in HW but currently the
  * 					limit of these HW filters was reached.
@@ -206,4 +204,5 @@
 /* Functions called in add_device */
 extern int nic_connect_to_services(nic_t *);
+extern int nic_register_as_ddf_fun(nic_t *, ddf_dev_ops_t *);
 extern int nic_get_resources(nic_t *, hw_res_list_parsed_t *);
 extern void nic_set_specific(nic_t *, void *);
@@ -220,8 +219,10 @@
 	poll_mode_change_handler, poll_request_handler);
 
+/* Functions called in device_added */
+extern int nic_ready(nic_t *);
+
 /* General driver functions */
 extern ddf_dev_t *nic_get_ddf_dev(nic_t *);
 extern ddf_fun_t *nic_get_ddf_fun(nic_t *);
-extern void nic_set_ddf_fun(nic_t *, ddf_fun_t *);
 extern nic_t *nic_get_from_ddf_dev(ddf_dev_t *);
 extern nic_t *nic_get_from_ddf_fun(ddf_fun_t *);
@@ -232,5 +233,6 @@
 extern int nic_report_poll_mode(nic_t *, nic_poll_mode_t, struct timeval *);
 extern void nic_query_address(nic_t *, nic_address_t *);
-extern void nic_received_noneth_frame(nic_t *, void *, size_t);
+extern void nic_received_packet(nic_t *, packet_t *);
+extern void nic_received_noneth_packet(nic_t *, packet_t *);
 extern void nic_received_frame(nic_t *, nic_frame_t *);
 extern void nic_received_frame_list(nic_t *, nic_frame_list_t *);
@@ -246,5 +248,7 @@
 extern void nic_report_collisions(nic_t *, unsigned);
 
-/* Frame / frame list allocation and deallocation */
+/* Packet / frame / frame list allocation and deallocation */
+extern packet_t *nic_alloc_packet(nic_t *, size_t);
+extern void nic_release_packet(nic_t *, packet_t *);
 extern nic_frame_t *nic_alloc_frame(nic_t *, size_t);
 extern nic_frame_list_t *nic_alloc_frame_list(void);
@@ -271,4 +275,8 @@
 extern void nic_sw_period_stop(nic_t *);
 
+/* Packet DMA lock */
+extern int nic_dma_lock_packet(packet_t *, size_t, void **);
+extern int nic_dma_unlock_packet(packet_t *, size_t);
+
 #endif // __NIC_H__
 
Index: uspace/lib/nic/include/nic_driver.h
===================================================================
--- uspace/lib/nic/include/nic_driver.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/nic/include/nic_driver.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -44,5 +44,5 @@
 
 #include <fibril_synch.h>
-#include <nic/nic.h>
+#include <net/device.h>
 #include <async.h>
 
@@ -50,4 +50,6 @@
 #include "nic_rx_control.h"
 #include "nic_wol_virtues.h"
+
+#define DEVICE_CATEGORY_NIC "nic"
 
 struct sw_poll_info {
@@ -70,4 +72,6 @@
 	 */
 	ddf_fun_t *fun;
+	/** Identifier for higher network stack layers */
+	nic_device_id_t device_id;
 	/** Current state of the device */
 	nic_device_state_t state;
@@ -78,6 +82,8 @@
 	/** Device's default MAC address (assigned the first time, used in STOP) */
 	nic_address_t default_mac;
-	/** Client callback session */
-	async_sess_t *client_session;
+	/** Session to SERVICE_NETWORKING */
+	async_sess_t *net_session;
+	/** Session to SERVICE_ETHERNET or SERVICE_NILDUMMY */
+	async_sess_t *nil_session;
 	/** Phone to APIC or i8259 */
 	async_sess_t *irc_session;
Index: pace/lib/nic/include/nic_ev.h
===================================================================
--- uspace/lib/nic/include/nic_ev.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @addtogroup libnic
- * @{
- */
-/**
- * @file
- * @brief Prototypes of default DDF NIC interface methods implementations
- */
-
-#ifndef NIC_EV_H__
-#define NIC_EV_H__
-
-#include <async.h>
-#include <nic/nic.h>
-#include <sys/types.h>
-
-extern int nic_ev_addr_changed(async_sess_t *, const nic_address_t *);
-extern int nic_ev_device_state(async_sess_t *, sysarg_t);
-extern int nic_ev_received(async_sess_t *, void *, size_t);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/nic/include/nic_impl.h
===================================================================
--- uspace/lib/nic/include/nic_impl.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/nic/include/nic_impl.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -40,6 +40,7 @@
 
 #include <assert.h>
-#include <nic/nic.h>
+#include <net/device.h>
 #include <ddf/driver.h>
+#include <nil_remote.h>
 
 /* Inclusion of this file is not prohibited, because drivers could want to
@@ -48,5 +49,6 @@
 extern int nic_get_address_impl(ddf_fun_t *dev_fun, nic_address_t *address);
 extern int nic_send_frame_impl(ddf_fun_t *dev_fun, void *data, size_t size);
-extern int nic_callback_create_impl(ddf_fun_t *dev_fun);
+extern int nic_connect_to_nil_impl(ddf_fun_t *dev_fun, services_t nil_service,
+	int device_id);
 extern int nic_get_state_impl(ddf_fun_t *dev_fun, nic_device_state_t *state);
 extern int nic_set_state_impl(ddf_fun_t *dev_fun, nic_device_state_t state);
Index: uspace/lib/nic/include/nic_rx_control.h
===================================================================
--- uspace/lib/nic/include/nic_rx_control.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/nic/include/nic_rx_control.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -45,5 +45,6 @@
 #include <adt/hash_table.h>
 #include <fibril_synch.h>
-#include <nic/nic.h>
+#include <net/device.h>
+#include <net/packet_header.h>
 
 #include "nic_addr_db.h"
@@ -119,5 +120,5 @@
 	const nic_address_t *prev_addr, const nic_address_t *curr_addr);
 extern int nic_rxc_check(const nic_rxc_t *rxc,
-	const void *data, size_t size, nic_frame_type_t *frame_type);
+	const packet_t *packet, nic_frame_type_t *frame_type);
 extern void nic_rxc_hw_filtering(nic_rxc_t *rxc,
 	int unicast_exact, int multicast_exact, int vlan_exact);
Index: uspace/lib/nic/include/nic_wol_virtues.h
===================================================================
--- uspace/lib/nic/include/nic_wol_virtues.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/nic/include/nic_wol_virtues.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -43,5 +43,5 @@
 #endif
 
-#include <nic/nic.h>
+#include <net/device.h>
 #include <adt/hash_table.h>
 #include "nic.h"
Index: uspace/lib/nic/src/nic_driver.c
===================================================================
--- uspace/lib/nic/src/nic_driver.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/nic/src/nic_driver.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -49,9 +49,12 @@
 #include <devman.h>
 #include <ddf/interrupt.h>
+#include <net_interface.h>
 #include <ops/nic.h>
+#include <packet_client.h>
+#include <packet_remote.h>
+#include <net/packet_header.h>
 #include <errno.h>
 
 #include "nic_driver.h"
-#include "nic_ev.h"
 #include "nic_impl.h"
 
@@ -61,5 +64,5 @@
 
 /**
- * Initializes libraries required for NIC framework - logger
+ * Initializes libraries required for NIC framework - logger, packet manager
  *
  * @param name	Name of the device/driver (used in logging)
@@ -76,5 +79,6 @@
 	snprintf(buffer, 256, "drv/" DEVICE_CATEGORY_NIC "/%s", name);
 	
-	return EOK;
+	/* Initialize packet manager */
+	return pm_init();
 }
 
@@ -89,4 +93,9 @@
     nic_iface_t *iface)
 {
+	if (driver_ops) {
+		if (!driver_ops->device_added)
+			driver_ops->device_added = nic_device_added_impl;
+	}
+
 	if (dev_ops) {
 		if (!dev_ops->open)
@@ -107,6 +116,6 @@
 		if (!iface->send_frame)
 			iface->send_frame = nic_send_frame_impl;
-		if (!iface->callback_create)
-			iface->callback_create = nic_callback_create_impl;
+		if (!iface->connect_to_nil)
+			iface->connect_to_nil = nic_connect_to_nil_impl;
 		if (!iface->get_address)
 			iface->get_address = nic_get_address_impl;
@@ -153,5 +162,5 @@
 
 /**
- * Setup send frame handler. This MUST be called in the add_device handler
+ * Setup write packet handler. This MUST be called in the add_device handler
  * if the nic_send_message_impl function is used for sending messages (filled
  * as send_message member of the nic_iface_t structure). The function must not
@@ -261,11 +270,29 @@
 }
 
-/** Allocate frame
+/**
+ * Just a wrapper over the packet_get_1_remote function
+ */
+packet_t *nic_alloc_packet(nic_t *nic_data, size_t data_size)
+{
+	return packet_get_1_remote(nic_data->net_session, data_size);
+}
+
+
+/**
+ * Just a wrapper over the pq_release_remote function
+ */
+void nic_release_packet(nic_t *nic_data, packet_t *packet)
+{
+	pq_release_remote(nic_data->net_session, packet_get_id(packet));
+}
+
+/** Allocate frame and packet
  *
  *  @param nic_data 	The NIC driver data
- *  @param size	        Frame size in bytes
+ *  @param packet_size	Size of packet
+ *  @param offload_size	Size of packet offload
  *  @return pointer to allocated frame if success, NULL otherwise
  */
-nic_frame_t *nic_alloc_frame(nic_t *nic_data, size_t size)
+nic_frame_t *nic_alloc_frame(nic_t *nic_data, size_t packet_size)
 {
 	nic_frame_t *frame;
@@ -286,11 +313,11 @@
 	}
 
-	frame->data = malloc(size);
-	if (frame->data == NULL) {
+	packet_t *packet = nic_alloc_packet(nic_data, packet_size);
+	if (!packet) {
 		free(frame);
 		return NULL;
 	}
 
-	frame->size = size;
+	frame->packet = packet;
 	return frame;
 }
@@ -305,11 +332,7 @@
 	if (!frame)
 		return;
-
-	if (frame->data != NULL) {
-		free(frame->data);
-		frame->data = NULL;
-		frame->size = 0;
-	}
-
+	if (frame->packet != NULL) {
+		nic_release_packet(nic_data, frame->packet);
+	}
 	fibril_mutex_lock(&nic_globals.lock);
 	if (nic_globals.frame_cache_size >= NIC_GLOBALS_MAX_CACHE_SIZE) {
@@ -424,5 +447,5 @@
 
 /**
- * Connect to IRC service. This function should be called only from
+ * Connect to the NET and IRQ services. This function should be called only from
  * the add_device handler, thus no locking is required.
  *
@@ -431,8 +454,14 @@
  * @return EOK		If connection was successful.
  * @return EINVAL	If the IRC service cannot be determined.
- * @return EREFUSED	If IRC service cannot be connected.
+ * @return EREFUSED	If NET or IRC service cannot be connected.
  */
 int nic_connect_to_services(nic_t *nic_data)
 {
+	/* NET service */
+	nic_data->net_session = service_connect_blocking(EXCHANGE_SERIALIZE,
+		SERVICE_NETWORKING, 0, 0);
+	if (nic_data->net_session == NULL)
+		return errno;
+	
 	/* IRC service */
 	sysarg_t apic;
@@ -451,4 +480,26 @@
 	
 	return EOK;
+}
+
+/** Notify the NET service that the device is ready
+ *
+ * @param nic NICF structure
+ *
+ * @return EOK on success
+ *
+ */
+int nic_ready(nic_t *nic)
+{
+	fibril_rwlock_read_lock(&nic->main_lock);
+	
+	async_sess_t *session = nic->net_session;
+	devman_handle_t handle = nic->dev->handle;
+	
+	fibril_rwlock_read_unlock(&nic->main_lock);
+	
+	if (session == NULL)
+		return EINVAL;
+	
+	return net_driver_ready(session, handle);
 }
 
@@ -495,7 +546,7 @@
 	
 	/* Notify NIL layer (and uppper) if bound - not in add_device */
-	if (nic_data->client_session != NULL) {
-		int rc = nic_ev_addr_changed(nic_data->client_session,
-		    address);
+	if (nic_data->nil_session != NULL) {
+		int rc = nil_addr_changed_msg(nic_data->nil_session,
+		    nic_data->device_id, address);
 		if (rc != EOK) {
 			fibril_rwlock_write_unlock(&nic_data->main_lock);
@@ -553,5 +604,5 @@
 
 /**
- * The busy flag can be set to 1 only in the send_frame handler, to 0 it can
+ * The busy flag can be set to 1 only in the write_packet handler, to 0 it can
  * be set anywhere.
  *
@@ -562,5 +613,5 @@
 {
 	/*
-	 * When the function is called in send_frame handler the main lock is
+	 * When the function is called in write_packet handler the main lock is
 	 * locked so no race can happen.
 	 * Otherwise, when it is unexpectedly set to 0 (even with main lock held
@@ -571,26 +622,42 @@
 
 /**
- * This is the function that the driver should call when it receives a frame.
- * The frame is checked by filters and then sent up to the NIL layer or
- * discarded. The frame is released.
- *
- * @param nic_data
- * @param frame		The received frame
+ * Provided for correct naming conventions.
+ * The packet is checked by filters and then sent up to the NIL layer or
+ * discarded, the frame is released.
+ *
+ * @param nic_data
+ * @param frame		The frame containing received packet
  */
 void nic_received_frame(nic_t *nic_data, nic_frame_t *frame)
 {
+	nic_received_packet(nic_data, frame->packet);
+	frame->packet = NULL;
+	nic_release_frame(nic_data, frame);
+}
+
+/**
+ * This is the function that the driver should call when it receives a packet.
+ * The packet is checked by filters and then sent up to the NIL layer or
+ * discarded.
+ *
+ * @param nic_data
+ * @param packet		The received packet
+ */
+void nic_received_packet(nic_t *nic_data, packet_t *packet)
+{
 	/* Note: this function must not lock main lock, because loopback driver
-	 * 		 calls it inside send_frame handler (with locked main lock) */
+	 * 		 calls it inside write_packet handler (with locked main lock) */
+	packet_id_t pid = packet_get_id(packet);
+	
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	nic_frame_type_t frame_type;
-	int check = nic_rxc_check(&nic_data->rx_control, frame->data,
-	    frame->size, &frame_type);
+	int check = nic_rxc_check(&nic_data->rx_control, packet, &frame_type);
 	fibril_rwlock_read_unlock(&nic_data->rxc_lock);
 	/* Update statistics */
 	fibril_rwlock_write_lock(&nic_data->stats_lock);
-
+	/* Both sending message up and releasing packet are atomic IPC calls */
 	if (nic_data->state == NIC_STATE_ACTIVE && check) {
 		nic_data->stats.receive_packets++;
-		nic_data->stats.receive_bytes += frame->size;
+		nic_data->stats.receive_bytes += packet_get_data_length(packet);
 		switch (frame_type) {
 		case NIC_FRAME_MULTICAST:
@@ -604,6 +671,5 @@
 		}
 		fibril_rwlock_write_unlock(&nic_data->stats_lock);
-		nic_ev_received(nic_data->client_session, frame->data,
-		    frame->size);
+		nil_received_msg(nic_data->nil_session, nic_data->device_id, pid);
 	} else {
 		switch (frame_type) {
@@ -619,31 +685,31 @@
 		}
 		fibril_rwlock_write_unlock(&nic_data->stats_lock);
-	}
-	nic_release_frame(nic_data, frame);
+		nic_release_packet(nic_data, packet);
+	}
 }
 
 /**
  * This function is to be used only in the loopback driver. It's workaround
- * for the situation when the frame does not contain ethernet address.
+ * for the situation when the packet does not contain ethernet address.
  * The filtering is therefore not applied here.
  *
  * @param nic_data
- * @param data		Frame data
- * @param size		Frame size in bytes
- */
-void nic_received_noneth_frame(nic_t *nic_data, void *data, size_t size)
+ * @param packet
+ */
+void nic_received_noneth_packet(nic_t *nic_data, packet_t *packet)
 {
 	fibril_rwlock_write_lock(&nic_data->stats_lock);
 	nic_data->stats.receive_packets++;
-	nic_data->stats.receive_bytes += size;
+	nic_data->stats.receive_bytes += packet_get_data_length(packet);
 	fibril_rwlock_write_unlock(&nic_data->stats_lock);
 	
-	nic_ev_received(nic_data->client_session, data, size);
-}
-
-/**
- * Some NICs can receive multiple frames during single interrupt. These can
+	nil_received_msg(nic_data->nil_session, nic_data->device_id,
+	    packet_get_id(packet));
+}
+
+/**
+ * Some NICs can receive multiple packets during single interrupt. These can
  * send them in whole list of frames (actually nic_frame_t structures), then
- * the list is deallocated and each frame is passed to the
+ * the list is deallocated and each packet is passed to the
  * nic_received_packet function.
  *
@@ -660,5 +726,7 @@
 
 		list_remove(&frame->link);
-		nic_received_frame(nic_data, frame);
+		nic_received_packet(nic_data, frame->packet);
+		frame->packet = NULL;
+		nic_release_frame(nic_data, frame);
 	}
 	nic_driver_release_frame_list(frames);
@@ -690,6 +758,8 @@
 	nic_data->dev = NULL;
 	nic_data->fun = NULL;
+	nic_data->device_id = NIC_DEVICE_INVALID_ID;
 	nic_data->state = NIC_STATE_STOPPED;
-	nic_data->client_session = NULL;
+	nic_data->net_session = NULL;
+	nic_data->nil_session = NULL;
 	nic_data->irc_session = NULL;
 	nic_data->poll_mode = NIC_POLL_IMMEDIATE;
@@ -745,6 +815,10 @@
  */
 static void nic_destroy(nic_t *nic_data) {
-	if (nic_data->client_session != NULL) {
-		async_hangup(nic_data->client_session);
+	if (nic_data->net_session != NULL) {
+		async_hangup(nic_data->net_session);
+	}
+
+	if (nic_data->nil_session != NULL) {
+		async_hangup(nic_data->nil_session);
 	}
 
@@ -772,4 +846,41 @@
 
 /**
+ * Creates an exposed DDF function for the device, named "port0".
+ * Device options are set as this function's options. The function is bound
+ * (see ddf_fun_bind) and then registered to the DEVICE_CATEGORY_NIC class.
+ * Note: this function should be called only from add_device handler, therefore
+ * we don't need to use locks.
+ *
+ * @param nic_data	The NIC structure
+ * @param ops		Device options for the DDF function.
+ */
+int nic_register_as_ddf_fun(nic_t *nic_data, ddf_dev_ops_t *ops)
+{
+	int rc;
+	assert(nic_data);
+
+	nic_data->fun = ddf_fun_create(nic_data->dev, fun_exposed, "port0");
+	if (nic_data->fun == NULL)
+		return ENOMEM;
+	
+	nic_data->fun->ops = ops;
+	nic_data->fun->driver_data = nic_data;
+
+	rc = ddf_fun_bind(nic_data->fun);
+	if (rc != EOK) {
+		ddf_fun_destroy(nic_data->fun);
+		return rc;
+	}
+
+	rc = ddf_fun_add_to_category(nic_data->fun, DEVICE_CATEGORY_NIC);
+	if (rc != EOK) {
+		ddf_fun_destroy(nic_data->fun);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/**
  * Set information about current HW filtering.
  *  1 ...	Only those frames we want to receive are passed through HW
@@ -986,13 +1097,4 @@
 {
 	return nic_data->fun;
-}
-
-/**
- * @param nic_data
- * @param fun
- */
-void nic_set_ddf_fun(nic_t *nic_data, ddf_fun_t *fun)
-{
-	nic_data->fun = fun;
 }
 
@@ -1227,4 +1329,23 @@
 }
 
+/** Lock packet for DMA usage
+ *
+ * @param packet
+ * @return physical address of packet
+ */
+int nic_dma_lock_packet(packet_t *packet, size_t size, void **phys)
+{
+	return dmamem_map(packet, SIZE2PAGES(size), 0, 0, phys);
+}
+
+/** Unlock packet after DMA usage
+ *
+ * @param packet
+ */
+int nic_dma_unlock_packet(packet_t *packet, size_t size)
+{
+	return dmamem_unmap(packet, size);
+}
+
 /** @}
  */
Index: pace/lib/nic/src/nic_ev.c
===================================================================
--- uspace/lib/nic/src/nic_ev.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ 	(revision )
@@ -1,97 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @addtogroup libnic
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <async.h>
-#include <device/nic.h>
-#include <errno.h>
-#include "nic_ev.h"
-
-/** Device address changed. */
-int nic_ev_addr_changed(async_sess_t *sess, const nic_address_t *addr)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-
-	ipc_call_t answer;
-	aid_t req = async_send_0(exch, NIC_EV_ADDR_CHANGED, &answer);
-	sysarg_t retval = async_data_write_start(exch, addr,
-	    sizeof(nic_address_t));
-
-	async_exchange_end(exch);
-
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		return retval;
-	}
-
-	async_wait_for(req, &retval);
-	return retval;
-}
-
-/** Device state changed. */
-int nic_ev_device_state(async_sess_t *sess, sysarg_t state)
-{
-	int rc;
-
-	async_exch_t *exch = async_exchange_begin(sess);
-	rc = async_req_1_0(exch, NIC_EV_DEVICE_STATE, state);
-	async_exchange_end(exch);
-
-	return rc;
-}
-
-/** Frame received. */
-int nic_ev_received(async_sess_t *sess, void *data, size_t size)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-
-	ipc_call_t answer;
-	aid_t req = async_send_0(exch, NIC_EV_RECEIVED, &answer);
-	sysarg_t retval = async_data_write_start(exch, data, size);
-
-	async_exchange_end(exch);
-
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		return retval;
-	}
-
-	async_wait_for(req, &retval);
-	return retval;
-}
-
-/** @}
- */
Index: uspace/lib/nic/src/nic_impl.c
===================================================================
--- uspace/lib/nic/src/nic_impl.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/nic/src/nic_impl.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -36,10 +36,8 @@
  */
 
-#include <errno.h>
 #include <str_error.h>
 #include <ipc/services.h>
 #include <ns.h>
 #include "nic_driver.h"
-#include "nic_ev.h"
 #include "nic_impl.h"
 
@@ -87,5 +85,6 @@
 	}
 	if (state == NIC_STATE_ACTIVE) {
-		if (nic_data->client_session == NULL) {
+		if (nic_data->nil_session == NULL || nic_data->net_session == NULL
+		    || nic_data->device_id < 0) {
 			fibril_rwlock_write_unlock(&nic_data->main_lock);
 			return EINVAL;
@@ -117,6 +116,6 @@
 	if (state == NIC_STATE_STOPPED) {
 		/* Notify upper layers that we are reseting the MAC */
-		int rc = nic_ev_addr_changed(nic_data->client_session,
-			&nic_data->default_mac);
+		int rc = nil_addr_changed_msg(nic_data->nil_session,
+			nic_data->device_id, &nic_data->default_mac);
 		nic_data->poll_mode = nic_data->default_poll_mode;
 		memcpy(&nic_data->poll_period, &nic_data->default_poll_period,
@@ -150,5 +149,5 @@
 	nic_data->state = state;
 
-	nic_ev_device_state(nic_data->client_session, state);
+	nil_device_state_msg(nic_data->nil_session, nic_data->device_id, state);
 
 	fibril_rwlock_write_unlock(&nic_data->main_lock);
@@ -183,24 +182,31 @@
 
 /**
- * Default implementation of the connect_client method.
- * Creates callback connection to the client.
+ * Default implementation of the connect_to_nil method.
+ * Connects the driver to the NIL service.
  *
  * @param	fun
- *
- * @return EOK		On success, or negative error code.
- */
-int nic_callback_create_impl(ddf_fun_t *fun)
-{
-	nic_t *nic = (nic_t *) fun->driver_data;
-	fibril_rwlock_write_lock(&nic->main_lock);
+ * @param	nil_service	ID of the server implementing the NIL service
+ * @param	device_id	ID of the device as used in higher layers
+ *
+ * @return EOK		If the services were bound
+ * @return 			Negative error code from service_connect_blocking
+ */
+int nic_connect_to_nil_impl(ddf_fun_t *fun, services_t nil_service,
+    nic_device_id_t device_id)
+{
+	nic_t *nic_data = (nic_t *) fun->driver_data;
+	fibril_rwlock_write_lock(&nic_data->main_lock);
 	
-	nic->client_session = async_callback_receive(EXCHANGE_SERIALIZE);
-	if (nic->client_session == NULL) {
-		fibril_rwlock_write_unlock(&nic->main_lock);
-		return ENOMEM;
-	}
+	nic_data->device_id = device_id;
 	
-	fibril_rwlock_write_unlock(&nic->main_lock);
-	return EOK;
+	nic_data->nil_session = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    nil_service, 0, 0);
+	if (nic_data->nil_session != NULL) {
+		fibril_rwlock_write_unlock(&nic_data->main_lock);
+		return EOK;
+	}
+	
+	fibril_rwlock_write_unlock(&nic_data->main_lock);
+	return EHANGUP;
 }
 
@@ -799,4 +805,16 @@
 }
 
+/** Default implementation of the device_added method
+ *
+ * Just calls nic_ready.
+ *
+ * @param dev
+ *
+ */
+void nic_device_added_impl(ddf_dev_t *dev)
+{
+	nic_ready((nic_t *) dev->driver_data);
+}
+
 /**
  * Default handler for unknown methods (outside of the NIC interface).
Index: uspace/lib/nic/src/nic_rx_control.c
===================================================================
--- uspace/lib/nic/src/nic_rx_control.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/nic/src/nic_rx_control.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -40,6 +40,7 @@
 #include <bool.h>
 #include <errno.h>
-#include <mem.h>
-#include <nic/nic.h>
+#include <net/device.h>
+#include <net_checksum.h>
+#include <packet_client.h>
 #include "nic_rx_control.h"
 
@@ -391,17 +392,14 @@
  *
  * @param rxc
- * @param frame	    The probed frame
+ * @param packet	The probed frame
  *
  * @return True if the frame passes, false if it does not
  */
-int nic_rxc_check(const nic_rxc_t *rxc, const void *data, size_t size,
+int nic_rxc_check(const nic_rxc_t *rxc, const packet_t *packet,
 	nic_frame_type_t *frame_type)
 {
 	assert(frame_type != NULL);
-	uint8_t *dest_addr = (uint8_t *) data;
+	uint8_t *dest_addr = (uint8_t *) packet + packet->data_start;
 	uint8_t *src_addr = dest_addr + ETH_ADDR;
-
-	if (size < 2 * ETH_ADDR)
-		return false;
 
 	if (dest_addr[0] & 1) {
@@ -450,5 +448,5 @@
 	if (!rxc->vlan_exact && rxc->vlan_mask != NULL) {
 		vlan_header_t *vlan_header = (vlan_header_t *)
-			((uint8_t *) data + 2 * ETH_ADDR);
+			((uint8_t *) packet + packet->data_start + 2 * ETH_ADDR);
 		if (vlan_header->tpid_upper == VLAN_TPID_UPPER &&
 			vlan_header->tpid_lower == VLAN_TPID_LOWER) {
@@ -486,43 +484,4 @@
 		rxc->vlan_exact = vlan_exact;
 }
-
-/** Polynomial used in multicast address hashing */
-#define CRC_MCAST_POLYNOMIAL  0x04c11db6
-
-/** Compute the standard hash from MAC
- *
- * Hashing MAC into 64 possible values and using the value as index to
- * 64bit number.
- *
- * The code is copied from qemu-0.13's implementation of ne2000 and rt8139
- * drivers, but according to documentation there it originates in FreeBSD.
- *
- * @param[in] addr The 6-byte MAC address to be hashed
- *
- * @return 64-bit number with only single bit set to 1
- *
- */
-static uint64_t multicast_hash(const uint8_t addr[6])
-{
-	uint32_t crc;
-    int carry, i, j;
-    uint8_t b;
-
-    crc = 0xffffffff;
-    for (i = 0; i < 6; i++) {
-        b = addr[i];
-        for (j = 0; j < 8; j++) {
-            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
-            crc <<= 1;
-            b >>= 1;
-            if (carry)
-                crc = ((crc ^ CRC_MCAST_POLYNOMIAL) | carry);
-        }
-    }
-	
-    uint64_t one64 = 1;
-    return one64 << (crc >> 26);
-}
-
 
 /**
Index: uspace/lib/nic/src/nic_wol_virtues.c
===================================================================
--- uspace/lib/nic/src/nic_wol_virtues.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/nic/src/nic_wol_virtues.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -38,5 +38,4 @@
 #include "nic_wol_virtues.h"
 #include <assert.h>
-#include <errno.h>
 
 #define NIC_WV_HASH_COUNT 32
Index: uspace/lib/posix/ctype.c
===================================================================
--- uspace/lib/posix/ctype.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/lib/posix/ctype.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -112,5 +112,5 @@
  * @return Non-zero if character match the definition, zero otherwise.
  */
-int posix_isascii(int c)
+extern int posix_isascii(int c)
 {
 	return c >= 0 && c < 128;
@@ -123,5 +123,5 @@
  * @return Coverted character.
  */
-int posix_toascii(int c)
+extern int posix_toascii(int c)
 {
 	return c & 0x7F;
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/devman/devman.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -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:
@@ -800,5 +803,4 @@
 	default:
 		dev->state = DEVICE_INVALID;
-		break;
 	}
 	
Index: uspace/srv/hid/input/generic/input.c
===================================================================
--- uspace/srv/hid/input/generic/input.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/hid/input/generic/input.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -39,5 +39,4 @@
 #include <adt/list.h>
 #include <bool.h>
-#include <fibril_synch.h>
 #include <ipc/services.h>
 #include <ipc/input.h>
@@ -84,6 +83,4 @@
 async_sess_t *irc_sess = NULL;
 
-static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
-
 void kbd_push_data(kbd_dev_t *kdev, sysarg_t data)
 {
@@ -596,20 +593,12 @@
 	int rc;
 	
-	fibril_mutex_lock(&discovery_lock);
-	
 	rc = dev_check_new_kbdevs();
-	if (rc != EOK) {
-		fibril_mutex_unlock(&discovery_lock);
+	if (rc != EOK)
 		return rc;
-	}
 	
 	rc = dev_check_new_mousedevs();
-	if (rc != EOK) {
-		fibril_mutex_unlock(&discovery_lock);
+	if (rc != EOK)
 		return rc;
-	}
-	
-	fibril_mutex_unlock(&discovery_lock);
-	
+
 	return EOK;
 }
Index: uspace/srv/hid/input/include/sun.h
===================================================================
--- uspace/srv/hid/input/include/sun.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
+++ uspace/srv/hid/input/include/sun.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2009 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 kbdgen generic
+ * @brief Sun keyboard virtual port driver.
+ * @ingroup kbd
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_SUN_H_
+#define KBD_SUN_H_
+
+extern int ns16550_port_init(void);
+extern int z8530_port_init(void);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/dummy.c
===================================================================
--- uspace/srv/hid/input/port/dummy.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
+++ uspace/srv/hid/input/port/dummy.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @brief	Dummy keyboard port driver.
+ * @ingroup  kbd
+ * @{
+ */ 
+/** @file
+ */
+
+#include <kbd_port.h>
+#include <kbd.h>
+
+int kbd_port_init(void)
+{
+	return 0;
+}
+
+void kbd_port_yield(void)
+{
+}
+
+void kbd_port_reclaim(void)
+{
+}
+
+void kbd_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/** @}
+*/
Index: uspace/srv/hid/input/port/sgcn.c
===================================================================
--- uspace/srv/hid/input/port/sgcn.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
+++ uspace/srv/hid/input/port/sgcn.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2008 Pavel Rimsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief SGCN (Serengeti Console) keyboard port driver.
+ */
+
+#include <as.h>
+#include <ddi.h>
+#include <async.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <thread.h>
+#include <bool.h>
+#include <errno.h>
+
+#define POLL_INTERVAL  10000
+
+/**
+ * SGCN buffer header. It is placed at the very beginning of the SGCN
+ * buffer.
+ */
+typedef struct {
+	/** hard-wired to "CON" */
+	char magic[4];
+	
+	/** we don't need this */
+	char unused[8];
+	
+	/** offset within the SGCN buffer of the input buffer start */
+	uint32_t in_begin;
+	
+	/** offset within the SGCN buffer of the input buffer end */
+	uint32_t in_end;
+	
+	/** offset within the SGCN buffer of the input buffer read pointer */
+	uint32_t in_rdptr;
+	
+	/** offset within the SGCN buffer of the input buffer write pointer */
+	uint32_t in_wrptr;
+} __attribute__ ((packed)) sgcn_buffer_header_t;
+
+/*
+ * Returns a pointer to the object of a given type which is placed at the given
+ * offset from the console buffer beginning.
+ */
+#define SGCN_BUFFER(type, offset) \
+		((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
+
+/** Returns a pointer to the console buffer header. */
+#define SGCN_BUFFER_HEADER	(SGCN_BUFFER(sgcn_buffer_header_t, 0))
+
+/**
+ * Virtual address mapped to SRAM.
+ */
+static uintptr_t sram_virt_addr;
+
+/**
+ * SGCN buffer offset within SGCN.
+ */
+static uintptr_t sram_buffer_offset;
+
+/* polling thread */
+static void sgcn_thread_impl(void *arg);
+
+static volatile bool polling_disabled = false;
+
+/**
+ * Initializes the SGCN driver.
+ * Maps the physical memory (SRAM) and creates the polling thread. 
+ */
+int kbd_port_init(void)
+{
+	sysarg_t sram_paddr;
+	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
+		return -1;
+	
+	sysarg_t sram_size;
+	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
+		sram_buffer_offset = 0;
+	
+	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
+	
+	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
+	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0) {
+		printf("SGCN: uspace driver could not map physical memory.");
+		return -1;
+	}
+	
+	thread_id_t tid;
+	int rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
+	if (rc != 0)
+		return rc;
+	
+	return 0;
+}
+
+void kbd_port_yield(void)
+{
+	polling_disabled = true;
+}
+
+void kbd_port_reclaim(void)
+{
+	polling_disabled = false;
+}
+
+void kbd_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/**
+ * Handler of the "key pressed" event. Reads codes of all the pressed keys from
+ * the buffer. 
+ */
+static void sgcn_key_pressed(void)
+{
+	char c;
+	
+	uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
+	uint32_t end = SGCN_BUFFER_HEADER->in_end;
+	uint32_t size = end - begin;
+	
+	volatile char *buf_ptr = (volatile char *)
+		SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
+	volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
+	volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
+	
+	while (*in_rdptr_ptr != *in_wrptr_ptr) {
+		c = *buf_ptr;
+		*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
+		buf_ptr = (volatile char *)
+			SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
+		kbd_push_scancode(c);
+	}
+}
+
+/**
+ * Thread to poll SGCN for keypresses.
+ */
+static void sgcn_thread_impl(void *arg)
+{
+	(void) arg;
+
+	while (1) {
+		if (polling_disabled == false)
+			sgcn_key_pressed();
+		usleep(POLL_INTERVAL);
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/hid/input/port/sun.c
===================================================================
--- uspace/srv/hid/input/port/sun.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
+++ uspace/srv/hid/input/port/sun.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2009 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 kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief Sun keyboard virtual port driver.
+ */
+
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sun.h>
+#include <sysinfo.h>
+#include <errno.h>
+#include <bool.h>
+
+/** Sun keyboard virtual port driver.
+ *
+ * This is a virtual port driver which can use
+ * both ns16550_port_init and z8530_port_init
+ * according to the information passed from the
+ * kernel. This is just a temporal hack.
+ *
+ */
+int kbd_port_init(void)
+{
+	sysarg_t z8530;
+	if (sysinfo_get_value("kbd.type.z8530", &z8530) != EOK)
+		z8530 = false;
+	
+	sysarg_t ns16550;
+	if (sysinfo_get_value("kbd.type.ns16550", &ns16550) != EOK)
+		ns16550 = false;
+	
+	if (z8530) {
+		if (z8530_port_init() == 0)
+			return 0;
+	}
+	
+	if (ns16550) {
+		if (ns16550_port_init() == 0)
+			return 0;
+	}
+	
+	return -1;
+}
+
+void kbd_port_yield(void)
+{
+}
+
+void kbd_port_reclaim(void)
+{
+}
+
+void kbd_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/** @}
+*/
Index: uspace/srv/hid/input/port/z8530.c
===================================================================
--- uspace/srv/hid/input/port/z8530.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
+++ uspace/srv/hid/input/port/z8530.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2006 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 kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief Z8530 keyboard port driver.
+ */
+
+#include <ipc/irc.h>
+#include <async.h>
+#include <sysinfo.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sun.h>
+#include <sys/types.h>
+#include <ddi.h>
+#include <errno.h>
+
+#define CHAN_A_STATUS  4
+#define CHAN_A_DATA    6
+
+#define RR0_RCA  1
+
+static irq_cmd_t z8530_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,     /* Will be patched in run-time */
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_BTEST,
+		.value = RR0_RCA,
+		.srcarg = 1,
+		.dstarg = 3
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 2,
+		.srcarg = 3
+	},
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,     /* Will be patched in run-time */
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+	
+irq_code_t z8530_kbd = {
+	sizeof(z8530_cmds) / sizeof(irq_cmd_t),
+	z8530_cmds
+};
+
+static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+
+int z8530_port_init(void)
+{
+	sysarg_t kaddr;
+	if (sysinfo_get_value("kbd.address.kernel", &kaddr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	z8530_cmds[0].addr = (void *) kaddr + CHAN_A_STATUS;
+	z8530_cmds[3].addr = (void *) kaddr + CHAN_A_DATA;
+	
+	async_set_interrupt_received(z8530_irq_handler);
+	register_irq(inr, device_assign_devno(), inr, &z8530_kbd);
+	
+	return 0;
+}
+
+static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	int scan_code = IPC_GET_ARG2(*call);
+	kbd_push_scancode(scan_code);
+	
+	if (irc_service)
+		async_msg_1(irc_phone, IRC_CLEAR_INTERRUPT,
+		    IPC_GET_IMETHOD(*call));
+}
+
+/** @}
+ */
Index: uspace/srv/loc/loc.c
===================================================================
--- uspace/srv/loc/loc.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/loc/loc.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -56,10 +56,4 @@
 #define NULL_SERVICES  256
 
-/** Callback session */
-typedef struct {
-	link_t cb_sess_list;
-	async_sess_t *sess;
-} cb_sess_t;
-
 LIST_INITIALIZE(services_list);
 LIST_INITIALIZE(namespaces_list);
@@ -92,5 +86,5 @@
 
 static FIBRIL_MUTEX_INITIALIZE(callback_sess_mutex);
-static LIST_INITIALIZE(callback_sess_list);
+static async_sess_t *callback_sess = NULL;
 
 service_id_t loc_create_id(void)
@@ -614,5 +608,4 @@
 	size_t act_size;
 	loc_service_t *svc;
-	char *fqn;
 	
 	if (!async_data_read_receive(&callid, &size)) {
@@ -632,14 +625,6 @@
 	}
 	
-	if (asprintf(&fqn, "%s/%s", svc->namespace->name, svc->name) < 0) {
-		fibril_mutex_unlock(&services_list_mutex);
-		async_answer_0(callid, ENOMEM);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	act_size = str_size(fqn);
+	act_size = str_size(svc->name);
 	if (act_size > size) {
-		free(fqn);
 		fibril_mutex_unlock(&services_list_mutex);
 		async_answer_0(callid, EOVERFLOW);
@@ -648,7 +633,6 @@
 	}
 	
-	sysarg_t retval = async_data_read_finalize(callid, fqn,
+	sysarg_t retval = async_data_read_finalize(callid, svc->name,
 	    min(size, act_size));
-	free(fqn);
 	
 	fibril_mutex_unlock(&services_list_mutex);
@@ -806,10 +790,7 @@
 }
 
-/** Create callback connection.
- *
- * Create callback connection which will be used to send category change
- * events.
- *
- * On success, answer will contain EOK int retval.
+/** Find ID for category specified by name.
+ *
+ * On success, answer will contain EOK int retval and service ID in arg1.
  * On failure, error code will be sent in retval.
  *
@@ -817,5 +798,5 @@
 static void loc_callback_create(ipc_callid_t iid, ipc_call_t *icall)
 {
-	cb_sess_t *cb_sess = calloc(1, sizeof(cb_sess_t));
+	async_sess_t *cb_sess = async_callback_receive(EXCHANGE_SERIALIZE);
 	if (cb_sess == NULL) {
 		async_answer_0(iid, ENOMEM);
@@ -823,16 +804,12 @@
 	}
 	
-	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
-	if (sess == NULL) {
-		free(cb_sess);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	cb_sess->sess = sess;
-	link_initialize(&cb_sess->cb_sess_list);
-	
 	fibril_mutex_lock(&callback_sess_mutex);
-	list_append(&cb_sess->cb_sess_list, &callback_sess_list);
+	if (callback_sess != NULL) {
+		fibril_mutex_unlock(&callback_sess_mutex);
+		async_answer_0(iid, EEXIST);
+		return;
+	}
+	
+	callback_sess = cb_sess;
 	fibril_mutex_unlock(&callback_sess_mutex);
 	
@@ -843,15 +820,11 @@
 {
 	fibril_mutex_lock(&callback_sess_mutex);
-	
-	list_foreach(callback_sess_list, link) {
-		cb_sess_t *cb_sess;
-		
-		cb_sess = list_get_instance(link, cb_sess_t, cb_sess_list);
-		
-		async_exch_t *exch = async_exchange_begin(cb_sess->sess);
+
+	if (callback_sess != NULL) {
+		async_exch_t *exch = async_exchange_begin(callback_sess);
 		async_msg_0(exch, LOC_EVENT_CAT_CHANGE);
 		async_exchange_end(exch);
 	}
-	
+
 	fibril_mutex_unlock(&callback_sess_mutex);
 }
Index: uspace/srv/net/cfg/e1k.nic
===================================================================
--- uspace/srv/net/cfg/e1k.nic	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/net/cfg/e1k.nic	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -3,5 +3,5 @@
 NAME=e1k
 
-HWPATH=devices/\hw\pci0\00:03.0\port0
+HWPATH=/hw/pci0/00:03.0/port0
 NIL=eth
 IL=ip
Index: uspace/srv/net/cfg/lo.nic
===================================================================
--- uspace/srv/net/cfg/lo.nic	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/net/cfg/lo.nic	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -3,5 +3,5 @@
 NAME=lo
 
-HWPATH=devices/\virt\lo\port0
+HWPATH=/virt/lo/port0
 NIL=nildummy
 IL=ip
Index: uspace/srv/net/cfg/ne2k.nic
===================================================================
--- uspace/srv/net/cfg/ne2k.nic	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/net/cfg/ne2k.nic	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -3,5 +3,5 @@
 NAME=ne2k
 
-HWPATH=devices/\hw\pci0\00:01.0\ne2k\port0
+HWPATH=/hw/pci0/00:01.0/ne2k/port0
 NIL=eth
 IL=ip
Index: uspace/srv/net/net/Makefile
===================================================================
--- uspace/srv/net/net/Makefile	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/net/net/Makefile	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -31,6 +31,5 @@
 ROOT_PATH = $(USPACE_PREFIX)/..
 LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include \
-    -I$(LIBDRV_PREFIX)/include
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
 
 COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/net/net/net.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -2,5 +2,4 @@
  * Copyright (c) 2009 Lukas Mejdrech
  * Copyright (c) 2011 Radim Vansa
- * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -42,4 +41,5 @@
 #include <stdio.h>
 #include <str.h>
+#include <devman.h>
 #include <str_error.h>
 #include <ns.h>
@@ -56,7 +56,4 @@
 #include <adt/measured_strings.h>
 #include <adt/module_map.h>
-#include <fibril_synch.h>
-#include <loc.h>
-#include <nic.h>
 #include <nil_remote.h>
 #include <net_interface.h>
@@ -76,7 +73,4 @@
 GENERIC_CHAR_MAP_IMPLEMENT(measured_strings, measured_string_t);
 DEVICE_MAP_IMPLEMENT(netifs, netif_t);
-LIST_INITIALIZE(netif_list);
-
-static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
 
 /** Add the configured setting to the configuration map.
@@ -293,10 +287,10 @@
  *
  */
-static int init_device(netif_t *netif, service_id_t sid)
+static int init_device(netif_t *netif, devman_handle_t handle)
 {
 	printf("%s: Initializing device '%s'\n", NAME, netif->name);
 	
-	netif->sid = sid;
-	netif->sess = loc_service_connect(EXCHANGE_SERIALIZE, netif->sid,
+	netif->handle = handle;
+	netif->sess = devman_device_connect(EXCHANGE_SERIALIZE, netif->handle,
 	    IPC_FLAG_BLOCKING);
 	if (netif->sess == NULL) {
@@ -343,5 +337,5 @@
 		    strtol((const char *) setting->value, NULL, 10) : 0;
 		rc = nil_device_req(netif->nil->sess, netif->id,
-		    netif->sid, mtu);
+		    netif->handle, mtu);
 		if (rc != EOK) {
 			printf("%s: Unable to start network interface layer\n",
@@ -365,35 +359,22 @@
 		break;
 	default:
-		printf("%s: Unknown service\n", NAME);
 		return ENOENT;
 	}
 	
 	printf("%s: Activating device '%s'\n", NAME, netif->name);
-	list_append(&netif->netif_list, &netif_list);
 	return nic_set_state(netif->sess, NIC_STATE_ACTIVE);
 }
 
-static int net_nic_ready(service_id_t sid)
-{
-	int rc;
-	char *hwpath;
-	
-	rc = loc_service_get_name(sid, &hwpath);
-	if (rc != EOK) {
-		printf("%s: Failed getting name of service '%u'\n",
-		    NAME, (unsigned) sid);
+static int net_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) {
-		printf("%s: Service '%s' not found in map.\n", NAME, hwpath);
-		free(hwpath);
+	if (index == CHAR_MAP_NULL)
 		return ENOENT;
-	}
-	
-	free(hwpath);
 	
 	netif_t *netif = netifs_get_index(&net_globals.netifs, index);
@@ -401,5 +382,5 @@
 		return ENOENT;
 	
-	rc = init_device(netif, sid);
+	rc = init_device(netif, handle);
 	if (rc != EOK)
 		return rc;
@@ -410,4 +391,21 @@
 	
 	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_port_ready(funs[i]);
+		if (rc != EOK)
+			return rc;
+	}
 	
 	return EOK;
@@ -481,4 +479,8 @@
 		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;
@@ -526,71 +528,4 @@
 		answer_call(callid, res, &answer, count);
 	}
-}
-
-static int nic_check_new(void)
-{
-	category_id_t nic_cat;
-	service_id_t *svcs;
-	size_t count, i;
-	bool already_known;
-	int rc;
-
-	fibril_mutex_lock(&discovery_lock);
-
-	rc = loc_category_get_id(DEVICE_CATEGORY_NIC, &nic_cat, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		printf("%s: Failed resolving category '%s'.\n", NAME,
-		    DEVICE_CATEGORY_NIC);
-		return ENOENT;
-	}
-
-	rc = loc_category_get_svcs(nic_cat, &svcs, &count);
-	if (rc != EOK) {
-		printf("%s: Failed getting list of NIC devices.\n", NAME);
-		return EIO;
-	}
-
-	for (i = 0; i < count; i++) {
-		already_known = false;
-
-		list_foreach(netif_list, link) {
-			netif_t *netif = list_get_instance(link, netif_t, netif_list);
-			if (netif->sid == svcs[i]) {
-				already_known = true;
-				break;
-			}
-		}
-
-		if (!already_known) {
-			rc = net_nic_ready(svcs[i]);
-			if (rc != EOK) {
-				printf("%s: Failed adding NIC device #%u.\n",
-				    NAME, (unsigned) svcs[i]);
-			}
-		}
-	}
-
-	free(svcs);
-	fibril_mutex_unlock(&discovery_lock);
-	return EOK;
-}
-
-static void cat_change_cb(void)
-{
-	(void) nic_check_new();
-}
-
-static int net_start_nic_discovery(void)
-{
-	int rc;
-
-	rc = loc_register_cat_change_cb(cat_change_cb);
-	if (rc != EOK) {
-		printf("%s: Failed registering callback for device discovery (%d).\n",
-		    NAME, rc);
-		return rc;
-	}
-
-	return nic_check_new();
 }
 
@@ -638,5 +573,5 @@
 				continue;
 			
-			netif->sid = -1;
+			netif->handle = -1;
 			netif->sess = NULL;
 			
@@ -762,11 +697,4 @@
 	}
 	
-	rc = net_start_nic_discovery();
-	if (rc != EOK) {
-		printf("%s: Error starting NIC discovery\n", NAME);
-		pm_destroy();
-		return rc;
-	}
-	
 	task_retval(0);
 	async_manager();
Index: uspace/srv/net/net/net.h
===================================================================
--- uspace/srv/net/net/net.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/net/net/net.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -35,5 +35,4 @@
 #define NET_NET_H_
 
-#include <ipc/loc.h>
 #include <net/device.h>
 #include <adt/char_map.h>
@@ -42,4 +41,5 @@
 #include <adt/module_map.h>
 #include <net/packet.h>
+#include <devman.h>
 
 #define NAME  "net"
@@ -96,11 +96,9 @@
 	
 	/** Serving network interface driver module index. */
-	service_id_t sid;    /**< Service ID */
-	async_sess_t *sess;  /**< Driver session. */
+	devman_handle_t handle;  /**< Handle for devman */
+	async_sess_t *sess;      /**< Driver session. */
 	
 	module_t *nil;  /**< Serving link layer module index. */
 	module_t *il;   /**< Serving internet layer module index. */
-	
-	link_t netif_list;
 } netif_t;
 
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/net/nil/eth/eth.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -48,5 +48,4 @@
 #include <ipc/net.h>
 #include <ipc/services.h>
-#include <loc.h>
 #include <net/modules.h>
 #include <net_checksum.h>
@@ -170,8 +169,5 @@
 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
 
-static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg);
-
-static int eth_device_state(eth_device_t *device, sysarg_t state)
+int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
 {
 	int index;
@@ -183,6 +179,6 @@
 		proto = eth_protos_get_index(&eth_globals.protos, index);
 		if ((proto) && (proto->sess)) {
-			il_device_state_msg(proto->sess, device->device_id,
-			    state, proto->service);
+			il_device_state_msg(proto->sess, device_id, state,
+			    proto->service);
 		}
 	}
@@ -230,5 +226,5 @@
  *
  * @param[in] device_id New device identifier.
- * @param[in] sid       NIC service ID.
+ * @param[in] handle    Device driver handle.
  * @param[in] mtu       Device maximum transmission unit.
  *
@@ -238,5 +234,5 @@
  *
  */
-static int eth_device_message(nic_device_id_t device_id, service_id_t sid,
+static int eth_device_message(nic_device_id_t device_id, devman_handle_t handle,
     size_t mtu)
 {
@@ -263,5 +259,5 @@
 	device = eth_devices_find(&eth_globals.devices, device_id);
 	if (device) {
-		if (device->sid != sid) {
+		if (device->handle != handle) {
 			printf("Device %d already exists\n", device->device_id);
 			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
@@ -302,5 +298,5 @@
 
 	device->device_id = device_id;
-	device->sid = sid;
+	device->handle = handle;
 	device->flags = 0;
 	if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
@@ -339,5 +335,5 @@
 	
 	/* Bind the device driver */
-	device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid,
+	device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
 	    IPC_FLAG_BLOCKING);
 	if (device->sess == NULL) {
@@ -347,11 +343,5 @@
 	}
 	
-	rc = nic_callback_create(device->sess, eth_nic_cb_connection, device);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		async_hangup(device->sess);
-		free(device);
-		return EIO;
-	}
+	nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id);
 	
 	/* Get hardware address */
@@ -372,7 +362,7 @@
 	}
 	
-	printf("%s: Device registered (id: %d, sid: %zu: mtu: %zu, "
+	printf("%s: Device registered (id: %d, handle: %zu: mtu: %zu, "
 	    "mac: " PRIMAC ", flags: 0x%x)\n", NAME,
-	    device->device_id, device->sid, device->mtu,
+	    device->device_id, device->handle, device->mtu,
 	    ARGSMAC(device->addr.address), device->flags);
 
@@ -824,28 +814,5 @@
 }
 
-static int eth_received(eth_device_t *device)
-{
-	void *data;
-	size_t size;
-	int rc;
-	
-	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
-	if (rc != EOK) {
-		printf("%s: data_write_accept() failed\n", NAME);
-		return rc;
-	}
-	
-	packet_t *packet = packet_get_1_remote(eth_globals.net_sess, size);
-	if (packet == NULL)
-		return ENOMEM;
-	
-	void *pdata = packet_suffix(packet, size);
-	memcpy(pdata, data, size);
-	free(data);
-	
-	return nil_received_msg_local(device->device_id, packet);
-}
-
-static int eth_addr_changed(eth_device_t *device)
+static int eth_addr_changed(nic_device_id_t device_id)
 {
 	nic_address_t address;
@@ -865,24 +832,28 @@
 
 	fibril_rwlock_write_lock(&eth_globals.devices_lock);
-
-	printf("Device %d changing address from " PRIMAC " to " PRIMAC "\n",
-		device->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;
+	/* 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;
+	}
 }
 
@@ -950,40 +921,23 @@
 		
 		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;
 	}
 	
 	return ENOTSUP;
-}
-
-static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	eth_device_t *device = (eth_device_t *)arg;
-	int rc;
-	
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			break;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case NIC_EV_DEVICE_STATE:
-			rc = eth_device_state(device, IPC_GET_ARG1(call));
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_RECEIVED:
-			rc = eth_received(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_ADDR_CHANGED:
-			rc = eth_addr_changed(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-		}
-	}
 }
 
Index: uspace/srv/net/nil/eth/eth.h
===================================================================
--- uspace/srv/net/nil/eth/eth.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/net/nil/eth/eth.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -41,8 +41,8 @@
 #include <async.h>
 #include <fibril_synch.h>
-#include <ipc/loc.h>
 #include <ipc/services.h>
 #include <net/device.h>
 #include <adt/measured_strings.h>
+#include <devman.h>
 
 /** Ethernet address length. */
@@ -224,5 +224,5 @@
 	nic_device_id_t device_id;
 	/** Device handle */
-	service_id_t sid;
+	devman_handle_t handle;
 	/** Driver session. */
 	async_sess_t *sess;
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -2,5 +2,4 @@
  * Copyright (c) 2009 Lukas Mejdrech
  * Copyright (c) 2011 Radim Vansa
- * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -54,6 +53,6 @@
 #include <packet_remote.h>
 #include <packet_client.h>
+#include <devman.h>
 #include <device/nic.h>
-#include <loc.h>
 #include <nil_skel.h>
 #include "nildummy.h"
@@ -70,21 +69,13 @@
 DEVICE_MAP_IMPLEMENT(nildummy_devices, nildummy_device_t);
 
-static void nildummy_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg);
-
-static int nildummy_device_state(nildummy_device_t *device, 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);
 	if (nildummy_globals.proto.sess)
-		il_device_state_msg(nildummy_globals.proto.sess,
-		    device->device_id, state, nildummy_globals.proto.service);
+		il_device_state_msg(nildummy_globals.proto.sess, device_id,
+		    state, nildummy_globals.proto.service);
 	fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
 	
 	return EOK;
-}
-
-static int nildummy_addr_changed(nildummy_device_t *device)
-{
-	return ENOTSUP;
 }
 
@@ -124,5 +115,5 @@
  */
 static int nildummy_device_message(nic_device_id_t device_id,
-    service_id_t sid, size_t mtu)
+    devman_handle_t handle, size_t mtu)
 {
 	fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
@@ -132,5 +123,5 @@
 	    nildummy_devices_find(&nildummy_globals.devices, device_id);
 	if (device) {
-		if (device->sid != sid) {
+		if (device->handle != handle) {
 			printf("Device %d exists, handles do not match\n",
 			    device->device_id);
@@ -167,5 +158,5 @@
 	
 	device->device_id = device_id;
-	device->sid = sid;
+	device->handle = handle;
 	if (mtu > 0)
 		device->mtu = mtu;
@@ -174,5 +165,5 @@
 	
 	/* Bind the device driver */
-	device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid,
+	device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
 	    IPC_FLAG_BLOCKING);
 	if (device->sess == NULL) {
@@ -182,14 +173,8 @@
 	}
 	
-	int rc = nic_callback_create(device->sess, nildummy_nic_cb_conn,
-	    device);
-	if (rc != EOK) {
-		async_hangup(device->sess);
-		
-		return ENOENT;
-	}
+	nic_connect_to_nil(device->sess, SERVICE_NILDUMMY, device_id);
 	
 	/* Get hardware address */
-	rc = nic_get_address(device->sess, &device->addr);
+	int rc = nic_get_address(device->sess, &device->addr);
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
@@ -360,4 +345,6 @@
     services_t sender)
 {
+	packet_t *p;
+	
 	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
 	
@@ -369,5 +356,5 @@
 	}
 	
-	packet_t *p = packet;
+	p = packet;
 	do {
 		nic_send_frame(device->sess, packet_get_data(p),
@@ -381,25 +368,4 @@
 	
 	return EOK;
-}
-
-static int nildummy_received(nildummy_device_t *device)
-{
-	void *data;
-	size_t size;
-	int rc;
-
-	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
-	if (rc != EOK)
-		return rc;
-
-	packet_t *packet = packet_get_1_remote(nildummy_globals.net_sess, size);
-	if (packet == NULL)
-		return ENOMEM;
-
-	void *pdata = packet_suffix(packet, size);
-	memcpy(pdata, data, size);
-	free(pdata);
-
-	return nil_received_msg_local(device->device_id, packet);
 }
 
@@ -458,42 +424,22 @@
 		*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;
 	}
 	
 	return ENOTSUP;
 }
-
-static void nildummy_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	nildummy_device_t *device = (nildummy_device_t *)arg;
-	int rc;
-	
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			break;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case NIC_EV_DEVICE_STATE:
-			rc = nildummy_device_state(device, IPC_GET_ARG1(call));
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_RECEIVED:
-			rc = nildummy_received(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_ADDR_CHANGED:
-			rc = nildummy_addr_changed(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-		}
-	}
-}
-
 
 int main(int argc, char *argv[])
Index: uspace/srv/net/nil/nildummy/nildummy.h
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.h	(revision e10d41aadcc79d6daf95be94a88c873b2da4e492)
+++ uspace/srv/net/nil/nildummy/nildummy.h	(revision 96d9cdd7d2e57187ac2e549b249f642b6dc1522f)
@@ -41,6 +41,6 @@
 #include <async.h>
 #include <fibril_synch.h>
-#include <ipc/loc.h>
 #include <ipc/services.h>
+#include <ipc/devman.h>
 #include <net/device.h>
 
@@ -78,6 +78,6 @@
 	/** Device identifier. */
 	nic_device_id_t device_id;
-	/** Device service ID. */
-	service_id_t sid;
+	/** Device driver handle. */
+	devman_handle_t handle;
 	/** Driver session. */
 	async_sess_t *sess;
