Index: boot/Makefile.grub
===================================================================
--- boot/Makefile.grub	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ boot/Makefile.grub	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -52,8 +52,8 @@
 $(BOOT_OUTPUT): build_dist
 ifeq ($(GRUB_ARCH),pc)
-	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)/
+	$(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)/
 endif
 ifeq ($(GRUB_ARCH),efi)
-	mkisofs -J -r -input-charset utf-8 -V "HelenOS boot ISO" -efi-boot $(ELTORITO) -o $@ $(DISTROOT)/
+	$(GENISOIMAGE) -J -r -input-charset utf-8 -V "HelenOS boot ISO" -efi-boot $(ELTORITO) -o $@ $(DISTROOT)/
 endif
 
Index: boot/Makefile.silo
===================================================================
--- boot/Makefile.silo	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ boot/Makefile.silo	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -41,5 +41,5 @@
 
 $(POST_OUTPUT): build_dist
-	mkisofs -f -G $(ISOFS_B_IN) -B ... -r -o $@ $(DISTROOT)/
+	$(GENISOIMAGE) -f -G $(ISOFS_B_IN) -B ... -r -o $@ $(DISTROOT)/
 
 build_dist: clean
Index: boot/Makefile.yaboot
===================================================================
--- boot/Makefile.yaboot	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ boot/Makefile.yaboot	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -40,5 +40,5 @@
 
 $(POST_OUTPUT): build_dist
-	mkisofs -hfs -part -map $(MAPS) -no-desktop -hfs-volid "HelenOS" -hfs-bless $(DISTROOT)/boot -r -o $@ $(DISTROOT)/
+	$(GENISOIMAGE) -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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ kernel/arch/abs32le/src/abs32le.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -49,5 +49,4 @@
 #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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ kernel/arch/amd64/include/interrupt.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -55,5 +55,4 @@
 #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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ kernel/arch/amd64/src/amd64.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -214,22 +214,8 @@
 		}
 	}
-	
-	/*
-	 * 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ kernel/arch/arm32/src/arm32.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -38,5 +38,4 @@
 #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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ kernel/arch/ia32/include/interrupt.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -55,5 +55,4 @@
 #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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ kernel/arch/ia32/src/ia32.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -168,22 +168,8 @@
 		}
 	}
-	
-	/*
-	 * 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ kernel/arch/ia32/src/mm/frame.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -46,4 +46,6 @@
 #include <print.h>
 
+#define PHYSMEM_LIMIT32  UINT64_C(0x100000000)
+
 size_t hardcoded_unmapped_ktext_size = 0;
 size_t hardcoded_unmapped_kdata_size = 0;
@@ -56,15 +58,16 @@
 		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 >= 0x100000000ULL)
+		if (base64 >= PHYSMEM_LIMIT32)
 			continue;
-		if (base64 + size64 > 0x100000000ULL)
-			size64 -= base64 + size64 - 0x100000000ULL;
+		
+		if (base64 + size64 > PHYSMEM_LIMIT32)
+			size64 = PHYSMEM_LIMIT32 - base64;
 #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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ kernel/arch/ia64/include/interrupt.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -61,5 +61,4 @@
 #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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ kernel/arch/ia64/src/ia64.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -127,5 +127,6 @@
 }
 
-void arch_post_cpu_init(void){
+void arch_post_cpu_init(void)
+{
 }
 
@@ -192,5 +193,6 @@
 	
 #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();
@@ -201,16 +203,6 @@
 		}
 	}
-	
-	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);
-
+#endif
+	
 	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ tools/autotool.py	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -184,4 +184,37 @@
 	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"
@@ -459,5 +492,8 @@
 	
 	for key, value in common.items():
-		outmk.write('%s = %s\n' % (key, value))
+		if (type(value) is list):
+			outmk.write('%s = %s\n' % (key, " ".join(value)))
+		else:
+			outmk.write('%s = %s\n' % (key, value))
 	
 	outmk.close()
@@ -624,5 +660,5 @@
 		# Platform-specific utilities
 		if ((config['BARCH'] == "amd64") or (config['BARCH'] == "ia32") or (config['BARCH'] == "ppc32") or (config['BARCH'] == "sparc64")):
-			check_app(["mkisofs", "--version"], "ISO 9660 creation utility", "usually part of genisoimage")
+			common['GENISOIMAGE'] = check_app_alternatives(["mkisofs", "genisoimage"], ["--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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/app/trace/trace.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -623,5 +623,4 @@
 error:
 	loader_abort(ldr);
-	free(ldr);
 	return NULL;
 }
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/bus/isa/isa.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/bus/isa/isa.dev	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -14,5 +14,4 @@
 	irq 12
 	io_range 060 5
-	
 
 ne2k:
Index: uspace/drv/bus/isa/isa.ma
===================================================================
--- uspace/drv/bus/isa/isa.ma	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/bus/isa/isa.ma	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -1,1 +1,1 @@
-9 pci/ven=8086&dev=7000
+9 pci/class=06&subclass=01
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -92,5 +92,5 @@
 static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
 {
-	/* This is an old ugly way, copied from ne2000 driver */
+	/* This is an old ugly way */
 	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/char/i8042/buffer.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -26,8 +26,10 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /**
  * @addtogroup kbd
  * @{
  */
+
 /** @file
  * @brief Cyclic buffer structure.
@@ -46,22 +48,26 @@
  * 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);
@@ -74,27 +80,29 @@
 
 /** 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;
@@ -103,22 +111,26 @@
 
 /** 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;
@@ -127,12 +139,14 @@
 	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/char/i8042/i8042.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -29,8 +29,10 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /** @addtogroup kbd_port
  * @ingroup kbd
  * @{
  */
+
 /** @file
  * @brief i8042 PS/2 port driver.
@@ -44,11 +46,55 @@
 #include <str_error.h>
 #include <inttypes.h>
-
 #include <ddf/log.h>
 #include <ddf/interrupt.h>
-
 #include "i8042.h"
 
-#define NAME       "i8042"
+/* 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)
 
 void default_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
@@ -59,25 +105,9 @@
 };
 
-/* 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
 	},
@@ -95,5 +125,5 @@
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,	/* will be patched in run-time */
+		.addr = NULL,  /* will be patched in run-time */
 		.dstarg = 2
 	},
@@ -111,31 +141,40 @@
 
 /** Interrupt handler routine.
- * Writes new data to the corresponding buffer.
- * @param dev Device that caued the interrupt.
- * @param iid Call id.
+ *
+ * Write 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,
@@ -144,14 +183,15 @@
 	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) {
@@ -159,5 +199,5 @@
 		return ret;
 	}
-
+	
 	dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
 	if (!dev->aux_fun) {
@@ -165,5 +205,5 @@
 		return ENOMEM;
 	}
-
+	
 	ret = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
 	if (ret != EOK) {
@@ -172,35 +212,22 @@
 		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);
@@ -208,24 +235,9 @@
 	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];
@@ -233,16 +245,20 @@
 	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 =
@@ -251,10 +267,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);
@@ -263,9 +279,9 @@
 	pio_write_8(&dev->regs->data, i8042_KBD_IE | i8042_KBD_TRANSLATE |
 	    i8042_AUX_IE);
-
+	
 	return EOK;
 }
 
-// TODO use shared instead this
+// FIXME TODO use shared instead this
 enum {
 	IPC_CHAR_READ = DEV_FIRST_CUSTOM_METHOD,
@@ -274,8 +290,11 @@
 
 /** 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)
@@ -283,13 +302,19 @@
 	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;
@@ -297,8 +322,11 @@
 
 /** 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)
@@ -306,18 +334,21 @@
 	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)
@@ -325,31 +356,35 @@
 	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/char/i8042/i8042.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -27,8 +27,10 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /** @addtogroup kbd_port
  * @ingroup  kbd
  * @{
  */
+
 /** @file
  * @brief i8042 port driver.
@@ -41,8 +43,9 @@
 #include <fibril_synch.h>
 #include <ddf/driver.h>
-
 #include "buffer.h"
 
-#define BUFFER_SIZE 12
+#define NAME  "i8042"
+
+#define BUFFER_SIZE  12
 
 /** i8042 HW I/O interface */
@@ -55,9 +58,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. */
@@ -66,5 +69,7 @@
 
 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/char/i8042/main.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -26,7 +26,9 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /** @addtogroup drvi8042
  * @{
  */
+
 /** @file
  * @brief i8042 driver DDF bits.
@@ -41,12 +43,100 @@
 #include <ddf/log.h>
 #include <stdio.h>
-
 #include "i8042.h"
 
-#define NAME "i8042"
+#define CHECK_RET_RETURN(ret, message...) \
+	do { \
+		if (ret != EOK) { \
+			ddf_msg(LVL_ERROR, message); \
+			return ret; \
+		} \
+	} while (0)
 
-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);
+/** 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;
+}
 
 /** DDF driver operations. */
@@ -61,107 +151,11 @@
 };
 
-/** 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(NAME ": HelenOS ps/2 driver.\n");
+	printf("%s: HelenOS PS/2 driver.\n", NAME);
 	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/char/ps2mouse/ps2mouse.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -116,5 +116,5 @@
 	assert(mouse);
 	assert(dev);
-	mouse->input_sess = NULL;
+	mouse->client_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->input_sess);
+		    async_exchange_begin(mouse->client_sess);
 		if (!exch) {
 			ddf_msg(LVL_ERROR,
-			    "Failed to create input exchange.");
+			    "Failed creating exchange.");
 			continue;
 		}
@@ -277,8 +277,8 @@
 
 		async_exch_t *exch =
-		    async_exchange_begin(mouse->input_sess);
+		    async_exchange_begin(mouse->client_sess);
 		if (!exch) {
 			ddf_msg(LVL_ERROR,
-			    "Failed to create input exchange.");
+			    "Failed creating exchange.");
 			continue;
 		}
@@ -386,14 +386,14 @@
 		if (sess == NULL) {
 			ddf_msg(LVL_WARN,
-			    "Failed to create start input session");
+			    "Failed creating client callback session");
 			async_answer_0(icallid, EAGAIN);
 			break;
 		}
-		if (mouse->input_sess == NULL) {
-			mouse->input_sess = sess;
-			ddf_msg(LVL_DEBUG, "Set input session");
+		if (mouse->client_sess == NULL) {
+			mouse->client_sess = sess;
+			ddf_msg(LVL_DEBUG, "Set client session");
 			async_answer_0(icallid, EOK);
 		} else {
-			ddf_msg(LVL_ERROR, "Input session already set");
+			ddf_msg(LVL_ERROR, "Client session already set");
 			async_answer_0(icallid, ELIMIT);
 		}
Index: uspace/drv/char/ps2mouse/ps2mouse.h
===================================================================
--- uspace/drv/char/ps2mouse/ps2mouse.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/char/ps2mouse/ps2mouse.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -43,5 +43,5 @@
 	ddf_fun_t *mouse_fun;      /**< Mouse function. */
 	async_sess_t *parent_sess; /**< Connection to device providing data. */
-	async_sess_t *input_sess;  /**< Callback connection to consumer. */
+	async_sess_t *client_sess;  /**< Callback connection to client. */
 	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/char/xtkbd/xtkbd.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -206,5 +206,5 @@
 	assert(kbd);
 	assert(dev);
-	kbd->input_sess = NULL;
+	kbd->client_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->input_sess);
+			    async_exchange_begin(kbd->client_sess);
 			if (!exch) {
 				ddf_msg(LVL_ERROR,
-				    "Failed to create input exchange.");
+				    "Failed creating exchange.");
 				continue;
 			}
@@ -352,14 +352,14 @@
 		if (sess == NULL) {
 			ddf_msg(LVL_WARN,
-			    "Failed to create start input session");
+			    "Failed creating callback session");
 			async_answer_0(icallid, EAGAIN);
 			break;
 		}
