Index: kernel/arch/arm32/include/mm/km.h
===================================================================
--- kernel/arch/arm32/include/mm/km.h	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ kernel/arch/arm32/include/mm/km.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -39,8 +39,12 @@
 
 #define KM_ARM32_IDENTITY_START		UINT32_C(0x80000000)
-#define KM_ARM32_IDENTITY_SIZE		UINT32_C(0x40000000)
+#define KM_ARM32_IDENTITY_SIZE		UINT32_C(0x70000000)
 
-#define KM_ARM32_NON_IDENTITY_START	UINT32_C(0xc0000000)
-#define KM_ARM32_NON_IDENTITY_SIZE	UINT32_C(0x40000000)
+#define KM_ARM32_NON_IDENTITY_START	UINT32_C(0xf0000000)
+/*
+ * The last virtual megabyte contains the high exception vectors (0xFFFF0000).
+ * Do not include this range into kernel non-identity.
+ */
+#define KM_ARM32_NON_IDENTITY_SIZE	UINT32_C(0x0ff00000)
 
 extern void km_identity_arch_init(void);
Index: kernel/arch/arm32/src/mm/page.c
===================================================================
--- kernel/arch/arm32/src/mm/page.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ kernel/arch/arm32/src/mm/page.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -65,15 +65,11 @@
 		page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
 	
+#ifdef HIGH_EXCEPTION_VECTORS
 	/* Create mapping for exception table at high offset */
-#ifdef HIGH_EXCEPTION_VECTORS
-	// XXX: fixme to use proper non-identity page
-	void *virtaddr = frame_alloc(ONE_FRAME, FRAME_KA);
-	page_mapping_insert(AS_KERNEL, EXC_BASE_ADDRESS, KA2PA(virtaddr),
-	    flags);
+	uintptr_t ev_frame = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_NONE);
+	page_mapping_insert(AS_KERNEL, EXC_BASE_ADDRESS, ev_frame, flags);
 #else
 #error "Only high exception vector supported now"
 #endif
-	cur = ALIGN_DOWN(0x50008010, FRAME_SIZE);
-	page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
 
 	page_table_unlock(AS_KERNEL, true);
Index: kernel/arch/ia32/src/mm/frame.c
===================================================================
--- kernel/arch/ia32/src/mm/frame.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ kernel/arch/ia32/src/mm/frame.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -54,6 +54,19 @@
 	
 	for (i = 0; i < e820counter; i++) {
-		uintptr_t base = (uintptr_t) e820table[i].base_address;
-		size_t size = (size_t) e820table[i].size;
+		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)
+			continue;
+		if (base64 + size64 > 0x100000000ULL)
+			size64 -= base64 + size64 - 0x100000000ULL;
+#endif
+
+		uintptr_t base = (uintptr_t) base64;
+		size_t size = (size_t) size64;
 		
 		if (!frame_adjust_zone_bounds(low, &base, &size))
Index: kernel/genarch/src/mm/page_pt.c
===================================================================
--- kernel/genarch/src/mm/page_pt.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ kernel/genarch/src/mm/page_pt.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -322,6 +322,7 @@
 
 	ASSERT(ispwr2(ptl0step));
-
-	for (addr = ALIGN_DOWN(base, ptl0step); addr < base + size;
+	ASSERT(size > 0);
+
+	for (addr = ALIGN_DOWN(base, ptl0step); addr - 1 < base + size - 1;
 	    addr += ptl0step) {
 		uintptr_t l1;
Index: kernel/generic/include/mm/frame.h
===================================================================
--- kernel/generic/include/mm/frame.h	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ kernel/generic/include/mm/frame.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -83,6 +83,7 @@
 #define FRAME_TO_ZONE_FLAGS(ff)	\
 	((((ff) & FRAME_LOWMEM) ? ZONE_LOWMEM : \
-	    (((ff) & FRAME_HIGHMEM) ? ZONE_HIGHMEM : ZONE_NONE)) | \
-	    (ZONE_AVAILABLE | ZONE_LOWMEM /* | ZONE_HIGHMEM */)) 
+	    (((ff) & FRAME_HIGHMEM) ? ZONE_HIGHMEM : \
+	    ZONE_LOWMEM /* | ZONE_HIGHMEM */)) | \
+	    ZONE_AVAILABLE) 
 
 #define ZONE_FLAGS_MATCH(zf, f) \