-		if (kbd->input_sess == NULL) {
-			kbd->input_sess = sess;
-			ddf_msg(LVL_DEBUG, "Set input session");
+		if (kbd->client_sess == NULL) {
+			kbd->client_sess = sess;
+			ddf_msg(LVL_DEBUG, "Set client session");
 			async_answer_0(icallid, EOK);
 		} else {
-			ddf_msg(LVL_ERROR, "Input session already set");
+			ddf_msg(LVL_ERROR, "Client session already set");
 			async_answer_0(icallid, ELIMIT);
 		}
Index: uspace/drv/char/xtkbd/xtkbd.h
===================================================================
--- uspace/drv/char/xtkbd/xtkbd.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/char/xtkbd/xtkbd.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -43,5 +43,5 @@
 	ddf_fun_t *kbd_fun;        /**< Keyboard function. */
 	async_sess_t *parent_sess; /**< Connection to device providing data. */
-	async_sess_t *input_sess;  /**< Callback connection to consumer. */
+	async_sess_t *client_sess; /**< Callback connection to client. */
 	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/nic/e1k/e1k.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -52,7 +52,4 @@
 #include <nil_remote.h>
 #include <ops/nic.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <net/packet_header.h>
 #include "e1k.h"
 
@@ -62,13 +59,13 @@
 
 /* Must be power of 8 */
-#define E1000_RX_PACKETS_COUNT  128
-#define E1000_TX_PACKETS_COUNT  128
+#define E1000_RX_FRAME_COUNT  128
+#define E1000_TX_FRAME_COUNT  128
 
 #define E1000_RECEIVE_ADDRESS  16
 
-/** Maximum sending packet size */
+/** Maximum sending frame size */
 #define E1000_MAX_SEND_FRAME_SIZE  2048
-/** Maximum receiving packet size */
-#define E1000_MAX_RECEIVE_PACKET_SIZE  2048
+/** Maximum receiving frame size */
+#define E1000_MAX_RECEIVE_FRAME_SIZE  2048
 
 /** nic_driver_data_t* -> e1000_t* cast */
@@ -137,11 +134,13 @@
 	void *rx_ring_virt;
 	
-	/** Packets in rx ring  */
-	packet_t **rx_ring_packets;
+	/** Ring of RX frames, physical address */
+	void **rx_frame_phys;
+	/** Ring of RX frames, virtual address */
+	void **rx_frame_virt;
 	
 	/** VLAN tag */
 	uint16_t vlan_tag;
 	
-	/** Add VLAN tag to packet */
+	/** Add VLAN tag to frame */
 	bool vlan_tag_add;
 	
@@ -477,5 +476,5 @@
 }
 
-/** Get state of acceptance of weird packets
+/** Get state of acceptance of weird frames
  *
  * @param      device Device to check
@@ -495,5 +494,5 @@
 };
 
-/** Set acceptance of weird packets
+/** Set acceptance of weird frames
  *
  * @param device Device to update
@@ -679,5 +678,5 @@
 }
 
-/** Disable receiving packets for default address
+/** Disable receiving frames for default address
  *
  * @param e1000 E1000 data structure
@@ -691,5 +690,5 @@
 }
 
-/** Enable receiving packets for default address
+/** Enable receiving frames for default address
  *
  * @param e1000 E1000 data structure
@@ -751,5 +750,5 @@
 }
 
-/** Enable accepting of broadcast packets
+/** Enable accepting of broadcast frames
  *
  * @param e1000 E1000 data structure
@@ -763,5 +762,5 @@
 }
 
-/** Disable accepting of broadcast packets
+/** Disable accepting of broadcast frames
  *
  * @param e1000 E1000 data structure
@@ -799,5 +798,5 @@
 }
 
-/** Set multicast packets acceptance mode
+/** Set multicast frames acceptance mode
  *
  * @param nic      NIC device to update
@@ -853,5 +852,5 @@
 }
 
-/** Set unicast packets acceptance mode
+/** Set unicast frames acceptance mode
  *
  * @param nic      NIC device to update
@@ -911,5 +910,5 @@
 }
 
-/** Set broadcast packets acceptance mode
+/** Set broadcast frames acceptance mode
  *
  * @param nic  NIC device to update
@@ -996,5 +995,5 @@
 	if (vlan_mask) {
 		/*
-		 * Disable receiving, so that packet matching
+		 * Disable receiving, so that frame matching
 		 * partially written VLAN is not received.
 		 */
@@ -1063,7 +1062,7 @@
 }
 
-/** Fill receive descriptor with new empty packet
- *
- * Store packet in e1000->rx_ring_packets
+/** Fill receive descriptor with new empty buffer
+ *
+ * Store frame in e1000->rx_frame_phys
  *
  * @param nic    NIC data stricture
@@ -1074,22 +1073,9 @@
 {
 	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));
 	
-	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->phys_addr = PTR_TO_U64(e1000->rx_frame_phys[offset]);
 	rx_descriptor->length = 0;
 	rx_descriptor->checksum = 0;
@@ -1155,10 +1141,10 @@
 }
 
-/** Receive packets
+/** Receive frames
  *
  * @param nic NIC data
  *
  */
-static void e1000_receive_packets(nic_t *nic)
+static void e1000_receive_frames(nic_t *nic)
 {
 	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
@@ -1167,5 +1153,5 @@
 	
 	uint32_t *tail_addr = E1000_REG_ADDR(e1000, E1000_RDT);
-	uint32_t next_tail = e1000_inc_tail(*tail_addr, E1000_RX_PACKETS_COUNT);
+	uint32_t next_tail = e1000_inc_tail(*tail_addr, E1000_RX_FRAME_COUNT);
 	
 	e1000_rx_descriptor_t *rx_descriptor = (e1000_rx_descriptor_t *)
@@ -1173,16 +1159,18 @@
 	
 	while (rx_descriptor->status & 0x01) {
-		uint32_t packet_size = rx_descriptor->length - E1000_CRC_SIZE;
+		uint32_t frame_size = rx_descriptor->length - E1000_CRC_SIZE;
 		
-		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);
+		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.");
+		}
 		
 		e1000_fill_new_rx_descriptor(nic, next_tail);
 		
-		*tail_addr = e1000_inc_tail(*tail_addr, E1000_RX_PACKETS_COUNT);
-		next_tail = e1000_inc_tail(*tail_addr, E1000_RX_PACKETS_COUNT);
+		*tail_addr = e1000_inc_tail(*tail_addr, E1000_RX_FRAME_COUNT);
+		next_tail = e1000_inc_tail(*tail_addr, E1000_RX_FRAME_COUNT);
 		
 		rx_descriptor = (e1000_rx_descriptor_t *)
@@ -1225,5 +1213,5 @@
 {
 	if (icr & ICR_RXT0)
-		e1000_receive_packets(nic);
+		e1000_receive_frames(nic);
 }
 
@@ -1274,5 +1262,5 @@
 }
 
-/** Force receiving all packets in the receive buffer
+/** Force receiving all frames in the receive buffer
  *
  * @param nic NIC data
@@ -1347,9 +1335,9 @@
 static void e1000_initialize_rx_registers(e1000_t *e1000)
 {
-	E1000_REG_WRITE(e1000, E1000_RDLEN, E1000_RX_PACKETS_COUNT * 16);
+	E1000_REG_WRITE(e1000, E1000_RDLEN, E1000_RX_FRAME_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_PACKETS_COUNT - 1);
+	E1000_REG_WRITE(e1000, E1000_RDT, E1000_RX_FRAME_COUNT - 1);
 	
 	/* Set Broadcast Enable Bit */
@@ -1371,5 +1359,5 @@
 	
 	int rc = dmamem_map_anonymous(
-	    E1000_RX_PACKETS_COUNT * sizeof(e1000_rx_descriptor_t),
+	    E1000_RX_FRAME_COUNT * sizeof(e1000_rx_descriptor_t),
 	    AS_AREA_READ | AS_AREA_WRITE, 0, &e1000->rx_ring_phys,
 	    &e1000->rx_ring_virt);
@@ -1382,52 +1370,92 @@
 	    (uint32_t) PTR_TO_U64(e1000->rx_ring_phys));
 	
-	e1000->rx_ring_packets =
-	    malloc(E1000_RX_PACKETS_COUNT * sizeof(packet_t *));
-	// FIXME: Check return value
-	
+	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;
+	}
+	
+	/* Write descriptor */
+	for (i = 0; i < E1000_RX_FRAME_COUNT; i++)
+		e1000_fill_new_rx_descriptor(nic, i);
+	
+	e1000_initialize_rx_registers(e1000);
+	
+	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;
+}
+
+/** Uninitialize receive structure
+ *
+ * @param nic NIC data
+ *
+ */
+static void e1000_uninitialize_rx_structure(nic_t *nic)
+{
+	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_PACKETS_COUNT;
-	    offset++)
-		e1000_fill_new_rx_descriptor(nic, offset);
-	
-	e1000_initialize_rx_registers(e1000);
-	
-	fibril_mutex_unlock(&e1000->rx_lock);
-	return EOK;
-}
-
-/** Uninitialize receive structure
- *
- * @param nic NIC data
- *
- */
-static void e1000_uninitialize_rx_structure(nic_t *nic)
-{
-	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
-	
-	/* Write descriptor */
-	for (unsigned int offset = 0;
-	    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_RX_FRAME_COUNT;
 	    offset++)
 		e1000_clear_rx_descriptor(e1000, offset);
@@ -1498,5 +1526,5 @@
 static void e1000_initialize_tx_registers(e1000_t *e1000)
 {
-	E1000_REG_WRITE(e1000, E1000_TDLEN, E1000_TX_PACKETS_COUNT * 16);
+	E1000_REG_WRITE(e1000, E1000_TDLEN, E1000_TX_FRAME_COUNT * 16);
 	E1000_REG_WRITE(e1000, E1000_TDH, 0);
 	E1000_REG_WRITE(e1000, E1000_TDT, 0);
@@ -1530,5 +1558,5 @@
 	
 	int rc = dmamem_map_anonymous(
-	    E1000_TX_PACKETS_COUNT * sizeof(e1000_tx_descriptor_t),
+	    E1000_TX_FRAME_COUNT * sizeof(e1000_tx_descriptor_t),
 	    AS_AREA_READ | AS_AREA_WRITE, 0, &e1000->tx_ring_phys,
 	    &e1000->tx_ring_virt);
@@ -1537,8 +1565,8 @@
 	
 	bzero(e1000->tx_ring_virt,
-	    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 *));
+	    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 *));
 
 	if (e1000->tx_frame_phys == NULL || e1000->tx_frame_virt == NULL) {
@@ -1547,5 +1575,5 @@
 	}
 	
-	for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
+	for (i = 0; i < E1000_TX_FRAME_COUNT; i++) {
 		rc = dmamem_map_anonymous(
 		    E1000_MAX_SEND_FRAME_SIZE, AS_AREA_READ | AS_AREA_WRITE,
@@ -1572,5 +1600,5 @@
 	
 	if (e1000->tx_frame_phys != NULL && e1000->tx_frame_virt != NULL) {
-		for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
+		for (i = 0; i < E1000_TX_FRAME_COUNT; i++) {
 			if (e1000->tx_frame_virt[i] != NULL) {
 				dmamem_unmap_anonymous(e1000->tx_frame_virt[i]);
@@ -1603,5 +1631,5 @@
 	size_t i;
 	
-	for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
+	for (i = 0; i < E1000_TX_FRAME_COUNT; i++) {
 		dmamem_unmap_anonymous(e1000->tx_frame_virt[i]);
 		e1000->tx_frame_virt[i] = NULL;
@@ -1618,4 +1646,5 @@
 		e1000->tx_frame_phys = NULL;
 	}
+	
 	dmamem_unmap_anonymous(e1000->tx_ring_virt);
 }
@@ -1630,5 +1659,5 @@
 	/* Write descriptor */
 	for (unsigned int offset = 0;
-	    offset < E1000_TX_PACKETS_COUNT;
+	    offset < E1000_TX_FRAME_COUNT;
 	    offset++)
 		e1000_clear_tx_descriptor(nic, offset);
@@ -1687,5 +1716,5 @@
 }
 
-/** Activate the device to receive and transmit packets
+/** Activate the device to receive and transmit frames
  *
  * @param nic NIC driver data
@@ -2028,5 +2057,4 @@
 	case E1000_82545:
 	case E1000_82546:
-	case E1000_82572:
 		e1000->info.eerd_start = 0x01;
 		e1000->info.eerd_done = 0x10;
@@ -2035,4 +2063,5 @@
 		break;
 	case E1000_82547:
+	case E1000_82572:
 	case E1000_80003ES2:
 		e1000->info.eerd_start = 0x01;
@@ -2073,4 +2102,5 @@
 int e1000_dev_add(ddf_dev_t *dev)
 {
+	ddf_fun_t *fun;
 	assert(dev);
 	
@@ -2103,11 +2133,14 @@
 	e1000_initialize_vlan(e1000);
 	
-	rc = nic_register_as_ddf_fun(nic, &e1000_dev_ops);
-	if (rc != EOK)
+	fun = ddf_fun_create(nic_get_ddf_dev(nic), fun_exposed, "port0");
+	if (fun == NULL)
 		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_tx_structure;
+		goto err_fun_create;
 	
 	rc = nic_connect_to_services(nic);
@@ -2132,10 +2165,24 @@
 		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);
@@ -2283,5 +2330,5 @@
 	
 	if (!descriptor_available) {
-		/* Packet lost */
+		/* Frame lost */
 		fibril_mutex_unlock(&e1000->tx_lock);
 		return;
@@ -2312,5 +2359,5 @@
 	
 	tdt++;
-	if (tdt == E1000_TX_PACKETS_COUNT)
+	if (tdt == E1000_TX_FRAME_COUNT)
 		tdt = 0;
 	
Index: uspace/drv/nic/e1k/e1k.h
===================================================================
--- uspace/drv/nic/e1k/e1k.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/nic/e1k/e1k.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -39,5 +39,5 @@
 #include <stdint.h>
 
-/** Ethernet CRC size after packet received in rx_descriptor */
+/** Ethernet CRC size after frame 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 Packet Enable */
+	TXDESCRIPTOR_COMMAND_VLE = (1 << 6),   /**< VLAN frame 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/nic/lo/lo.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -42,5 +42,4 @@
 #include <async.h>
 #include <nic.h>
-#include <packet_client.h>
 
 #define NAME  "lo"
@@ -61,17 +60,6 @@
 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_packet(nic_data, packet);
+	nic_received_noneth_frame(nic_data, data, size);
 }
 
@@ -92,36 +80,61 @@
 static int lo_dev_add(ddf_dev_t *dev)
 {
-	nic_t *nic_data = nic_create_and_bind(dev);
-	if (nic_data == NULL) {
+	ddf_fun_t *fun = NULL;
+	bool bound = false;
+	
+	nic_t *nic = nic_create_and_bind(dev);
+	if (nic == NULL) {
 		printf("%s: Failed to initialize\n", NAME);
 		return ENOMEM;
 	}
 	
-	dev->driver_data = nic_data;
-	nic_set_send_frame_handler(nic_data, lo_send_frame);
+	dev->driver_data = nic;
+	nic_set_send_frame_handler(nic, lo_send_frame);
 	
-	int rc = nic_connect_to_services(nic_data);
+	int rc = nic_connect_to_services(nic);
 	if (rc != EOK) {
 		printf("%s: Failed to connect to services\n", NAME);
-		nic_unbind_and_destroy(dev);
-		return rc;
+		goto error;
 	}
 	
-	rc = nic_register_as_ddf_fun(nic_data, &lo_dev_ops);
+	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;
+	}
+	nic_set_ddf_fun(nic, fun);
+	fun->ops = &lo_dev_ops;
+	fun->driver_data = nic;
+	
+	rc = nic_report_address(nic, &lo_addr);
 	if (rc != EOK) {
-		printf("%s: Failed to register as DDF function\n", NAME);
-		nic_unbind_and_destroy(dev);
-		return rc;
+		printf("%s: Failed to setup loopback address\n", NAME);
+		goto error;
 	}
 	
-	rc = nic_report_address(nic_data, &lo_addr);
+	rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
-		printf("%s: Failed to setup loopback address\n", NAME);
-		nic_unbind_and_destroy(dev);
-		return rc;
+		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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/nic/ne2k/dp8390.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -59,6 +59,4 @@
 #include <stdio.h>
 #include <libarch/ddi.h>
-#include <net/packet.h>
-#include <packet_client.h>
 #include "dp8390.h"
 
@@ -76,5 +74,5 @@
 	uint8_t status;
 	
-	/** Pointer to next packet */
+	/** Pointer to next frame */
 	uint8_t next;
 	
@@ -393,6 +391,6 @@
 	/*
 	 * Reset the transmit ring. If we were transmitting a frame,
-	 * we pretend that the packet is processed. Higher layers will
-	 * retransmit if the packet wasn't actually sent.
+	 * we pretend that the frame is processed. Higher layers will
+	 * retransmit if the frame wasn't actually sent.
 	 */
 	ne2k->sq.dirty = false;
@@ -448,6 +446,5 @@
 		return NULL;
 	
-	void *buf = packet_suffix(frame->packet, length);
-	bzero(buf, length);
+	bzero(frame->data, length);
 	uint8_t last = page + length / DP_PAGE;
 	
@@ -455,10 +452,10 @@
 		size_t left = (ne2k->stop_page - page) * DP_PAGE
 		    - sizeof(recv_header_t);
-		ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
+		ne2k_download(ne2k, frame->data, page * DP_PAGE + sizeof(recv_header_t),
 		    left);
-		ne2k_download(ne2k, buf + left, ne2k->start_page * DP_PAGE,
+		ne2k_download(ne2k, frame->data + left, ne2k->start_page * DP_PAGE,
 		    length - left);
 	} else {
-		ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
+		ne2k_download(ne2k, frame->data, page * DP_PAGE + sizeof(recv_header_t),
 		    length);
 	}
@@ -541,5 +538,5 @@
 		 * Update the boundary pointer
 		 * to the value of the page
-		 * prior to the next packet to
+		 * prior to the next frame to
 		 * be processed.
 		 */
@@ -584,5 +581,5 @@
 		fibril_mutex_lock(&ne2k->sq_mutex);
 		if (ne2k->sq.dirty) {
-			/* Prepare the buffer for next packet */
+			/* Prepare the buffer for next frame */
 			ne2k->sq.dirty = false;
 			ne2k->sq.size = 0;
Index: uspace/drv/nic/ne2k/dp8390.h
===================================================================
--- uspace/drv/nic/ne2k/dp8390.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/nic/ne2k/dp8390.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -264,5 +264,4 @@
 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -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 packet may also be lost, but this is not a problem.
+	 * that. Some frames may also be lost, but this is not a problem.
 	 */
 	ne2k_set_physical_address((ne2k_t *) nic_get_specific(nic_data), address);
@@ -338,4 +338,6 @@
 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);
@@ -371,5 +373,5 @@
 	}
 	
-	rc = nic_register_as_ddf_fun(nic_data, &ne2k_dev_ops);
+	rc = nic_connect_to_services(nic_data);
 	if (rc != EOK) {
 		ne2k_dev_cleanup(dev);
@@ -377,7 +379,24 @@
 	}
 	
-	rc = nic_connect_to_services(nic_data);
-	if (rc != EOK) {
+	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;
 	}
Index: uspace/drv/nic/rtl8139/defs.h
===================================================================
--- uspace/drv/nic/rtl8139/defs.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/nic/rtl8139/defs.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -29,29 +29,33 @@
 /** @file 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_
+ * Registers, bit positions and masks definition
+ * of the RTL8139 network family cards
+ */
+
+#ifndef RTL8139_DEFS_H_
+#define RTL8139_DEFS_H_
+
 #include <sys/types.h>
 #include <libarch/ddi.h>
 
-
-/** 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
-
+/** 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
 
 /** HW version
  *
- *  as can be detected from HWVERID part of TCR
- *  (Transmit Configuration Register)
- */
-enum rtl8139_version_id {
+ * As can be detected from HWVERID part of TCR
+ * (Transmit Configuration Register).
+ *
+ */
+typedef enum {
 	RTL8139 = 0,          /**< RTL8139 */
 	RTL8139A,             /**< RTL8139A */
@@ -66,7 +70,5 @@
 	RTL8101,              /**< RTL8101 */
 	RTL8139_VER_COUNT     /**< Count of known RTL versions, the last value */
-};
-
-extern const char* model_names[RTL8139_VER_COUNT];
+} rtl8139_version_id_t;
 
 /** Registers of RTL8139 family card offsets from the memory address base */
@@ -75,5 +77,5 @@
 	MAC0  = IDR0,    /**< Alias for IDR0 */
 
-	// 0x6 - 0x7 reserved
+	// 0x06 - 0x07 reserved
 
 	MAR0    = 0x08,  /**< Multicast mask registers 8 1b registers sequence */
@@ -94,5 +96,5 @@
 
 	CR      = 0x37,  /**< Command register, 1b */
-	CAPR    = 0x38,  /**< Current address of packet read, 2b */
+	CAPR    = 0x38,  /**< Current address of frame read, 2b */
 	CBA     = 0x3a,  /**< Current buffer address, 2b */
 
@@ -213,4 +215,5 @@
 	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)
@@ -282,5 +285,5 @@
 	RCR_MulERINT = 1 << 17,    /**< Multiple early interrupt select */
 
-	/** Minimal error packet length (1 = 8B, 0 = 64B). If AER/AR is set, RER8
+	/** Minimal error frame length (1 = 8B, 0 = 64B). If AER/AR is set, RER8
 	 * is "Don't care"
 	 */
@@ -302,10 +305,10 @@
 
 	RCR_WRAP              = 1 << 7,  /**< Rx buffer wrapped */
-	RCR_ACCEPT_ERROR      = 1 << 5,  /**< Accept error packet */
-	RCR_ACCEPT_RUNT       = 1 << 4,  /**< Accept Runt (8-64 bytes) packets */
+	RCR_ACCEPT_ERROR      = 1 << 5,  /**< Accept error frame */
+	RCR_ACCEPT_RUNT       = 1 << 4,  /**< Accept Runt (8-64 bytes) frames */
 	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 packets with 
+	RCR_ACCEPT_ALL_PHYS   = 1 << 0,  /**< Accept all frames with 
 	                                  * phys. desticnation 
 									  */
@@ -362,5 +365,5 @@
 	ANAR_ACK          = (1 << 14),  /**< Capability reception acknowledge */
 	ANAR_REMOTE_FAULT = (1 << 13),  /**< Remote fault detection capability */
-	ANAR_PAUSE        = (1 << 10),  /**< Symetric pause packet capability */
+	ANAR_PAUSE        = (1 << 10),  /**< Symetric pause frame capability */
 	ANAR_100T4        = (1 << 9),   /**< T4, not supported by the device */
 	ANAR_100TX_FD     = (1 << 8),   /**< 100BASE_TX full duplex */
@@ -399,5 +402,5 @@
 	CONFIG3_GNT_SELECT = (1 << 7),  /**< Gnt select */
 	CONFIG3_PARM_EN    = (1 << 6),  /**< Parameter enabled (100MBit mode) */
-	CONFIG3_MAGIC      = (1 << 5),  /**< WoL Magic packet enable */
+	CONFIG3_MAGIC      = (1 << 5),  /**< WoL Magic frame enable */
 	CONFIG3_LINK_UP    = (1 << 4),  /**< Wakeup if link is reestablished */
 	CONFIG3_CLKRUN_EN  = (1 << 2),  /**< CLKRUN enabled */ /* TODO: check what does it mean */
@@ -416,9 +419,9 @@
 };
 