Index: kernel/generic/include/mm/km.h
===================================================================
--- kernel/generic/include/mm/km.h	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ kernel/generic/include/mm/km.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -37,4 +37,5 @@
 
 #include <typedefs.h>
+#include <mm/frame.h>
 
 extern void km_identity_init(void);
@@ -48,4 +49,7 @@
 extern bool km_is_non_identity(uintptr_t);
 
+extern uintptr_t km_temporary_page_get(uintptr_t *, frame_flags_t);
+extern void km_temporary_page_put(uintptr_t);
+
 #endif
 
Index: kernel/generic/src/mm/backend_anon.c
===================================================================
--- kernel/generic/src/mm/backend_anon.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ kernel/generic/src/mm/backend_anon.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -44,4 +44,5 @@
 #include <mm/frame.h>
 #include <mm/slab.h>
+#include <mm/km.h>
 #include <synch/mutex.h>
 #include <adt/list.h>
@@ -155,4 +156,6 @@
 int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
 {
+	uintptr_t upage = ALIGN_DOWN(addr, PAGE_SIZE);
+	uintptr_t kpage;
 	uintptr_t frame;
 
@@ -175,5 +178,5 @@
 		mutex_lock(&area->sh_info->lock);
 		frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
-		    ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf);
+		    upage - area->base, &leaf);
 		if (!frame) {
 			bool allocate = true;
@@ -185,6 +188,5 @@
 			 */
 			for (i = 0; i < leaf->keys; i++) {
-				if (leaf->key[i] ==
-				    ALIGN_DOWN(addr, PAGE_SIZE) - area->base) {
+				if (leaf->key[i] == upage - area->base) {
 					allocate = false;
 					break;
@@ -192,7 +194,8 @@
 			}
 			if (allocate) {
-				frame = (uintptr_t) frame_alloc_noreserve(
-				    ONE_FRAME, 0);
-				memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
+				kpage = km_temporary_page_get(&frame,
+				    FRAME_NO_RESERVE);
+				memsetb((void *) kpage, PAGE_SIZE, 0);
+				km_temporary_page_put(kpage);
 				
 				/*
@@ -201,6 +204,5 @@
 				 */
 				btree_insert(&area->sh_info->pagemap,
-				    ALIGN_DOWN(addr, PAGE_SIZE) - area->base,
-				    (void *) frame, leaf);
+				    upage - area->base, (void *) frame, leaf);
 			}
 		}
@@ -223,15 +225,16 @@
 		 *   the different causes
 		 */
-		frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
-		memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
+		kpage = km_temporary_page_get(&frame, FRAME_NO_RESERVE);
+		memsetb((void *) kpage, PAGE_SIZE, 0);
+		km_temporary_page_put(kpage);
 	}
 	
 	/*
-	 * Map 'page' to 'frame'.
+	 * Map 'upage' to 'frame'.
 	 * Note that TLB shootdown is not attempted as only new information is
 	 * being inserted into page tables.
 	 */
-	page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
-	if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
+	page_mapping_insert(AS, upage, frame, as_area_get_flags(area));
+	if (!used_space_insert(area, upage, 1))
 		panic("Cannot insert used space.");
 		
Index: kernel/generic/src/mm/backend_elf.c
===================================================================
--- kernel/generic/src/mm/backend_elf.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ kernel/generic/src/mm/backend_elf.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -44,4 +44,5 @@
 #include <mm/page.h>
 #include <mm/reserve.h>
+#include <mm/km.h>
 #include <genarch/mm/page_pt.h>
 #include <genarch/mm/page_ht.h>
@@ -229,5 +230,9 @@
 	elf_segment_header_t *entry = area->backend_data.segment;
 	btree_node_t *leaf;
-	uintptr_t base, frame, page, start_anon;
+	uintptr_t base;
+	uintptr_t frame;
+	uintptr_t kpage;
+	uintptr_t upage;
+	uintptr_t start_anon;
 	size_t i;
 	bool dirty = false;
@@ -249,6 +254,6 @@
 	    (((void *) elf) + ALIGN_DOWN(entry->p_offset, PAGE_SIZE));
 
-	/* Virtual address of faulting page*/
-	page = ALIGN_DOWN(addr, PAGE_SIZE);
+	/* Virtual address of faulting page */
+	upage = ALIGN_DOWN(addr, PAGE_SIZE);
 
 	/* Virtual address of the end of initialized part of segment */
@@ -264,5 +269,5 @@
 		mutex_lock(&area->sh_info->lock);
 		frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
-		    page - area->base, &leaf);
+		    upage - area->base, &leaf);
 		if (!frame) {
 			unsigned int i;
@@ -273,5 +278,5 @@
 
 			for (i = 0; i < leaf->keys; i++) {
-				if (leaf->key[i] == page - area->base) {
+				if (leaf->key[i] == upage - area->base) {
 					found = true;
 					break;
@@ -281,7 +286,7 @@
 		if (frame || found) {
 			frame_reference_add(ADDR2PFN(frame));
-			page_mapping_insert(AS, addr, frame,
+			page_mapping_insert(AS, upage, frame,
 			    as_area_get_flags(area));
-			if (!used_space_insert(area, page, 1))
+			if (!used_space_insert(area, upage, 1))
 				panic("Cannot insert used space.");
 			mutex_unlock(&area->sh_info->lock);
@@ -294,5 +299,5 @@
 	 * mapping.
 	 */
-	if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
+	if (upage >= entry->p_vaddr && upage + PAGE_SIZE <= start_anon) {
 		/*
 		 * Initialized portion of the segment. The memory is backed
@@ -304,16 +309,16 @@
 		 */
 		if (entry->p_flags & PF_W) {
-			frame = (uintptr_t)frame_alloc_noreserve(ONE_FRAME, 0);
-			memcpy((void *) PA2KA(frame),
-			    (void *) (base + i * FRAME_SIZE), FRAME_SIZE);
+			kpage = km_temporary_page_get(&frame, FRAME_NO_RESERVE);
+			memcpy((void *) kpage, (void *) (base + i * PAGE_SIZE),
+			    PAGE_SIZE);
 			if (entry->p_flags & PF_X) {
-				smc_coherence_block((void *) PA2KA(frame),
-				    FRAME_SIZE);
+				smc_coherence_block((void *) kpage, PAGE_SIZE);
 			}
+			km_temporary_page_put(kpage);
 			dirty = true;
 		} else {
 			frame = KA2PA(base + i * FRAME_SIZE);
 		}	
-	} else if (page >= start_anon) {
+	} else if (upage >= start_anon) {
 		/*
 		 * This is the uninitialized portion of the segment.
@@ -322,6 +327,7 @@
 		 * and cleared.
 		 */
-		frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
-		memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
+		kpage = km_temporary_page_get(&frame, FRAME_NO_RESERVE);
+		memsetb((void *) kpage, PAGE_SIZE, 0);
+		km_temporary_page_put(kpage);
 		dirty = true;
 	} else {
@@ -334,25 +340,25 @@
 		 * (The segment can be and often is shorter than 1 page).
 		 */
-		if (page < entry->p_vaddr)
-			pad_lo = entry->p_vaddr - page;
+		if (upage < entry->p_vaddr)
+			pad_lo = entry->p_vaddr - upage;
 		else
 			pad_lo = 0;
 
-		if (start_anon < page + PAGE_SIZE)
-			pad_hi = page + PAGE_SIZE - start_anon;
+		if (start_anon < upage + PAGE_SIZE)
+			pad_hi = upage + PAGE_SIZE - start_anon;
 		else
 			pad_hi = 0;
 
-		frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
-		memcpy((void *) (PA2KA(frame) + pad_lo),
-		    (void *) (base + i * FRAME_SIZE + pad_lo),
-		    FRAME_SIZE - pad_lo - pad_hi);
+		kpage = km_temporary_page_get(&frame, FRAME_NO_RESERVE);
+		memcpy((void *) (kpage + pad_lo),
+		    (void *) (base + i * PAGE_SIZE + pad_lo),
+		    PAGE_SIZE - pad_lo - pad_hi);
 		if (entry->p_flags & PF_X) {
-			smc_coherence_block((void *) (PA2KA(frame) + pad_lo), 
-			    FRAME_SIZE - pad_lo - pad_hi);
+			smc_coherence_block((void *) (kpage + pad_lo), 
+			    PAGE_SIZE - pad_lo - pad_hi);
 		}
-		memsetb((void *) PA2KA(frame), pad_lo, 0);
-		memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi,
-		    0);
+		memsetb((void *) kpage, pad_lo, 0);
+		memsetb((void *) (kpage + PAGE_SIZE - pad_hi), pad_hi, 0);
+		km_temporary_page_put(kpage);
 		dirty = true;
 	}
@@ -360,5 +366,5 @@
 	if (dirty && area->sh_info) {
 		frame_reference_add(ADDR2PFN(frame));
-		btree_insert(&area->sh_info->pagemap, page - area->base,
+		btree_insert(&area->sh_info->pagemap, upage - area->base,
 		    (void *) frame, leaf);
 	}
@@ -367,6 +373,6 @@
 		mutex_unlock(&area->sh_info->lock);
 
-	page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
-	if (!used_space_insert(area, page, 1))
+	page_mapping_insert(AS, upage, frame, as_area_get_flags(area));
+	if (!used_space_insert(area, upage, 1))
 		panic("Cannot insert used space.");
 
Index: kernel/generic/src/mm/km.c
===================================================================
--- kernel/generic/src/mm/km.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ kernel/generic/src/mm/km.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -39,10 +39,44 @@
 #include <arch/mm/km.h>
 #include <mm/page.h>
+#include <mm/frame.h>
+#include <mm/asid.h>
 #include <config.h>
 #include <typedefs.h>
 #include <lib/ra.h>
 #include <debug.h>
+#include <arch.h>
 
 static ra_arena_t *km_ni_arena;
+
+#define DEFERRED_PAGES_MAX	(PAGE_SIZE / sizeof(uintptr_t)) 
+
+/** Number of freed pages in the deferred buffer. */
+static volatile unsigned deferred_pages;
+/** Buffer of deferred freed pages. */
+static uintptr_t deferred_page[DEFERRED_PAGES_MAX];
+
+/** Flush the buffer of deferred freed pages.
+ *
+ * @return		Number of freed pages.
+ */
+static unsigned km_flush_deferred(void)
+{
+	unsigned i = 0;
+	ipl_t ipl;
+
+	ipl = tlb_shootdown_start(TLB_INVL_ASID, ASID_KERNEL, 0, 0);
+
+	for (i = 0; i < deferred_pages; i++) {
+		page_mapping_remove(AS_KERNEL, deferred_page[i]);
+		km_page_free(deferred_page[i], PAGE_SIZE);
+	}
+
+	tlb_invalidate_asid(ASID_KERNEL);
+
+	as_invalidate_translation_cache(AS_KERNEL, 0, -1);
+	tlb_shootdown_finalize(ipl);
+
+	return i;
+}
 
 /** Architecture dependent setup of identity-mapped kernel memory. */
@@ -87,4 +121,79 @@
 }
 
+/** Unmap kernen non-identity page.
+ *
+ * @param[in] page	Non-identity page to be unmapped.
+ */
+static void km_unmap_deferred(uintptr_t page)
+{
+	page_table_lock(AS_KERNEL, true);
+
+	if (deferred_pages == DEFERRED_PAGES_MAX) {
+		(void) km_flush_deferred();
+		deferred_pages = 0;
+	}
+
+	deferred_page[deferred_pages++] = page;
+
+	page_table_unlock(AS_KERNEL, true);
+}
+
+/** Create a temporary page.
+ *
+ * The page is mapped read/write to a newly allocated frame of physical memory.
+ * The page must be returned back to the system by a call to
+ * km_temporary_page_put().
+ *
+ * @param[inout] framep	Pointer to a variable which will receive the physical
+ *			address of the allocated frame.
+ * @param[in] flags	Frame allocation flags. FRAME_NONE or FRAME_NO_RESERVE.
+ * @return		Virtual address of the allocated frame.
+ */
+uintptr_t km_temporary_page_get(uintptr_t *framep, frame_flags_t flags)
+{
+	uintptr_t frame;
+	uintptr_t page;
+
+	ASSERT(THREAD);
+	ASSERT(framep);
+	ASSERT(!(flags & ~FRAME_NO_RESERVE));
+
+	/*
+	 * Allocate a frame, preferably from high memory.
+	 */
+	frame = (uintptr_t) frame_alloc(ONE_FRAME,
+	    FRAME_HIGHMEM | FRAME_ATOMIC | flags); 
+	if (frame) {
+		page = km_page_alloc(PAGE_SIZE, PAGE_SIZE);
+		ASSERT(page);	// FIXME
+		page_table_lock(AS_KERNEL, true);
+		page_mapping_insert(AS_KERNEL, page, frame,
+		    PAGE_CACHEABLE | PAGE_READ | PAGE_WRITE);
+		page_table_unlock(AS_KERNEL, true);
+	} else {
+		frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME,
+		    FRAME_LOWMEM);
+		page = PA2KA(frame);
+	}
+
+	*framep = frame;
+	return page;	
+}
+
+/** Destroy a temporary page.
+ *
+ * This function destroys a temporary page previously created by
+ * km_temporary_page_get(). The page destruction may be immediate or deferred.
+ * The frame mapped by the destroyed page is not freed.
+ *
+ * @param[in] page	Temporary page to be destroyed.
+ */
+void km_temporary_page_put(uintptr_t page)
+{
+	ASSERT(THREAD);
+
+	if (km_is_non_identity(page))
+		km_unmap_deferred(page);
+}
 
 /** @}
Index: kernel/generic/src/mm/page.c
===================================================================
--- kernel/generic/src/mm/page.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ kernel/generic/src/mm/page.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -202,5 +202,5 @@
 	asize = ALIGN_UP(size, PAGE_SIZE);
 	align = ispwr2(size) ? size : (1U << (fnzb(size) + 1));
-	virtaddr = km_page_alloc(asize, align);
+	virtaddr = km_page_alloc(asize, max(PAGE_SIZE, align));
 
 	page_table_lock(AS_KERNEL, true);
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/drv/nic/e1k/e1k.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -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,88 @@
 	    (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 +1522,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 +1554,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 +1561,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 +1571,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 +1596,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 +1627,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;
@@ -1630,5 +1654,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 +1711,5 @@
 }
 
-/** Activate the device to receive and transmit packets
+/** Activate the device to receive and transmit frames
  *
  * @param nic NIC driver data
@@ -2073,4 +2097,5 @@
 int e1000_dev_add(ddf_dev_t *dev)
 {
+	ddf_fun_t *fun;
 	assert(dev);
 	
@@ -2103,11 +2128,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 +2160,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 +2325,5 @@
 	
 	if (!descriptor_available) {
-		/* Packet lost */
+		/* Frame lost */
 		fibril_mutex_unlock(&e1000->tx_lock);
 		return;
@@ -2312,5 +2354,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 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/drv/nic/e1k/e1k.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -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 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/drv/nic/lo/lo.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -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,59 @@
 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 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/drv/nic/ne2k/dp8390.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -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 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/drv/nic/ne2k/dp8390.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -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 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -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 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/drv/nic/rtl8139/defs.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -42,8 +42,8 @@
 #define RTL8139_IO_SIZE 256
 
-/** The maximal transmitted packet length in bytes allowed according to RTL8139
+/** The maximal transmitted frame length in bytes allowed according to RTL8139
  *  documentation (see SIZE part of TSD documentation)
  */
-#define RTL8139_PACKET_MAX_LENGTH 1792
+#define RTL8139_FRAME_MAX_LENGTH 1792
 
 
@@ -94,5 +94,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 */
 
@@ -282,5 +282,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 +302,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 +362,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 +399,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 +416,9 @@
 };
 
-/** Maximal runt packet size + 1 */
+/** Maximal runt frame size + 1 */
 #define RTL8139_RUNT_MAX_SIZE 64
 
-/** Bits in packet header */
-enum rtl8139_packet_header {
+/** Bits in frame header */
+enum rtl8139_frame_header {
 	RSR_MAR  = (1 << 15),  /**< Multicast received */
 	RSR_PAM  = (1 << 14),  /**< Physical address match */
@@ -426,10 +426,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 +451,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 +459,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 
 							  */
@@ -478,11 +478,11 @@
 extern const struct rtl8139_hwver_map rtl8139_versions[RTL8139_VER_COUNT + 1];
 
-/** Size in the packet header while copying from RxFIFO to Rx buffer */
+/** Size in the frame header while copying from RxFIFO to Rx buffer */
 #define RTL8139_EARLY_SIZE UINT16_C(0xfff0)
-/** The only supported pause packet time value */
+/** The only supported pause frame 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
+/** 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 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -39,5 +39,4 @@
 #include <io/log.h>
 #include <nic.h>
-#include <packet_client.h>
 #include <device/pci.h>
 
@@ -152,5 +151,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 +169,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 +393,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 +411,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 +436,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];
@@ -505,32 +504,25 @@
 }
 
-/** 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 +560,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 +573,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 +597,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 +610,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 +621,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 +634,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 +719,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 +749,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 +761,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 +817,5 @@
 	}
 
-	/* Check transmittion interrupts first to allow transmit next packets
+	/* Check transmittion interrupts first to allow transmit next frames
 	 * sooner
 	 */
@@ -832,5 +824,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 +925,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,10 +1205,10 @@
 		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);
 
@@ -1288,4 +1280,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 +1318,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;
 	}
 
@@ -1335,4 +1343,10 @@
 	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 +1491,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 +1516,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 +1522,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 +1554,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 +1810,5 @@
 }
 
-/** Set unicast packets acceptance mode
+/** Set unicast frames acceptance mode
  *
  *  @param nic_data  The nic device to update
@@ -1854,5 +1868,5 @@
 }
 
-/** Set multicast packets acceptance mode
+/** Set multicast frames acceptance mode
  *
  *  @param nic_data  The nic device to update
@@ -1899,5 +1913,5 @@
 }
 
-/** Set broadcast packets acceptance mode
+/** Set broadcast frames acceptance mode
  *
  *  @param nic_data  The nic device to update
@@ -1929,5 +1943,5 @@
 }
 
-/** Get state of acceptance of weird packets
+/** Get state of acceptance of weird frames
  *
  *  @param[in]  device  The device to check
@@ -1951,5 +1965,5 @@
 };
 
-/** Set acceptance of weird packets
+/** Set acceptance of weird frames
  *
  *  @param device  The device to update
@@ -2127,5 +2141,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 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/drv/nic/rtl8139/driver.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -39,5 +39,5 @@
 /** Transmittion buffers count */
 #define TX_BUFF_COUNT 4
-/** Size of buffer for one packet
+/** Size of buffer for one frame
  *  - 2kB
  */
@@ -49,11 +49,11 @@
 #define RTL8139_CRC_SIZE 4
 
-/** The default mode of accepting unicast packets */
+/** The default mode of accepting unicast frames */
 #define RTL8139_RCR_UCAST_DEFAULT RCR_ACCEPT_PHYS_MATCH
-/** The default mode of accepting multicast packets */
+/** The default mode of accepting multicast frames */
 #define RTL8139_RCR_MCAST_DEFAULT 0
-/** The default mode of accepting broadcast packets */
+/** The default mode of accepting broadcast frames */
 #define RTL8139_RCR_BCAST_DEFAULT RCR_ACCEPT_BROADCAST
-/** The default mode of accepting defect packets */
+/** The default mode of accepting defect frames */
 #define RTL8139_RCR_DEFECT_DEFAULT 0
 
@@ -112,5 +112,5 @@
 	size_t tx_used;
 
-	/** Buffer for receiving packets */
+	/** Buffer for receiving frames */
 	void *rx_buff_phys;
 	void *rx_buff_virt;
Index: uspace/lib/net/include/nil_remote.h
===================================================================
--- uspace/lib/net/include/nil_remote.h	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/lib/net/include/nil_remote.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -39,4 +39,5 @@
 #include <generic.h>
 #include <async.h>
+#include <sys/types.h>
 
 #define nil_bind_service(service, device_id, me, receiver) \
@@ -61,5 +62,5 @@
     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_received_msg(async_sess_t *, nic_device_id_t, void *, size_t);
 extern int nil_addr_changed_msg(async_sess_t *, nic_device_id_t,
     const nic_address_t *);
Index: uspace/lib/net/nil/nil_remote.c
===================================================================
--- uspace/lib/net/nil/nil_remote.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/lib/net/nil/nil_remote.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -77,8 +77,22 @@
  */
 int nil_received_msg(async_sess_t *sess, nic_device_id_t device_id,
-    packet_id_t packet_id)
+    void *data, size_t size)
 {
-	return generic_received_msg_remote(sess, NET_NIL_RECEIVED,
-	    device_id, packet_id, 0, 0);
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, NET_NIL_RECEIVED, (sysarg_t) device_id,
+	    &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/include/nic.h
===================================================================
--- uspace/lib/nic/include/nic.h	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/lib/nic/include/nic.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -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 *);
@@ -225,4 +226,5 @@
 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 +235,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 +249,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 +274,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 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/lib/nic/include/nic_driver.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -50,6 +50,4 @@
 #include "nic_rx_control.h"
 #include "nic_wol_virtues.h"
-
-#define DEVICE_CATEGORY_NIC "nic"
 
 struct sw_poll_info {
Index: uspace/lib/nic/include/nic_rx_control.h
===================================================================
--- uspace/lib/nic/include/nic_rx_control.h	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/lib/nic/include/nic_rx_control.h	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -46,5 +46,4 @@
 #include <fibril_synch.h>
 #include <net/device.h>
-#include <net/packet_header.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/src/nic_driver.c
===================================================================
--- uspace/lib/nic/src/nic_driver.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/lib/nic/src/nic_driver.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -51,7 +51,4 @@
 #include <net_interface.h>
 #include <ops/nic.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <net/packet_header.h>
 #include <errno.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;
 }
 
@@ -162,5 +158,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 +266,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 +291,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 +310,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) {
@@ -604,5 +586,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 +595,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 +604,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 +637,6 @@
 		}
 		fibril_rwlock_write_unlock(&nic_data->stats_lock);