-/** Maximal runt packet size + 1 */
-#define RTL8139_RUNT_MAX_SIZE 64
-
-/** Bits in packet header */
-enum rtl8139_packet_header {
+/** Maximal runt frame size + 1 */
+#define RTL8139_RUNT_MAX_SIZE  64
+
+/** Bits in frame header */
+enum rtl8139_frame_header {
 	RSR_MAR  = (1 << 15),  /**< Multicast received */
 	RSR_PAM  = (1 << 14),  /**< Physical address match */
@@ -426,10 +429,10 @@
 
 	RSR_ISE  = (1 << 5),   /**< Invalid symbol error, 100BASE-TX only */
-	RSR_RUNT = (1 << 4),   /**< Runt packet (< RTL8139_RUNT_MAX_SIZE bytes) */
-
-	RSR_LONG = (1 << 3),   /**< Long packet (size > 4k bytes) */
+	RSR_RUNT = (1 << 4),   /**< Runt frame (< RTL8139_RUNT_MAX_SIZE bytes) */
+
+	RSR_LONG = (1 << 3),   /**< Long frame (size > 4k bytes) */
 	RSR_CRC  = (1 << 2),   /**< CRC error */
 	RSR_FAE  = (1 << 1),   /**< Frame alignment error */
-	RSR_ROK  = (1 << 0)    /**< Good packet received */
+	RSR_ROK  = (1 << 0)    /**< Good frame received */
 };
 
@@ -451,5 +454,5 @@
 									  */
 
-	APPEND_CRC = 1 << 16,        /**< Append CRC at the end of a packet */
+	APPEND_CRC = 1 << 16,        /**< Append CRC at the end of a frame */
 
 	MXTxDMA_SHIFT = 8,  /**< Max. DMA Burst per TxDMA shift, burst = 16^value */
@@ -459,5 +462,5 @@
 	TX_RETRY_COUNT_SIZE  = 4,            /**< Retries before aborting size */
 
-	CLEAR_ABORT = 1 << 0    /**< Retransmit aborted packet at the last 
+	CLEAR_ABORT = 1 << 0    /**< Retransmit aborted frame at the last 
 	                          *  transmitted descriptor 
 							  */
@@ -470,19 +473,21 @@
 
 /** Mapping of HW version -> version ID */
-struct rtl8139_hwver_map { 
-	uint32_t hwverid;                /**< HW version value in the register */
-	enum rtl8139_version_id ver_id;  /**< appropriate version id */
+struct rtl8139_hwver_map {
+	uint32_t hwverid;             /**< HW version value in the register */
+	rtl8139_version_id_t ver_id;  /**< appropriate version id */
 };
 
 /** Mapping of HW version -> version ID */
 extern const struct rtl8139_hwver_map rtl8139_versions[RTL8139_VER_COUNT + 1];
-
-/** 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
+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
 
 /** 8k buffer */
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/nic/rtl8139/driver.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -39,5 +39,4 @@
 #include <io/log.h>
 #include <nic.h>
-#include <packet_client.h>
 #include <device/pci.h>
 
@@ -56,21 +55,28 @@
 /** 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)
@@ -83,5 +89,6 @@
 /** Unlock transmitter and receiver data
  *
- *  @param rtl8139  RTL8139 private data
+ * @param rtl8139 RTL8139 private data
+ *
  */
 inline static void rtl8139_unlock_all(rtl8139_t *rtl8139)
@@ -152,5 +159,5 @@
 }
 
-/** Update the mask of accepted packets in the RCR register according to
+/** Update the mask of accepted frames in the RCR register according to
  * rcr_accept_mode value in rtl8139_t
  *
@@ -170,5 +177,5 @@
 }
 
-/** Fill the mask of accepted multicast packets in the card registers
+/** Fill the mask of accepted multicast frames in the card registers
  *
  *  @param rtl8139  The rtl8139 private data
@@ -394,5 +401,5 @@
 #define rtl8139_tbuf_busy(tsd) ((pio_read_32(tsd) & TSD_OWN) == 0)
 
-/** Send packet with the hardware
+/** Send frame with the hardware
  *
  * note: the main_lock is locked when framework calls this function
@@ -412,5 +419,5 @@
 	ddf_msg(LVL_DEBUG, "Sending frame");
 
-	if (size > RTL8139_PACKET_MAX_LENGTH) {
+	if (size > RTL8139_FRAME_MAX_LENGTH) {
 		ddf_msg(LVL_ERROR, "Send frame: frame too long, %zu bytes",
 		    size);
@@ -437,5 +444,5 @@
 	fibril_mutex_unlock(&rtl8139->tx_lock);
 
-	/* Get address of the buffer descriptor and packet data */
+	/* Get address of the buffer descriptor and frame data */
 	void *tsd = rtl8139->io_port + TSD0 + tx_curr * 4;
 	void *buf_addr = rtl8139->tx_buff[tx_curr];
@@ -458,5 +465,5 @@
 	pio_write_32(tsd, tsd_value);
 	return;
-
+	
 err_busy_no_inc:
 err_size:
@@ -505,32 +512,26 @@
 }
 
-/** Create packet structure from the buffer data
+/** Create frame structure from the buffer data
  *
  * @param nic_data      NIC driver data
  * @param rx_buffer     The receiver buffer
  * @param rx_size       The buffer 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);
+ * @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);
 	if (! frame) {
-		ddf_msg(LVL_ERROR, "Can not allocate frame for received packet.");
+		ddf_msg(LVL_ERROR, "Can not allocate frame for received frame.");
 		return NULL;
 	}
 
-	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);
+	void *ret = rtl8139_memcpy_wrapped(frame->data, rx_buffer, frame_start,
+	    RxBUF_SIZE, frame_size);
 	if (ret == NULL) {
 		nic_release_frame(nic_data, frame);
@@ -568,10 +569,10 @@
 }
 
-/** Receive all packets in queue
+/** Receive all frames in queue
  *
  *  @param nic_data  The controller 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)
+ *  @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)
 {
 	rtl8139_t *rtl8139 = nic_get_specific(nic_data);
@@ -581,5 +582,5 @@
 	nic_frame_list_t *frames = nic_alloc_frame_list();
 	if (!frames)
-		ddf_msg(LVL_ERROR, "Can not allocate frame list for received packets.");
+		ddf_msg(LVL_ERROR, "Can not allocate frame list for received frames.");
 
 	void *rx_buffer = rtl8139->rx_buff_virt;
@@ -605,12 +606,12 @@
 	while (!rtl8139_hw_buffer_empty(rtl8139)) {
 		void *rx_ptr = rx_buffer + rx_offset % RxBUF_SIZE;
-		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;
+		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;
 
 		if (size == RTL8139_EARLY_SIZE) {
-			/* The packet copying is still in progress, break receiving */
+			/* The frame copying is still in progress, break receiving */
 			ddf_msg(LVL_DEBUG, "Early threshold reached, not completely coppied");
 			break;
@@ -618,7 +619,7 @@
 
 		/* Check if the header is valid, otherwise we are lost in the buffer */
-		if (size == 0 || size > RTL8139_PACKET_MAX_LENGTH) {
+		if (size == 0 || size > RTL8139_FRAME_MAX_LENGTH) {
 			ddf_msg(LVL_ERROR, "Receiver error -> receiver reset (size: %4"PRIu16", "
-			    "header 0x%4"PRIx16". Offset: %zu)", size, packet_header, 
+			    "header 0x%4"PRIx16". Offset: %zu)", size, frame_header, 
 			    rx_offset);
 			goto rx_err;
@@ -629,11 +630,11 @@
 		}
 
-		cur_read += size + RTL_PACKET_HEADER_SIZE;
+		cur_read += size + RTL_FRAME_HEADER_SIZE;
 		if (cur_read > max_read)
 			break;
 
 		if (frames) {
-			nic_frame_t *frame = rtl8139_read_packet(nic_data, rx_buffer,
-			    RxBUF_SIZE, rx_offset + RTL_PACKET_HEADER_SIZE, packet_size);
+			nic_frame_t *frame = rtl8139_read_frame(nic_data, rx_buffer,
+			    RxBUF_SIZE, rx_offset + RTL_FRAME_HEADER_SIZE, frame_size);
 
 			if (frame)
@@ -642,7 +643,7 @@
 
 		/* Update offset */
-		rx_offset = ALIGN_UP(rx_offset + size + RTL_PACKET_HEADER_SIZE, 4);
-
-		/* Write lesser value to prevent overflow into unread packet
+		rx_offset = ALIGN_UP(rx_offset + size + RTL_FRAME_HEADER_SIZE, 4);
+
+		/* Write lesser value to prevent overflow into unread frame
 		 * (the recomendation from the RealTech rtl8139 programming guide)
 		 */
@@ -727,5 +728,5 @@
 		tx_used++;
 
-		/* If the packet was sent */
+		/* If the frame was sent */
 		if (tsd_value & TSD_TOK) {
 			size_t size = REG_GET_VAL(tsd_value, TSD_SIZE);
@@ -757,9 +758,9 @@
 }
 
-/** Receive all packets from the buffer
+/** Receive all frames from the buffer
  *
  *  @param rtl8139  driver private data
  */
-static void rtl8139_receive_packets(nic_t *nic_data)
+static void rtl8139_receive_frames(nic_t *nic_data)
 {
 	assert(nic_data);
@@ -769,5 +770,5 @@
 
 	fibril_mutex_lock(&rtl8139->rx_lock);
-	nic_frame_list_t *frames = rtl8139_packet_receive(nic_data);
+	nic_frame_list_t *frames = rtl8139_frame_receive(nic_data);
 	fibril_mutex_unlock(&rtl8139->rx_lock);
 
@@ -825,5 +826,5 @@
 	}
 
-	/* Check transmittion interrupts first to allow transmit next packets
+	/* Check transmittion interrupts first to allow transmit next frames
 	 * sooner
 	 */
@@ -832,5 +833,5 @@
 	}
 	if (isr & INT_ROK) {
-		rtl8139_receive_packets(nic_data);
+		rtl8139_receive_frames(nic_data);
 	}
 	if (isr & (INT_RER | INT_RXOVW | INT_FIFOOVW)) {
@@ -933,5 +934,5 @@
 }
 
-/** Activate the device to receive and transmit packets
+/** Activate the device to receive and transmit frames
  *
  *  @param nic_data  The nic driver data
@@ -1213,15 +1214,15 @@
 		goto failed;
 
-	/* Set default packet acceptance */
+	/* Set default frame 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 packet length */
+	/* Set receiver early treshold to 8/16 of frame 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");
@@ -1288,4 +1289,6 @@
 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);
@@ -1324,8 +1327,22 @@
 	}
 
-	rc = nic_register_as_ddf_fun(nic_data, &rtl8139_dev_ops);
+	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);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed to register as DDF function - error %d", rc);
-		goto err_irq;
+		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;
 	}
 
@@ -1334,5 +1351,11 @@
 
 	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);
@@ -1477,5 +1500,5 @@
 };
 
-/** Check if pause packet operations are valid in current situation 
+/** Check if pause frame operations are valid in current situation 
  *
  *  @param rtl8139  RTL8139 private structure
@@ -1502,5 +1525,5 @@
 }
 
-/** Get current pause packet configuration
+/** Get current pause frame configuration
  *
  *  Values are filled with NIC_RESULT_NOT_AVAILABLE if the value has no sense in
@@ -1508,7 +1531,7 @@
  *
  *  @param[in]  fun         The DDF structure of the 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
+ *  @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
  *
  *  @return EOK if succeed
@@ -1540,12 +1563,12 @@
 };
 
-/** Set current pause packet configuration
+/** Set current pause frame configuration
  *
  *  @param fun            The DDF structure of the RTL8139
- *  @param allow_send     Sign if local constroller sends pause packets
- *  @param allow_receive  Sign if local constroller receives pause packets
+ *  @param allow_send     Sign if local constroller sends pause frame
+ *  @param allow_receive  Sign if local constroller receives pause frames
  *  @param time           Time to use, ignored (not supported by device)
  *
- *  @return EOK if succeed, INVAL if the pause packet has no sence
+ *  @return EOK if succeed, INVAL if the pause frame has no sence
  */
 static int rtl8139_pause_set(ddf_fun_t *fun, int allow_send, int allow_receive, 
@@ -1796,5 +1819,5 @@
 }
 
-/** Set unicast packets acceptance mode
+/** Set unicast frames acceptance mode
  *
  *  @param nic_data  The nic device to update
@@ -1854,5 +1877,5 @@
 }
 
-/** Set multicast packets acceptance mode
+/** Set multicast frames acceptance mode
  *
  *  @param nic_data  The nic device to update
@@ -1899,5 +1922,5 @@
 }
 
-/** Set broadcast packets acceptance mode
+/** Set broadcast frames acceptance mode
  *
  *  @param nic_data  The nic device to update
@@ -1929,5 +1952,5 @@
 }
 
-/** Get state of acceptance of weird packets
+/** Get state of acceptance of weird frames
  *
  *  @param[in]  device  The device to check
@@ -1951,5 +1974,5 @@
 };
 
-/** Set acceptance of weird packets
+/** Set acceptance of weird frames
  *
  *  @param device  The device to update
@@ -2127,5 +2150,5 @@
 }
 
-/** Force receiving all packets in the receive buffer
+/** Force receiving all frames in the receive buffer
  *
  *  @param device  The device to receive
Index: uspace/drv/nic/rtl8139/driver.h
===================================================================
--- uspace/drv/nic/rtl8139/driver.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/nic/rtl8139/driver.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -30,36 +30,40 @@
 #define RTL8139_DRIVER_H_
 
+#include <sys/types.h>
+#include <stdint.h>
 #include "defs.h"
 #include "general.h"
-#include <sys/types.h>
-#include <stdint.h>
 
 /** The driver name */
-#define NAME "rtl8139"
+#define NAME  "rtl8139"
+
 /** Transmittion buffers count */
-#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
+#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
 
 /** Size of the CRC after the received frame in the receiver buffer */
-#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
+#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
 
 /** 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 */
@@ -112,5 +116,5 @@
 	size_t tx_used;
 
-	/** Buffer for receiving packets */
+	/** Buffer for receiving frames */
 	void *rx_buff_phys;
 	void *rx_buff_virt;
@@ -134,7 +138,6 @@
 
 	/** Version of RT8139 controller */
-	enum rtl8139_version_id hw_version;
+	rtl8139_version_id_t hw_version;
 } rtl8139_t;
-
 
 /* ***** Pointers casting - for both amd64 and ia32 ***** */
@@ -160,6 +163,4 @@
  */
 #define IOADDR_TO_PTR(ioaddr) ((void*)((size_t)(ioaddr)))
-
-
 
 /* ***** Bit operation macros ***** */
@@ -177,5 +178,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))))
 
@@ -237,4 +238,3 @@
 	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/drv/nic/rtl8139/general.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -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>
 