-		nil_received_msg(nic_data->nil_session, nic_data->device_id, pid);
+		nil_received_msg(nic_data->nil_session, nic_data->device_id,
+		    frame->data, frame->size);
 	} else {
 		switch (frame_type) {
@@ -685,31 +652,32 @@
 		}
 		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
+	    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 +694,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);
@@ -846,41 +812,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 +1026,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 +1267,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_rx_control.c
===================================================================
--- uspace/lib/nic/src/nic_rx_control.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/lib/nic/src/nic_rx_control.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -392,14 +392,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 +451,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) {
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/srv/net/nil/eth/eth.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -814,4 +814,25 @@
 }
 
+static int eth_received(nic_device_id_t device_id)
+{
+	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(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_id, packet);
+}
+
 static int eth_addr_changed(nic_device_id_t device_id)
 {
@@ -926,9 +947,5 @@
 		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);
-		
+		rc = eth_received(IPC_GET_ARG1(*call));
 		async_answer_0(callid, (sysarg_t) rc);
 		return rc;
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision 47a89fe90cc7aa9036af76b9b709c7357512c2b9)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision 86c71dec3e002c2f25c5b17cf1c6165ebf6477a1)
@@ -370,4 +370,25 @@
 }
 
+static int nildummy_received(nic_device_id_t device_id)
+{
+	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_id, packet);
+}
+
 int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
     ipc_call_t *answer, size_t *answer_count)
@@ -431,9 +452,5 @@
 	
 	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);
-		
+		rc = nildummy_received(IPC_GET_ARG1(*call));
 		async_answer_0(callid, (sysarg_t) rc);
 		return rc;