-extern void* rtl8139_memcpy_wrapped(void *dest, const void *src_buf,
-    size_t src_offset, size_t src_size, size_t data_size);
-
+/** Number of microseconds in second */
+#define RTL8139_USEC_IN_SEC  1000000
 
 /** Structure for HW timer control */
-typedef struct rtl8139_timer_act {
+typedef struct {
 	/** 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;
 
-/** 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);
-
+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 *);
 
 #endif
Index: uspace/lib/c/generic/device/nic.c
===================================================================
--- uspace/lib/c/generic/device/nic.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/c/generic/device/nic.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -73,8 +73,7 @@
 }
 
-/** Connect the driver to the NET and NIL services
- *
- * @param[in] dev_sess
- * @param[in] nil_service Service identifier for the NIL service
+/** Create callback connection from NIC service
+ *
+ * @param[in] dev_sess
  * @param[in] device_id
  *
@@ -82,13 +81,24 @@
  *
  */
-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;
+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;
 }
 
@@ -335,5 +345,5 @@
  * it can never force the NIC to advertise unsupported modes.
  *
- * The allowed modes are defined in "net/eth_phys.h" in the C library.
+ * The allowed modes are defined in "nic/eth_phys.h" in the C library.
  *
  * @param[in] dev_sess
@@ -372,5 +382,5 @@
 /** Probe current state of auto-negotiation.
  *
- * Modes are defined in the "net/eth_phys.h" in the C library.
+ * Modes are defined in the "nic/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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/c/generic/loc.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -47,4 +47,5 @@
 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;
@@ -54,10 +55,6 @@
 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;
@@ -69,21 +66,19 @@
 		}
 		
-		int retval;
-		
 		switch (IPC_GET_IMETHOD(call)) {
 		case LOC_EVENT_CAT_CHANGE:
 			fibril_mutex_lock(&loc_callback_mutex);
-			cb_fun = cat_change_cb;
-			if (cb_fun != NULL) {
+			loc_cat_change_cb_t cb_fun = cat_change_cb;
+			fibril_mutex_unlock(&loc_callback_mutex);
+			
+			async_answer_0(callid, EOK);
+			
+			if (cb_fun != NULL)
 				(*cb_fun)();
-			}
-			fibril_mutex_unlock(&loc_callback_mutex);
-			retval = 0;
+			
 			break;
 		default:
-			retval = ENOTSUP;
+			async_answer_0(callid, ENOTSUP);
 		}
-		
-		async_answer_0(callid, retval);
 	}
 }
@@ -101,36 +96,34 @@
 }
 
+/** 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) {
-		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+		async_exch_t *exch =
+		    loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
 		
 		ipc_call_t answer;
 		aid_t req = async_send_0(exch, LOC_CALLBACK_CREATE, &answer);
-		async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);
+		int rc = async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);
 		loc_exchange_end(exch);
 		
+		if (rc != EOK)
+			return rc;
+		
+		sysarg_t retval;
 		async_wait_for(req, &retval);
-		if (rc != EOK)
-			goto done;
-		
-		if (retval != EOK) {
-			rc = retval;
-			goto done;
-		}
+		if (retval != EOK)
+			return retval;
 		
 		loc_callback_created = true;
 	}
 	
-	rc = EOK;
-done:
-	fibril_mutex_unlock(&loc_callback_mutex);
-	return rc;
+	return EOK;
 }
 
@@ -795,22 +788,18 @@
     sysarg_t **data, size_t *count)
 {
-	service_id_t *ids;
-	size_t act_size;
-	size_t alloc_size;
-	int rc;
-
 	*data = NULL;
-	act_size = 0;	/* silence warning */
-
-	rc = loc_category_get_ids_once(method, arg1, NULL, 0,
+	*count = 0;
+	
+	size_t act_size = 0;
+	int rc = loc_category_get_ids_once(method, arg1, NULL, 0,
 	    &act_size);
 	if (rc != EOK)
 		return rc;
-
-	alloc_size = act_size;
-	ids = malloc(alloc_size);
+	
+	size_t alloc_size = act_size;
+	service_id_t *ids = malloc(alloc_size);
 	if (ids == NULL)
 		return ENOMEM;
-
+	
 	while (true) {
 		rc = loc_category_get_ids_once(method, arg1, ids, alloc_size,
@@ -818,16 +807,14 @@
 		if (rc != EOK)
 			return rc;
-
+		
 		if (act_size <= alloc_size)
 			break;
-
-		alloc_size *= 2;
-		free(ids);
-
-		ids = malloc(alloc_size);
+		
+		alloc_size = act_size;
+		ids = realloc(ids, alloc_size);
 		if (ids == NULL)
 			return ENOMEM;
 	}
-
+	
 	*count = act_size / sizeof(category_id_t);
 	*data = ids;
@@ -867,8 +854,13 @@
 int loc_register_cat_change_cb(loc_cat_change_cb_t cb_fun)
 {
-	if (loc_callback_create() != EOK)
+	fibril_mutex_lock(&loc_callback_mutex);
+	if (loc_callback_create() != EOK) {
+		fibril_mutex_unlock(&loc_callback_mutex);
 		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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/c/include/device/nic.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -37,11 +37,10 @@
 
 #include <async.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <ipc/services.h>
+#include <nic/nic.h>
+#include <ipc/common.h>
 
 typedef enum {
 	NIC_SEND_MESSAGE = 0,
-	NIC_CONNECT_TO_NIL,
+	NIC_CALLBACK_CREATE,
 	NIC_GET_STATE,
 	NIC_SET_STATE,
@@ -85,6 +84,12 @@
 } 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_connect_to_nil(async_sess_t *, services_t, nic_device_id_t);
+extern int nic_callback_create(async_sess_t *, async_client_conn_t, void *);
 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/c/include/ipc/devman.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -146,5 +146,4 @@
 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/c/include/ipc/net.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -305,5 +305,5 @@
  *
  */
-#define IPC_GET_DEVICE_HANDLE(call)  ((devman_handle_t) IPC_GET_ARG2(call))
+#define IPC_GET_DEVICE_HANDLE(call)  ((service_id_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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/c/include/ipc/net_net.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -54,7 +54,5 @@
 	NET_NET_GET_DEVICES_COUNT,
 	/** Return names and device IDs of all devices */
-	NET_NET_GET_DEVICES,
-	/** Notify the networking service about a ready device */
-	NET_NET_DRIVER_READY
+	NET_NET_GET_DEVICES
 } net_messages;
 
Index: uspace/lib/c/include/ipc/nil.h
===================================================================
--- uspace/lib/c/include/ipc/nil.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/c/include/ipc/nil.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -46,12 +46,4 @@
 	 */
 	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()
@@ -69,9 +61,5 @@
 	 * @see nil_get_broadcast_addr()
 	 */
-	NET_NIL_BROADCAST_ADDR,
-	/** Device has changed address
-	 * @see nil_addr_changed_msg()
-	 */
-	NET_NIL_ADDR_CHANGED
+	NET_NIL_BROADCAST_ADDR
 } nil_messages;
 
Index: uspace/lib/c/include/net/device.h
===================================================================
--- uspace/lib/c/include/net/device.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/c/include/net/device.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -1,5 +1,4 @@
 /*
  * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
  * All rights reserved.
  *
@@ -33,31 +32,12 @@
 
 /** @file
- * Device identifier, state and usage statistics.
+ * Network device.
  */
 
-#ifndef LIBC_DEVICE_ID_TYPE_H_
-#define LIBC_DEVICE_ID_TYPE_H_
+#ifndef LIBC_NET_DEVICE_H_
+#define LIBC_NET_DEVICE_H_
 
 #include <adt/int_map.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)
+#include <nic/nic.h>
 
 /** Device identifier to generic type map declaration. */
@@ -67,419 +47,9 @@
 #define DEVICE_MAP_IMPLEMENT  INT_MAP_IMPLEMENT
 
-/** Max length of any hw nic address (currently only eth) */
-#define NIC_MAX_ADDRESS_LENGTH  16
+/** Device identifier type. */
+typedef int nic_device_id_t;
 
 /** 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;
-
-/**
- * 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: pace/lib/c/include/net/eth_phys.h
===================================================================
--- uspace/lib/c/include/net/eth_phys.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ 	(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_NET_ETH_PHYS_H_
-#define LIBC_NET_ETH_PHYS_H_
-
-#include <sys/types.h>
-
-/*****************************************************/
-/* Definitions of possible supported physical layers */
-/*****************************************************/
-
-/* Ethernet physical layers */
-#define ETH_OLD          0
-#define ETH_10M          1
-#define ETH_100M         2
-#define ETH_1000M        3
-#define ETH_10G          4
-#define ETH_40G_100G     5
-/* 6, 7 reserved for future use */
-#define ETH_PHYS_LAYERS  8
-
-/* < 10Mbs ethernets */
-#define ETH_EXPERIMENTAL     0x0001
-#define ETH_1BASE5           0x0002
-/* 10Mbs ethernets */
-#define ETH_10BASE5          0x0001
-#define ETH_10BASE2          0x0002
-#define ETH_10BROAD36        0x0004
-#define ETH_STARLAN_10       0x0008
-#define ETH_LATTISNET        0x0010
-#define ETH_10BASE_T         0x0020
-#define ETH_FOIRL            0x0040
-#define ETH_10BASE_FL        0x0080
-#define ETH_10BASE_FB        0x0100
-#define ETH_10BASE_FP        0x0200
-/* 100Mbs (fast) ethernets */
-#define ETH_100BASE_TX       0x0001
-#define ETH_100BASE_T4       0x0002
-#define ETH_100BASE_T2       0x0004
-#define ETH_100BASE_FX       0x0008
-#define ETH_100BASE_SX       0x0010
-#define ETH_100BASE_BX10     0x0020
-#define ETH_100BASE_LX10     0x0040
-#define ETH_100BASE_VG       0x0080
-/* 1000Mbs (gigabit) ethernets */
-#define ETH_1000BASE_T       0x0001
-#define ETH_1000BASE_TX      0x0002
-#define ETH_1000BASE_SX      0x0004
-#define ETH_1000BASE_LX      0x0008
-#define ETH_1000BASE_LH      0x0010
-#define ETH_1000BASE_CX      0x0020
-#define ETH_1000BASE_BX10    0x0040
-#define ETH_1000BASE_LX10    0x0080
-#define ETH_1000BASE_PX10_D  0x0100
-#define ETH_1000BASE_PX10_U  0x0200
-#define ETH_1000BASE_PX20_D  0x0400
-#define ETH_1000BASE_PX20_U  0x0800
-#define ETH_1000BASE_ZX      0x1000
-#define ETH_1000BASE_KX      0x2000
-/* 10Gbs ethernets */
-#define ETH_10GBASE_SR       0x0001
-#define ETH_10GBASE_LX4      0x0002
-#define ETH_10GBASE_LR       0x0004
-#define ETH_10GBASE_ER       0x0008
-#define ETH_10GBASE_SW       0x0010
-#define ETH_10GBASE_LW       0x0020
-#define ETH_10GBASE_EW       0x0040
-#define ETH_10GBASE_CX4      0x0080
-#define ETH_10GBASE_T        0x0100
-#define ETH_10GBASE_LRM      0x0200
-#define ETH_10GBASE_KX4      0x0400
-#define ETH_10GBASE_KR       0x0800
-/* 40Gbs and 100Gbs ethernets */
-#define ETH_40GBASE_SR4      0x0001
-#define ETH_40GBASE_LR4      0x0002
-#define ETH_40GBASE_CR4      0x0004
-#define ETH_40GBASE_KR4      0x0008
-#define ETH_100GBASE_SR10    0x0010
-#define ETH_100GBASE_LR4     0x0020
-#define ETH_100GBASE_ER4     0x0040
-#define ETH_100GBASE_CR10    0x0080
-
-/******************************************/
-/* Auto-negotiation advertisement options */
-/******************************************/
-
-#define ETH_AUTONEG_10BASE_T_HALF    UINT32_C(0x00000001)
-#define ETH_AUTONEG_10BASE_T_FULL    UINT32_C(0x00000002)
-#define ETH_AUTONEG_100BASE_TX_HALF  UINT32_C(0x00000004)
-#define ETH_AUTONEG_100BASE_T4_HALF  UINT32_C(0x00000008)
-#define ETH_AUTONEG_100BASE_T2_HALF  UINT32_C(0x00000010)
-#define ETH_AUTONEG_100BASE_TX_FULL  UINT32_C(0x00000020)
-#define ETH_AUTONEG_100BASE_T2_FULL  UINT32_C(0x00000040)
-#define ETH_AUTONEG_1000BASE_T_HALF  UINT32_C(0x00000080)
-#define ETH_AUTONEG_1000BASE_T_FULL  UINT32_C(0x00000100)
-
-/** Symetric pause packet (802.3x standard) */
-#define ETH_AUTONEG_PAUSE_SYMETRIC   UINT32_C(0x10000000)
-/** Asymetric pause packet (802.3z standard, gigabit ethernet) */
-#define ETH_AUTONEG_PAUSE_ASYMETRIC  UINT32_C(0x20000000)
-
-#define ETH_AUTONEG_MODE_MASK      UINT32_C(0x0FFFFFFF)
-#define ETH_AUTONEG_FEATURES_MASK  UINT32_C(~(ETH_AUTONEG_MODE_MASK))
-
-#define ETH_AUTONEG_MODES  9
-
-struct eth_autoneg_map {
-	uint32_t value;
-	const char *name;
-};
-
-extern const char *ethernet_names[8][17];
-extern const struct eth_autoneg_map ethernet_autoneg_mapping[ETH_AUTONEG_MODES];
-
-#endif
Index: uspace/lib/c/include/nic/eth_phys.h
===================================================================
--- uspace/lib/c/include/nic/eth_phys.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
+++ uspace/lib/c/include/nic/eth_phys.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -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_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: uspace/lib/c/include/nic/nic.h
===================================================================
--- uspace/lib/c/include/nic/nic.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
+++ uspace/lib/c/include/nic/nic.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -0,0 +1,475 @@
+/*
+ * 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/drv/Makefile	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -35,4 +35,5 @@
 	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/drv/generic/driver.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -70,18 +70,4 @@
 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 *);
@@ -93,132 +79,4 @@
 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)
 {
@@ -301,14 +159,4 @@
 	
 	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);
 }
 
@@ -460,8 +308,4 @@
 		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:
@@ -751,5 +595,5 @@
 
 /** Allocate driver-specific device data. */
-extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)
+void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)
 {
 	void *data;
@@ -813,5 +657,5 @@
 
 /** Allocate driver-specific function data. */
-extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)
+void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)
 {
 	void *data;
@@ -1006,9 +850,6 @@
 	driver = drv;
 	
-	/* Initialize the list of interrupt contexts. */
-	init_interrupt_context_list(&interrupt_contexts);
-	
-	/* Set generic interrupt handler. */
-	async_set_interrupt_received(driver_irq_handler);
+	/* Initialize interrupt module */
+	interrupt_init();
 	
 	/*
Index: uspace/lib/drv/generic/interrupt.c
===================================================================
--- uspace/lib/drv/generic/interrupt.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
+++ uspace/lib/drv/generic/interrupt.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -0,0 +1,213 @@
+/*
+ * 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/drv/generic/remote_nic.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -63,14 +63,11 @@
 }
 
-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);
+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);
 	async_answer_0(callid, rc);
 }
@@ -1203,5 +1200,5 @@
 static remote_iface_func_ptr_t remote_nic_iface_ops[] = {
 	&remote_nic_send_frame,
-	&remote_nic_connect_to_nil,
+	&remote_nic_callback_create,
 	&remote_nic_get_state,
 	&remote_nic_set_state,
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/drv/include/ddf/driver.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -145,13 +145,4 @@
 	/** 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/drv/include/ddf/interrupt.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -64,16 +64,5 @@
 } interrupt_context_list_t;
 
-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 void interrupt_init(void);
 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/drv/include/ops/nic.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -38,5 +38,5 @@
 
 #include <ipc/services.h>
-#include <net/device.h>
+#include <nic/nic.h>
 #include <sys/time.h>
 
@@ -46,5 +46,5 @@
 	/** Mandatory methods */
 	int (*send_frame)(ddf_fun_t *, void *, size_t);
-	int (*connect_to_nil)(ddf_fun_t *, services_t, nic_device_id_t);
+	int (*callback_create)(ddf_fun_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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -27,8 +27,10 @@
  * 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/net/generic/net_checksum.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -45,7 +45,4 @@
 #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.
  *
@@ -224,39 +221,4 @@
 }
 
-/** 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/net/generic/net_remote.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -167,13 +167,4 @@
 }
 
-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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/net/include/net_checksum.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -67,5 +67,4 @@
 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/net/include/net_interface.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -52,5 +52,4 @@
 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/net/include/nil_remote.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -34,4 +34,5 @@
 #define __NET_NIL_REMOTE_H__
 
+#include <ipc/loc.h>
 #include <net/device.h>
 #include <net/packet.h>
@@ -39,4 +40,5 @@
 #include <generic.h>
 #include <async.h>
+#include <sys/types.h>
 
 #define nil_bind_service(service, device_id, me, receiver) \
@@ -60,8 +62,4 @@
 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/net/nil/nil_remote.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -36,4 +36,5 @@
  */
 
+#include <ipc/loc.h>
 #include <nil_remote.h>
 #include <generic.h>
@@ -43,75 +44,10 @@
 #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,
-    devman_handle_t handle, size_t mtu)
+    service_id_t sid, size_t mtu)
 {
 	async_exch_t *exch = async_exchange_begin(sess);
 	int rc = async_req_3_0(exch, NET_NIL_DEVICE, (sysarg_t) device_id,
-	    (sysarg_t) handle, (sysarg_t) mtu);
+	    (sysarg_t) sid, (sysarg_t) mtu);
 	async_exchange_end(exch);
 	return rc;
Index: uspace/lib/nic/Makefile
===================================================================
--- uspace/lib/nic/Makefile	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/nic/Makefile	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -29,9 +29,9 @@
 USPACE_PREFIX = ../..
 LIBRARY = libnic
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS += -DLIBNIC_INTERNAL -Iinclude -I$(LIBDRV_PREFIX)/include -I$(LIBNET_PREFIX)/include
+EXTRA_CFLAGS += -DLIBNIC_INTERNAL -Iinclude -I$(LIBDRV_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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/nic/include/nic.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -42,6 +42,7 @@
 #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;
@@ -61,9 +62,10 @@
 
 /**
- * Simple structure for sending the allocated frames (packets) in a list.
+ * Simple structure for sending lists of frames.
  */
 typedef struct {
 	link_t link;
-	packet_t *packet;
+	void *data;
+	size_t size;
 } nic_frame_t;
 
@@ -71,6 +73,6 @@
 
 /**
- * Handler for writing packet data to the NIC device.
- * The function is responsible for releasing the packet.
+ * Handler for writing frame data to the NIC device.
+ * The function is responsible for releasing the frame.
  * It does not return anything, if some error is detected the function just
  * silently fails (logging on debug level is suggested).
@@ -158,5 +160,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
- * 					packets' specifications was reached).
+ * 					frames' specifications was reached).
  * @return ELIMIT	If this filter must implemented in HW but currently the
  * 					limit of these HW filters was reached.
@@ -204,5 +206,4 @@
 /* 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 *);
@@ -219,10 +220,8 @@
 	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 *);
@@ -233,6 +232,5 @@
 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_packet(nic_t *, packet_t *);
-extern void nic_received_noneth_packet(nic_t *, packet_t *);
+extern void nic_received_noneth_frame(nic_t *, void *, size_t);
 extern void nic_received_frame(nic_t *, nic_frame_t *);
 extern void nic_received_frame_list(nic_t *, nic_frame_list_t *);
@@ -248,7 +246,5 @@
 extern void nic_report_collisions(nic_t *, unsigned);
 
-/* 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 *);
+/* Frame / frame list allocation and deallocation */
 extern nic_frame_t *nic_alloc_frame(nic_t *, size_t);
 extern nic_frame_list_t *nic_alloc_frame_list(void);
@@ -275,8 +271,4 @@
 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/nic/include/nic_driver.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -44,5 +44,5 @@
 
 #include <fibril_synch.h>
-#include <net/device.h>
+#include <nic/nic.h>
 #include <async.h>
 
@@ -50,6 +50,4 @@
 #include "nic_rx_control.h"
 #include "nic_wol_virtues.h"
-
-#define DEVICE_CATEGORY_NIC "nic"
 
 struct sw_poll_info {
@@ -72,6 +70,4 @@
 	 */
 	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;
@@ -82,8 +78,6 @@
 	/** Device's default MAC address (assigned the first time, used in STOP) */
 	nic_address_t default_mac;
-	/** Session to SERVICE_NETWORKING */
-	async_sess_t *net_session;
-	/** Session to SERVICE_ETHERNET or SERVICE_NILDUMMY */
-	async_sess_t *nil_session;
+	/** Client callback session */
+	async_sess_t *client_session;
 	/** Phone to APIC or i8259 */
 	async_sess_t *irc_session;
Index: uspace/lib/nic/include/nic_ev.h
===================================================================
--- uspace/lib/nic/include/nic_ev.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
+++ uspace/lib/nic/include/nic_ev.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -0,0 +1,52 @@
+/*
+ * 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/nic/include/nic_impl.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -40,7 +40,6 @@
 
 #include <assert.h>
-#include <net/device.h>
+#include <nic/nic.h>
 #include <ddf/driver.h>
-#include <nil_remote.h>
 
 /* Inclusion of this file is not prohibited, because drivers could want to
@@ -49,6 +48,5 @@
 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_connect_to_nil_impl(ddf_fun_t *dev_fun, services_t nil_service,
-	int device_id);
+extern int nic_callback_create_impl(ddf_fun_t *dev_fun);
 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/nic/include/nic_rx_control.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -45,6 +45,5 @@
 #include <adt/hash_table.h>
 #include <fibril_synch.h>
-#include <net/device.h>
-#include <net/packet_header.h>
+#include <nic/nic.h>
 
 #include "nic_addr_db.h"
@@ -120,5 +119,5 @@
 	const nic_address_t *prev_addr, const nic_address_t *curr_addr);
 extern int nic_rxc_check(const nic_rxc_t *rxc,
-	const packet_t *packet, nic_frame_type_t *frame_type);
+	const void *data, size_t size, 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/nic/include/nic_wol_virtues.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -43,5 +43,5 @@
 #endif
 
-#include <net/device.h>
+#include <nic/nic.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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/nic/src/nic_driver.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -49,12 +49,9 @@
 #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"
 
@@ -64,5 +61,5 @@
 
 /**
- * Initializes libraries required for NIC framework - logger, packet manager
+ * Initializes libraries required for NIC framework - logger
  *
  * @param name	Name of the device/driver (used in logging)
@@ -79,6 +76,5 @@
 	snprintf(buffer, 256, "drv/" DEVICE_CATEGORY_NIC "/%s", name);
 	
-	/* Initialize packet manager */
-	return pm_init();
+	return EOK;
 }
 
@@ -93,9 +89,4 @@
     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)
@@ -116,6 +107,6 @@
 		if (!iface->send_frame)
 			iface->send_frame = nic_send_frame_impl;
-		if (!iface->connect_to_nil)
-			iface->connect_to_nil = nic_connect_to_nil_impl;
+		if (!iface->callback_create)
+			iface->callback_create = nic_callback_create_impl;
 		if (!iface->get_address)
 			iface->get_address = nic_get_address_impl;
@@ -162,5 +153,5 @@
 
 /**
- * Setup write packet handler. This MUST be called in the add_device handler
+ * Setup send frame 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
@@ -270,29 +261,11 @@
 }
 
-/**
- * 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
+/** Allocate frame
  *
  *  @param nic_data 	The NIC driver data
- *  @param packet_size	Size of packet
- *  @param offload_size	Size of packet offload
+ *  @param size	        Frame size in bytes
  *  @return pointer to allocated frame if success, NULL otherwise
  */
-nic_frame_t *nic_alloc_frame(nic_t *nic_data, size_t packet_size)
+nic_frame_t *nic_alloc_frame(nic_t *nic_data, size_t size)
 {
 	nic_frame_t *frame;
@@ -313,11 +286,11 @@
 	}
 
-	packet_t *packet = nic_alloc_packet(nic_data, packet_size);
-	if (!packet) {
+	frame->data = malloc(size);
+	if (frame->data == NULL) {
 		free(frame);
 		return NULL;
 	}
 
-	frame->packet = packet;
+	frame->size = size;
 	return frame;
 }
@@ -332,7 +305,11 @@
 	if (!frame)
 		return;
-	if (frame->packet != NULL) {
-		nic_release_packet(nic_data, frame->packet);
-	}
+
+	if (frame->data != NULL) {
+		free(frame->data);
+		frame->data = NULL;
+		frame->size = 0;
+	}
+
 	fibril_mutex_lock(&nic_globals.lock);
 	if (nic_globals.frame_cache_size >= NIC_GLOBALS_MAX_CACHE_SIZE) {
@@ -447,5 +424,5 @@
 
 /**
- * Connect to the NET and IRQ services. This function should be called only from
+ * Connect to IRC service. This function should be called only from
  * the add_device handler, thus no locking is required.
  *
@@ -454,14 +431,8 @@
  * @return EOK		If connection was successful.
  * @return EINVAL	If the IRC service cannot be determined.
- * @return EREFUSED	If NET or IRC service cannot be connected.
+ * @return EREFUSED	If 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;
@@ -480,26 +451,4 @@
 	
 	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);
 }
 
@@ -546,7 +495,7 @@
 	
 	/* Notify NIL layer (and uppper) if bound - not in add_device */
-	if (nic_data->nil_session != NULL) {
-		int rc = nil_addr_changed_msg(nic_data->nil_session,
-		    nic_data->device_id, address);
+	if (nic_data->client_session != NULL) {
+		int rc = nic_ev_addr_changed(nic_data->client_session,
+		    address);
 		if (rc != EOK) {
 			fibril_rwlock_write_unlock(&nic_data->main_lock);
@@ -604,5 +553,5 @@
 
 /**
- * The busy flag can be set to 1 only in the write_packet handler, to 0 it can
+ * The busy flag can be set to 1 only in the send_frame handler, to 0 it can
  * be set anywhere.
  *
@@ -613,5 +562,5 @@
 {
 	/*
-	 * When the function is called in write_packet handler the main lock is
+	 * When the function is called in send_frame handler the main lock is
 	 * locked so no race can happen.
 	 * Otherwise, when it is unexpectedly set to 0 (even with main lock held
@@ -622,42 +571,26 @@
 
 /**
- * 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
+ * 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
  */
 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 write_packet handler (with locked main lock) */
-	packet_id_t pid = packet_get_id(packet);
-	
+	 * 		 calls it inside send_frame handler (with locked main lock) */
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	nic_frame_type_t frame_type;
-	int check = nic_rxc_check(&nic_data->rx_control, packet, &frame_type);
+	int check = nic_rxc_check(&nic_data->rx_control, frame->data,
+	    frame->size, &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 += packet_get_data_length(packet);
+		nic_data->stats.receive_bytes += frame->size;
 		switch (frame_type) {
 		case NIC_FRAME_MULTICAST:
@@ -671,5 +604,6 @@
 		}
 		fibril_rwlock_write_unlock(&nic_data->stats_lock);
-		nil_received_msg(nic_data->nil_session, nic_data->device_id, pid);
+		nic_ev_received(nic_data->client_session, frame->data,
+		    frame->size);
 	} else {
 		switch (frame_type) {
@@ -685,31 +619,31 @@
 		}
 		fibril_rwlock_write_unlock(&nic_data->stats_lock);
-		nic_release_packet(nic_data, packet);
-	}
+	}
+	nic_release_frame(nic_data, frame);
 }
 
 /**
  * This function is to be used only in the loopback driver. It's workaround
- * for the situation when the packet does not contain ethernet address.
+ * for the situation when the frame does not contain ethernet address.
  * The filtering is therefore not applied here.
  *
  * @param nic_data
- * @param packet
- */
-void nic_received_noneth_packet(nic_t *nic_data, packet_t *packet)
+ * @param data		Frame data
+ * @param size		Frame size in bytes
+ */
+void nic_received_noneth_frame(nic_t *nic_data, void *data, size_t size)
 {
 	fibril_rwlock_write_lock(&nic_data->stats_lock);
 	nic_data->stats.receive_packets++;
-	nic_data->stats.receive_bytes += packet_get_data_length(packet);
+	nic_data->stats.receive_bytes += size;
 	fibril_rwlock_write_unlock(&nic_data->stats_lock);
 	
-	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
+	nic_ev_received(nic_data->client_session, data, size);
+}
+
+/**
+ * Some NICs can receive multiple frames during single interrupt. These can
  * send them in whole list of frames (actually nic_frame_t structures), then
- * the list is deallocated and each packet is passed to the
+ * the list is deallocated and each frame is passed to the
  * nic_received_packet function.
  *
@@ -726,7 +660,5 @@
 
 		list_remove(&frame->link);
-		nic_received_packet(nic_data, frame->packet);
-		frame->packet = NULL;
-		nic_release_frame(nic_data, frame);
+		nic_received_frame(nic_data, frame);
 	}
 	nic_driver_release_frame_list(frames);
@@ -758,8 +690,6 @@
 	nic_data->dev = NULL;
 	nic_data->fun = NULL;
-	nic_data->device_id = NIC_DEVICE_INVALID_ID;
 	nic_data->state = NIC_STATE_STOPPED;
-	nic_data->net_session = NULL;
-	nic_data->nil_session = NULL;
+	nic_data->client_session = NULL;
 	nic_data->irc_session = NULL;
 	nic_data->poll_mode = NIC_POLL_IMMEDIATE;
@@ -815,10 +745,6 @@
  */
 static void nic_destroy(nic_t *nic_data) {
-	if (nic_data->net_session != NULL) {
-		async_hangup(nic_data->net_session);
-	}
-
-	if (nic_data->nil_session != NULL) {
-		async_hangup(nic_data->nil_session);
+	if (nic_data->client_session != NULL) {
+		async_hangup(nic_data->client_session);
 	}
 
@@ -846,41 +772,4 @@
 
 /**
- * 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
@@ -1097,4 +986,13 @@
 {
 	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;
 }
 
@@ -1329,23 +1227,4 @@
 }
 
-/** 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: uspace/lib/nic/src/nic_ev.c
===================================================================
--- uspace/lib/nic/src/nic_ev.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
+++ uspace/lib/nic/src/nic_ev.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -0,0 +1,97 @@
+/*
+ * 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/nic/src/nic_impl.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -36,8 +36,10 @@
  */
 
+#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"
 
@@ -85,6 +87,5 @@
 	}
 	if (state == NIC_STATE_ACTIVE) {
-		if (nic_data->nil_session == NULL || nic_data->net_session == NULL
-		    || nic_data->device_id < 0) {
+		if (nic_data->client_session == NULL) {
 			fibril_rwlock_write_unlock(&nic_data->main_lock);
 			return EINVAL;
@@ -116,6 +117,6 @@
 	if (state == NIC_STATE_STOPPED) {
 		/* Notify upper layers that we are reseting the MAC */
-		int rc = nil_addr_changed_msg(nic_data->nil_session,
-			nic_data->device_id, &nic_data->default_mac);
+		int rc = nic_ev_addr_changed(nic_data->client_session,
+			&nic_data->default_mac);
 		nic_data->poll_mode = nic_data->default_poll_mode;
 		memcpy(&nic_data->poll_period, &nic_data->default_poll_period,
@@ -149,5 +150,5 @@
 	nic_data->state = state;
 
-	nil_device_state_msg(nic_data->nil_session, nic_data->device_id, state);
+	nic_ev_device_state(nic_data->client_session, state);
 
 	fibril_rwlock_write_unlock(&nic_data->main_lock);
@@ -182,31 +183,24 @@
 
 /**
- * Default implementation of the connect_to_nil method.
- * Connects the driver to the NIL service.
+ * Default implementation of the connect_client method.
+ * Creates callback connection to the client.
  *
  * @param	fun
- * @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);
+ *
+ * @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);
 	
-	nic_data->device_id = device_id;
+	nic->client_session = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (nic->client_session == NULL) {
+		fibril_rwlock_write_unlock(&nic->main_lock);
+		return ENOMEM;
+	}
 	
-	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;
+	fibril_rwlock_write_unlock(&nic->main_lock);
+	return EOK;
 }
 
@@ -805,16 +799,4 @@
 }
 
-/** 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/nic/src/nic_rx_control.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -40,7 +40,6 @@
 #include <bool.h>
 #include <errno.h>
-#include <net/device.h>
-#include <net_checksum.h>
-#include <packet_client.h>
+#include <mem.h>
+#include <nic/nic.h>
 #include "nic_rx_control.h"
 
@@ -392,14 +391,17 @@
  *
  * @param rxc
- * @param packet	The probed frame
+ * @param frame	    The probed frame
  *
  * @return True if the frame passes, false if it does not
  */
-int nic_rxc_check(const nic_rxc_t *rxc, const packet_t *packet,
+int nic_rxc_check(const nic_rxc_t *rxc, const void *data, size_t size,
 	nic_frame_type_t *frame_type)
 {
 	assert(frame_type != NULL);
-	uint8_t *dest_addr = (uint8_t *) packet + packet->data_start;
+	uint8_t *dest_addr = (uint8_t *) data;
 	uint8_t *src_addr = dest_addr + ETH_ADDR;
+
+	if (size < 2 * ETH_ADDR)
+		return false;
 
 	if (dest_addr[0] & 1) {
@@ -448,5 +450,5 @@
 	if (!rxc->vlan_exact && rxc->vlan_mask != NULL) {
 		vlan_header_t *vlan_header = (vlan_header_t *)
-			((uint8_t *) packet + packet->data_start + 2 * ETH_ADDR);
+			((uint8_t *) data + 2 * ETH_ADDR);
 		if (vlan_header->tpid_upper == VLAN_TPID_UPPER &&
 			vlan_header->tpid_lower == VLAN_TPID_LOWER) {
@@ -484,4 +486,43 @@
 		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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/nic/src/nic_wol_virtues.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -38,4 +38,5 @@
 #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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/lib/posix/ctype.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -112,5 +112,5 @@
  * @return Non-zero if character match the definition, zero otherwise.
  */
-extern int posix_isascii(int c)
+int posix_isascii(int c)
 {
 	return c >= 0 && c < 128;
@@ -123,5 +123,5 @@
  * @return Coverted character.
  */
-extern int posix_toascii(int c)
+int posix_toascii(int c)
 {
 	return c & 0x7F;
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/devman/devman.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -794,7 +794,4 @@
 	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:
@@ -803,4 +800,5 @@
 	default:
 		dev->state = DEVICE_INVALID;
+		break;
 	}
 	
Index: uspace/srv/hid/input/generic/input.c
===================================================================
--- uspace/srv/hid/input/generic/input.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/hid/input/generic/input.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -39,4 +39,5 @@
 #include <adt/list.h>
 #include <bool.h>
+#include <fibril_synch.h>
 #include <ipc/services.h>
 #include <ipc/input.h>
@@ -83,4 +84,6 @@
 async_sess_t *irc_sess = NULL;
 
+static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
+
 void kbd_push_data(kbd_dev_t *kdev, sysarg_t data)
 {
@@ -593,12 +596,20 @@
 	int rc;
 	
+	fibril_mutex_lock(&discovery_lock);
+	
 	rc = dev_check_new_kbdevs();
-	if (rc != EOK)
+	if (rc != EOK) {
+		fibril_mutex_unlock(&discovery_lock);
 		return rc;
+	}
 	
 	rc = dev_check_new_mousedevs();
-	if (rc != EOK)
+	if (rc != EOK) {
+		fibril_mutex_unlock(&discovery_lock);
 		return rc;
-
+	}
+	
+	fibril_mutex_unlock(&discovery_lock);
+	
 	return EOK;
 }
Index: pace/srv/hid/input/include/sun.h
===================================================================
--- uspace/srv/hid/input/include/sun.h	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * 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: pace/srv/hid/input/port/dummy.c
===================================================================
--- uspace/srv/hid/input/port/dummy.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*
- * 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: pace/srv/hid/input/port/sgcn.c
===================================================================
--- uspace/srv/hid/input/port/sgcn.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ 	(revision )
@@ -1,188 +1,0 @@
-/*
- * 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: pace/srv/hid/input/port/sun.c
===================================================================
--- uspace/srv/hid/input/port/sun.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
- * 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: pace/srv/hid/input/port/z8530.c
===================================================================
--- uspace/srv/hid/input/port/z8530.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ 	(revision )
@@ -1,116 +1,0 @@
-/*
- * 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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/loc/loc.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -56,4 +56,10 @@
 #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);
@@ -86,5 +92,5 @@
 
 static FIBRIL_MUTEX_INITIALIZE(callback_sess_mutex);
-static async_sess_t *callback_sess = NULL;
+static LIST_INITIALIZE(callback_sess_list);
 
 service_id_t loc_create_id(void)
@@ -608,4 +614,5 @@
 	size_t act_size;
 	loc_service_t *svc;
+	char *fqn;
 	
 	if (!async_data_read_receive(&callid, &size)) {
@@ -625,6 +632,14 @@
 	}
 	
-	act_size = str_size(svc->name);
+	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);
 	if (act_size > size) {
+		free(fqn);
 		fibril_mutex_unlock(&services_list_mutex);
 		async_answer_0(callid, EOVERFLOW);
@@ -633,6 +648,7 @@
 	}
 	
-	sysarg_t retval = async_data_read_finalize(callid, svc->name,
+	sysarg_t retval = async_data_read_finalize(callid, fqn,
 	    min(size, act_size));
+	free(fqn);
 	
 	fibril_mutex_unlock(&services_list_mutex);
@@ -790,7 +806,10 @@
 }
 
-/** Find ID for category specified by name.
- *
- * On success, answer will contain EOK int retval and service ID in arg1.
+/** Create callback connection.
+ *
+ * Create callback connection which will be used to send category change
+ * events.
+ *
+ * On success, answer will contain EOK int retval.
  * On failure, error code will be sent in retval.
  *
@@ -798,5 +817,5 @@
 static void loc_callback_create(ipc_callid_t iid, ipc_call_t *icall)
 {
-	async_sess_t *cb_sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	cb_sess_t *cb_sess = calloc(1, sizeof(cb_sess_t));
 	if (cb_sess == NULL) {
 		async_answer_0(iid, ENOMEM);
@@ -804,12 +823,16 @@
 	}
 	
+	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);
-	if (callback_sess != NULL) {
-		fibril_mutex_unlock(&callback_sess_mutex);
-		async_answer_0(iid, EEXIST);
-		return;
-	}
-	
-	callback_sess = cb_sess;
+	list_append(&cb_sess->cb_sess_list, &callback_sess_list);
 	fibril_mutex_unlock(&callback_sess_mutex);
 	
@@ -820,11 +843,15 @@
 {
 	fibril_mutex_lock(&callback_sess_mutex);
-
-	if (callback_sess != NULL) {
-		async_exch_t *exch = async_exchange_begin(callback_sess);
+	
+	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);
 		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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/net/cfg/e1k.nic	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -3,5 +3,5 @@
 NAME=e1k
 
-HWPATH=/hw/pci0/00:03.0/port0
+HWPATH=devices/\hw\pci0\00:03.0\port0
 NIL=eth
 IL=ip
Index: uspace/srv/net/cfg/lo.nic
===================================================================
--- uspace/srv/net/cfg/lo.nic	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/net/cfg/lo.nic	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -3,5 +3,5 @@
 NAME=lo
 
-HWPATH=/virt/lo/port0
+HWPATH=devices/\virt\lo\port0
 NIL=nildummy
 IL=ip
Index: uspace/srv/net/cfg/ne2k.nic
===================================================================
--- uspace/srv/net/cfg/ne2k.nic	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/net/cfg/ne2k.nic	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -3,5 +3,5 @@
 NAME=ne2k
 
-HWPATH=/hw/pci0/00:01.0/ne2k/port0
+HWPATH=devices/\hw\pci0\00:01.0\ne2k\port0
 NIL=eth
 IL=ip
Index: uspace/srv/net/net/Makefile
===================================================================
--- uspace/srv/net/net/Makefile	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/net/net/Makefile	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -31,5 +31,6 @@
 ROOT_PATH = $(USPACE_PREFIX)/..
 LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include \
+    -I$(LIBDRV_PREFIX)/include
 
 COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/net/net/net.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -2,4 +2,5 @@
  * Copyright (c) 2009 Lukas Mejdrech
  * Copyright (c) 2011 Radim Vansa
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -41,5 +42,4 @@
 #include <stdio.h>
 #include <str.h>
-#include <devman.h>
 #include <str_error.h>
 #include <ns.h>
@@ -56,4 +56,7 @@
 #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>
@@ -73,4 +76,7 @@
 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.
@@ -287,10 +293,10 @@
  *
  */
-static int init_device(netif_t *netif, devman_handle_t handle)
+static int init_device(netif_t *netif, service_id_t sid)
 {
 	printf("%s: Initializing device '%s'\n", NAME, netif->name);
 	
-	netif->handle = handle;
-	netif->sess = devman_device_connect(EXCHANGE_SERIALIZE, netif->handle,
+	netif->sid = sid;
+	netif->sess = loc_service_connect(EXCHANGE_SERIALIZE, netif->sid,
 	    IPC_FLAG_BLOCKING);
 	if (netif->sess == NULL) {
@@ -337,5 +343,5 @@
 		    strtol((const char *) setting->value, NULL, 10) : 0;
 		rc = nil_device_req(netif->nil->sess, netif->id,
-		    netif->handle, mtu);
+		    netif->sid, mtu);
 		if (rc != EOK) {
 			printf("%s: Unable to start network interface layer\n",
@@ -359,22 +365,35 @@
 		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_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)
+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);
 		return EINVAL;
+	}
 	
 	int index = char_map_find(&net_globals.netif_hwpaths,
 	    (uint8_t *) hwpath, 0);
-	if (index == CHAR_MAP_NULL)
+	
+	if (index == CHAR_MAP_NULL) {
+		printf("%s: Service '%s' not found in map.\n", NAME, hwpath);
+		free(hwpath);
 		return ENOENT;
+	}
+	
+	free(hwpath);
 	
 	netif_t *netif = netifs_get_index(&net_globals.netifs, index);
@@ -382,5 +401,5 @@
 		return ENOENT;
 	
-	rc = init_device(netif, handle);
+	rc = init_device(netif, sid);
 	if (rc != EOK)
 		return rc;
@@ -391,21 +410,4 @@
 	
 	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;
@@ -479,8 +481,4 @@
 		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;
@@ -528,4 +526,71 @@
 		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();
 }
 
@@ -573,5 +638,5 @@
 				continue;
 			
-			netif->handle = -1;
+			netif->sid = -1;
 			netif->sess = NULL;
 			
@@ -697,4 +762,11 @@
 	}
 	
+	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/net/net/net.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -35,4 +35,5 @@
 #define NET_NET_H_
 
+#include <ipc/loc.h>
 #include <net/device.h>
 #include <adt/char_map.h>
@@ -41,5 +42,4 @@
 #include <adt/module_map.h>
 #include <net/packet.h>
-#include <devman.h>
 
 #define NAME  "net"
@@ -96,9 +96,11 @@
 	
 	/** Serving network interface driver module index. */
-	devman_handle_t handle;  /**< Handle for devman */
-	async_sess_t *sess;      /**< Driver session. */
+	service_id_t sid;    /**< Service ID */
+	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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/net/nil/eth/eth.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -48,4 +48,5 @@
 #include <ipc/net.h>
 #include <ipc/services.h>
+#include <loc.h>
 #include <net/modules.h>
 #include <net_checksum.h>
@@ -169,5 +170,8 @@
 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
 
-int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
+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 index;
@@ -179,6 +183,6 @@
 		proto = eth_protos_get_index(&eth_globals.protos, index);
 		if ((proto) && (proto->sess)) {
-			il_device_state_msg(proto->sess, device_id, state,
-			    proto->service);
+			il_device_state_msg(proto->sess, device->device_id,
+			    state, proto->service);
 		}
 	}
@@ -226,5 +230,5 @@
  *
  * @param[in] device_id New device identifier.
- * @param[in] handle    Device driver handle.
+ * @param[in] sid       NIC service ID.
  * @param[in] mtu       Device maximum transmission unit.
  *
@@ -234,5 +238,5 @@
  *
  */
-static int eth_device_message(nic_device_id_t device_id, devman_handle_t handle,
+static int eth_device_message(nic_device_id_t device_id, service_id_t sid,
     size_t mtu)
 {
@@ -259,5 +263,5 @@
 	device = eth_devices_find(&eth_globals.devices, device_id);
 	if (device) {
-		if (device->handle != handle) {
+		if (device->sid != sid) {
 			printf("Device %d already exists\n", device->device_id);
 			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
@@ -298,5 +302,5 @@
 
 	device->device_id = device_id;
-	device->handle = handle;
+	device->sid = sid;
 	device->flags = 0;
 	if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
@@ -335,5 +339,5 @@
 	
 	/* Bind the device driver */
-	device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
+	device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid,
 	    IPC_FLAG_BLOCKING);
 	if (device->sess == NULL) {
@@ -343,5 +347,11 @@
 	}
 	
-	nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id);
+	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;
+	}
 	
 	/* Get hardware address */
@@ -362,7 +372,7 @@
 	}
 	
-	printf("%s: Device registered (id: %d, handle: %zu: mtu: %zu, "
+	printf("%s: Device registered (id: %d, sid: %zu: mtu: %zu, "
 	    "mac: " PRIMAC ", flags: 0x%x)\n", NAME,
-	    device->device_id, device->handle, device->mtu,
+	    device->device_id, device->sid, device->mtu,
 	    ARGSMAC(device->addr.address), device->flags);
 
@@ -814,5 +824,28 @@
 }
 
-static int eth_addr_changed(nic_device_id_t device_id)
+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)
 {
 	nic_address_t address;
@@ -832,28 +865,24 @@
 
 	fibril_rwlock_write_lock(&eth_globals.devices_lock);
-	/* An existing device? */
-	eth_device_t *device = eth_devices_find(&eth_globals.devices, device_id);
-	if (device) {
-		printf("Device %d changing address from " PRIMAC " to " PRIMAC "\n",
-			device_id, ARGSMAC(device->addr.address), ARGSMAC(address.address));
-		memcpy(&device->addr, &address, sizeof (nic_address_t));
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-
-		/* Notify all upper layer modules */
-		fibril_rwlock_read_lock(&eth_globals.protos_lock);
-		int index;
-		for (index = 0; index < eth_protos_count(&eth_globals.protos); index++) {
-			eth_proto_t *proto = eth_protos_get_index(&eth_globals.protos, index);
-			if (proto->sess != NULL) {
-				il_addr_changed_msg(proto->sess, device->device_id,
-						ETH_ADDR, address.address);
-			}
-		}
-
-		fibril_rwlock_read_unlock(&eth_globals.protos_lock);
-		return EOK;
-	} else {
-		return ENOENT;
-	}
+
+	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;
 }
 
@@ -921,23 +950,40 @@
 		
 		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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/net/nil/eth/eth.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -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 */
-	devman_handle_t handle;
+	service_id_t sid;
 	/** Driver session. */
 	async_sess_t *sess;
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -2,4 +2,5 @@
  * Copyright (c) 2009 Lukas Mejdrech
  * Copyright (c) 2011 Radim Vansa
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -53,6 +54,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"
@@ -69,13 +70,21 @@
 DEVICE_MAP_IMPLEMENT(nildummy_devices, nildummy_device_t);
 
-int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
+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)
 {
 	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
 	if (nildummy_globals.proto.sess)
-		il_device_state_msg(nildummy_globals.proto.sess, device_id,
-		    state, nildummy_globals.proto.service);
+		il_device_state_msg(nildummy_globals.proto.sess,
+		    device->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;
 }
 
@@ -115,5 +124,5 @@
  */
 static int nildummy_device_message(nic_device_id_t device_id,
-    devman_handle_t handle, size_t mtu)
+    service_id_t sid, size_t mtu)
 {
 	fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
@@ -123,5 +132,5 @@
 	    nildummy_devices_find(&nildummy_globals.devices, device_id);
 	if (device) {
-		if (device->handle != handle) {
+		if (device->sid != sid) {
 			printf("Device %d exists, handles do not match\n",
 			    device->device_id);
@@ -158,5 +167,5 @@
 	
 	device->device_id = device_id;
-	device->handle = handle;
+	device->sid = sid;
 	if (mtu > 0)
 		device->mtu = mtu;
@@ -165,5 +174,5 @@
 	
 	/* Bind the device driver */
-	device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
+	device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid,
 	    IPC_FLAG_BLOCKING);
 	if (device->sess == NULL) {
@@ -173,8 +182,14 @@
 	}
 	
-	nic_connect_to_nil(device->sess, SERVICE_NILDUMMY, device_id);
+	int rc = nic_callback_create(device->sess, nildummy_nic_cb_conn,
+	    device);
+	if (rc != EOK) {
+		async_hangup(device->sess);
+		
+		return ENOENT;
+	}
 	
 	/* Get hardware address */
-	int rc = nic_get_address(device->sess, &device->addr);
+	rc = nic_get_address(device->sess, &device->addr);
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
@@ -345,6 +360,4 @@
     services_t sender)
 {
-	packet_t *p;
-	
 	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
 	
@@ -356,5 +369,5 @@
 	}
 	
-	p = packet;
+	packet_t *p = packet;
 	do {
 		nic_send_frame(device->sess, packet_get_data(p),
@@ -368,4 +381,25 @@
 	
 	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);
 }
 
@@ -424,22 +458,42 @@
 		*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 492ddc9a5844c132d0a705b09240f5e610c60c30)
+++ uspace/srv/net/nil/nildummy/nildummy.h	(revision bb6f135efbecc37de9a8684aa5c7a12633b57a04)
@@ -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 driver handle. */
-	devman_handle_t handle;
+	/** Device service ID. */
+	service_id_t sid;
 	/** Driver session. */
 	async_sess_t *sess;
