Index: Makefile
===================================================================
--- Makefile	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ Makefile	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -42,5 +42,5 @@
 CONFIG_HEADER = config.h
 
-.PHONY: all precheck cscope autotool config_auto config_default config distclean clean check
+.PHONY: all precheck cscope autotool config_auto config_default config distclean clean check distfile dist
 
 all: $(COMMON_MAKEFILE) $(COMMON_HEADER) $(CONFIG_MAKEFILE) $(CONFIG_HEADER)
@@ -64,4 +64,6 @@
 endif
 
+# Autotool (detects compiler features)
+
 $(COMMON_MAKEFILE): autotool
 $(COMMON_HEADER): autotool
@@ -70,4 +72,6 @@
 	$(AUTOTOOL)
 	-[ -f $(COMMON_HEADER_PREV) ] && diff -q $(COMMON_HEADER_PREV) $(COMMON_HEADER) && mv -f $(COMMON_HEADER_PREV) $(COMMON_HEADER)
+
+# Build-time configuration
 
 $(CONFIG_MAKEFILE): config_default
@@ -84,6 +88,16 @@
 	$(CONFIG) $<
 
+# Distribution files
+
+distfile: all
+	$(MAKE) -C dist distfile
+
+dist:
+	$(MAKE) -C dist dist
+
+# Cleaning
+
 distclean: clean
-	rm -f $(CSCOPE).out $(COMMON_MAKEFILE) $(COMMON_HEADER) $(COMMON_HEADER_PREV) $(CONFIG_MAKEFILE) $(CONFIG_HEADER) tools/*.pyc tools/checkers/*.pyc
+	rm -f $(CSCOPE).out $(COMMON_MAKEFILE) $(COMMON_HEADER) $(COMMON_HEADER_PREV) $(CONFIG_MAKEFILE) $(CONFIG_HEADER) tools/*.pyc tools/checkers/*.pyc dist/HelenOS-*
 
 clean:
Index: boot/arch/mips32/src/Makefile
===================================================================
--- boot/arch/mips32/src/Makefile	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ boot/arch/mips32/src/Makefile	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -32,9 +32,13 @@
 .PHONY: all clean
 
-all: ../../../../version ../../../../Makefile.config ../../../../config.h ../../../../config.defs
+all: ../../../../version ../../../../Makefile.common ../../../../Makefile.config ../../../../config.h
 	-[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
 	$(MAKE) -f Makefile.build PRECHECK=$(PRECHECK)
 
 clean:
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
@@ -43,4 +47,7 @@
 		rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
 	done
+	for file in $(NET_CFG) ; do \
+		rm -f $(USPACEDIR)/dist/cfg/net/`basename $$file` ; \
+	done
 	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(RAW) $(COMPS).h $(COMPS).c $(LINK) $(INITRD).img $(INITRD).fs
 	find . -name '*.o' -follow -exec rm \{\} \;
Index: boot/arch/mips32/src/Makefile.build
===================================================================
--- boot/arch/mips32/src/Makefile.build	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ boot/arch/mips32/src/Makefile.build	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -32,6 +32,6 @@
 
 include ../../../../version
+include ../../../../Makefile.common
 include ../../../../Makefile.config
-include ../../../../config.defs
 include Makefile.common
 include Makefile.toolchain
@@ -77,4 +77,8 @@
 
 $(DEPEND):
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		cp $$file $(USPACEDIR)/dist/srv/ ; \
@@ -82,4 +86,7 @@
 	for file in $(RD_APPS) ; do \
 		cp $$file $(USPACEDIR)/dist/app/ ; \
+	done
+	for file in $(NET_CFG) ; do \
+		cp $$file $(USPACEDIR)/dist/cfg/net/ ; \
 	done
 ifeq ($(RDFMT),tmpfs)
Index: boot/arch/mips32/src/Makefile.toolchain
===================================================================
--- boot/arch/mips32/src/Makefile.toolchain	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ boot/arch/mips32/src/Makefile.toolchain	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -27,14 +27,5 @@
 #
 
-## Toolchain configuration
-#
-
-ifndef CROSS_PREFIX
-	CROSS_PREFIX = /usr/local
-endif
-
 BFD_ARCH = mips
-TARGET = mipsel-linux-gnu
-TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips32/bin
 
 JOBFILE = ../../../../tools/jobfile.py
@@ -48,6 +39,4 @@
 	BFD_NAME = elf32-tradbigmips
 	BFD = ecoff-bigmips
-	TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips32eb/bin
-	TARGET = mips-linux-gnu
 endif
 
@@ -55,20 +44,4 @@
 	BFD_NAME = elf32-tradlittlemips
 	BFD = binary
-endif
-
-ifeq ($(COMPILER),gcc_native)
-	CC = gcc
-	AS = as
-	LD = ld
-	OBJCOPY = objcopy
-	OBJDUMP = objdump
-endif
-
-ifeq ($(COMPILER),gcc_cross)
-	CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc
-	AS = $(TOOLCHAIN_DIR)/$(TARGET)-as
-	LD = $(TOOLCHAIN_DIR)/$(TARGET)-ld
-	OBJCOPY = $(TOOLCHAIN_DIR)/$(TARGET)-objcopy
-	OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
 endif
 
Index: boot/arch/sparc64/include/arch.h
===================================================================
--- boot/arch/sparc64/include/arch.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ boot/arch/sparc64/include/arch.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -41,4 +41,5 @@
 #define STACK_BIAS                   2047
 #define STACK_WINDOW_SAVE_AREA_SIZE  (16 * 8)
+#define STACK_ARG_SAVE_AREA_SIZE     (6 * 8)
 
 #define NWINDOWS  8
Index: boot/arch/sparc64/src/asm.S
===================================================================
--- boot/arch/sparc64/src/asm.S	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ boot/arch/sparc64/src/asm.S	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -152,5 +152,5 @@
 .global ofw
 ofw:
-	save %sp, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
+	save %sp, -(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp
 	set ofw_cif, %l0
 	ldx [%l0], %l0
Index: boot/arch/sparc64/src/main.c
===================================================================
--- boot/arch/sparc64/src/main.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ boot/arch/sparc64/src/main.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -190,4 +190,5 @@
 	bootinfo.memmap.zones[0].start += OBP_BIAS;
 	bootinfo.memmap.zones[0].size -= OBP_BIAS;
+	bootinfo.memmap.total -= OBP_BIAS;
 }
 
@@ -204,4 +205,7 @@
 	bootinfo.physmem_start = ofw_get_physmem_start();
 	ofw_memmap(&bootinfo.memmap);
+
+	if (arch == ARCH_SUN4V)
+		sun4v_fixups();
 	
 	void *bootinfo_pa = ofw_translate(&bootinfo);
@@ -253,21 +257,16 @@
 		
 		/*
-		 * At this point, we claim the physical memory that we are
-		 * going to use. We should be safe in case of the virtual
+		 * At this point, we claim and map the physical memory that we
+		 * are going to use. We should be safe in case of the virtual
 		 * address space because the OpenFirmware, according to its
-		 * SPARC binding, should restrict its use of virtual memory
-		 * to addresses from [0xffd00000; 0xffefffff] and
-		 * [0xfe000000; 0xfeffffff].
-		 *
-		 * We don't map this piece of memory. We simply rely on
-		 * SILO to have it done for us already in this case.
-		 *
-		 * XXX SILO only maps 8 MB for us here. We should improve
-		 *     this code to be totally independent on the behavior
-		 *     of SILO.
-		 *
+		 * SPARC binding, should restrict its use of virtual memory to
+		 * addresses from [0xffd00000; 0xffefffff] and [0xfe000000;
+		 * 0xfeffffff].
 		 */
 		ofw_claim_phys(bootinfo.physmem_start + dest[i - 1],
 		    ALIGN_UP(components[i - 1].inflated, PAGE_SIZE));
+		
+		ofw_map(bootinfo.physmem_start + dest[i - 1], dest[i - 1],
+		    ALIGN_UP(components[i - 1].inflated, PAGE_SIZE), -1);
 		
 		int err = inflate(components[i - 1].start, components[i - 1].size,
@@ -304,7 +303,4 @@
 		sun4u_smp();
 	
-	if (arch == ARCH_SUN4V)
-		sun4v_fixups();
-	
 	printf("Booting the kernel ...\n");
 	jump_to_kernel(bootinfo.physmem_start | BSP_PROCESSOR, &bootinfo, subarch,
Index: boot/generic/src/balloc.c
===================================================================
--- boot/generic/src/balloc.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ boot/generic/src/balloc.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -65,4 +65,4 @@
 void *balloc_rebase(void *ptr)
 {
-	return (void *) ((uintptr_t) ptr - phys_base + ballocs->base);
+	return (void *) (((uintptr_t) ptr - phys_base) + ballocs->base);
 }
Index: dist/Makefile
===================================================================
--- dist/Makefile	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
+++ dist/Makefile	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -0,0 +1,62 @@
+#
+# 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.
+#
+
+-include ../version
+-include ../Makefile.config
+-include ../boot/arch/$(BARCH)/Makefile.inc
+-include ../boot/Makefile.common
+
+PROFILES = amd64 arm32/GXemul arm32/integratorcp arm32/gta02 ia32 \
+    ia64/i460GX ia64/ski mips32/GXemul mips32/msim sparc64/niagara \
+    sparc64/serengeti sparc64/ultra
+
+ifdef POST_OUTPUT
+	IMGFILE = $(POST_OUTPUT)
+else
+	IMGFILE = $(BOOT_OUTPUT)
+endif
+
+SUFFIX = $(suffix $(IMGFILE))
+DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX)
+
+.PHONY: all clean dist distfile
+
+all: distfile
+distfile: $(DISTFILE)
+
+$(DISTFILE): $(IMGFILE)
+	cp $< $@
+
+dist:
+	for profile in $(PROFILES); do \
+		$(MAKE) -C .. clean ; \
+		$(MAKE) -C .. PROFILE=$$profile distfile ; \
+	done
+
+clean:
+	rm -f $(DISTFILE)
Index: kernel/arch/ia32/_link.ld.in
===================================================================
--- kernel/arch/ia32/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/arch/ia32/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -49,7 +49,19 @@
 	}
 	
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); }
+	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_info 0 : { *(.debug_info); }
+	.debug_line 0 : { *(.debug_line); }
+	.debug_loc 0 : { *(.debug_loc); }
+	.debug_pubnames 0 : { *(.debug_pubnames); }
+	.debug_pubtypes 0 : { *(.debug_pubtypes); }
+	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_str 0 : { *(.debug_str); }
+#endif
+	
 	/DISCARD/ : {
-		*(.note.GNU-stack);
-		*(.comment);
+		*(*);
 	}
 	
Index: kernel/arch/mips32/src/mm/tlb.c
===================================================================
--- kernel/arch/mips32/src/mm/tlb.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/arch/mips32/src/mm/tlb.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -557,6 +557,7 @@
 	entry_hi_t hi, hi_save;
 	tlb_index_t index;
-
-	ASSERT(asid != ASID_INVALID);
+	
+	if (asid == ASID_INVALID)
+		return;
 
 	hi_save.value = cp0_entry_hi_read();
Index: kernel/arch/sparc64/src/sun4v/asm.S
===================================================================
--- kernel/arch/sparc64/src/sun4v/asm.S	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/arch/sparc64/src/sun4v/asm.S	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -41,6 +41,5 @@
 .global switch_to_userspace
 switch_to_userspace:
-	wrpr PSTATE_PRIV_BIT, %pstate
-	save %o1, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
+	save %o1, -(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp
 	flushw
 	wrpr %g0, 0, %cleanwin		! avoid information leak
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/generic/include/mm/as.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -115,17 +115,19 @@
 	
 	/**
-	 * Number of processors on wich is this address space active.
-	 * Protected by asidlock.
+	 * Number of processors on which this
+	 * address space is active. Protected by
+	 * asidlock.
 	 */
 	size_t cpu_refcount;
 	
-	/**
-	 * Address space identifier.
-	 * Constant on architectures that do not support ASIDs.
-	 * Protected by asidlock.
+	/** Address space identifier.
+	 *
+	 * Constant on architectures that do not
+	 * support ASIDs. Protected by asidlock.
+	 *
 	 */
 	asid_t asid;
 	
-	/** Number of references (i.e tasks that reference this as). */
+	/** Number of references (i.e. tasks that reference this as). */
 	atomic_t refcount;
 	
@@ -199,24 +201,29 @@
 typedef struct {
 	mutex_t lock;
+	
 	/** Containing address space. */
 	as_t *as;
 	
-	/**
-	 * Flags related to the memory represented by the address space area.
-	 */
+	/** Memory flags. */
 	unsigned int flags;
 	
-	/** Attributes related to the address space area itself. */
+	/** Address space area attributes. */
 	unsigned int attributes;
-	/** Size of this area in multiples of PAGE_SIZE. */
+	
+	/** Number of pages in the area. */
 	size_t pages;
+	
+	/** Number of resident pages in the area. */
+	size_t resident;
+	
 	/** Base address of this area. */
 	uintptr_t base;
+	
 	/** Map of used space. */
 	btree_t used_space;
 	
 	/**
-	 * If the address space area has been shared, this pointer will
-	 * reference the share info structure.
+	 * If the address space area is shared. this is
+	 * a reference to the share info structure.
 	 */
 	share_info_t *sh_info;
@@ -261,7 +268,6 @@
 extern bool as_area_check_access(as_area_t *, pf_access_t);
 extern size_t as_area_get_size(uintptr_t);
-extern int used_space_insert(as_area_t *, uintptr_t, size_t);
-extern int used_space_remove(as_area_t *, uintptr_t, size_t);
-
+extern bool used_space_insert(as_area_t *, uintptr_t, size_t);
+extern bool used_space_remove(as_area_t *, uintptr_t, size_t);
 
 /* Interface to be implemented by architectures. */
@@ -307,4 +313,5 @@
 extern sysarg_t sys_as_area_change_flags(uintptr_t, unsigned int);
 extern sysarg_t sys_as_area_destroy(uintptr_t);
+extern sysarg_t sys_as_get_unmapped_area(uintptr_t, size_t);
 
 /* Introspection functions. */
Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/generic/include/syscall/syscall.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -59,4 +59,5 @@
 	SYS_AS_AREA_CHANGE_FLAGS,
 	SYS_AS_AREA_DESTROY,
+	SYS_AS_GET_UNMAPPED_AREA,
 	
 	SYS_IPC_CALL_SYNC_FAST,
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/generic/src/console/cmd.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -553,6 +553,11 @@
 	for (i = 0; basic_commands[i]; i++) {
 		cmd_initialize(basic_commands[i]);
-		if (!cmd_register(basic_commands[i]))
-			printf("Cannot register command %s\n", basic_commands[i]->name);
+	}
+
+	for (i = 0; basic_commands[i]; i++) {
+		if (!cmd_register(basic_commands[i])) {
+			printf("Cannot register command %s\n",
+			    basic_commands[i]->name);
+		}
 	}
 }
Index: kernel/generic/src/lib/elf.c
===================================================================
--- kernel/generic/src/lib/elf.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/generic/src/lib/elf.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -157,4 +157,5 @@
 	case PT_NULL:
 	case PT_PHDR:
+	case PT_NOTE:
 		break;
 	case PT_LOAD:
@@ -173,5 +174,4 @@
 		break;
 	case PT_SHLIB:
-	case PT_NOTE:
 	case PT_LOPROC:
 	case PT_HIPROC:
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/generic/src/mm/as.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -71,4 +71,5 @@
 #include <memstr.h>
 #include <macros.h>
+#include <bitops.h>
 #include <arch.h>
 #include <errno.h>
@@ -86,17 +87,15 @@
  * Each architecture decides what functions will be used to carry out
  * address space operations such as creating or locking page tables.
- *
  */
 as_operations_t *as_operations = NULL;
 
-/**
- * Slab for as_t objects.
+/** Slab for as_t objects.
  *
  */
 static slab_cache_t *as_slab;
 
-/**
- * This lock serializes access to the ASID subsystem.
- * It protects:
+/** ASID subsystem lock.
+ *
+ * This lock protects:
  * - inactive_as_with_asid_head list
  * - as->asid for each as of the as_t type
@@ -107,7 +106,6 @@
 
 /**
- * This list contains address spaces that are not active on any
- * processor and that have valid ASID.
- *
+ * Inactive address spaces (on all processors)
+ * that have valid ASID.
  */
 LIST_INITIALIZE(inactive_as_with_asid_head);
@@ -123,13 +121,10 @@
 	mutex_initialize(&as->lock, MUTEX_PASSIVE);
 	
-	int rc = as_constructor_arch(as, flags);
-	
-	return rc;
+	return as_constructor_arch(as, flags);
 }
 
 NO_TRACE static size_t as_destructor(void *obj)
 {
-	as_t *as = (as_t *) obj;
-	return as_destructor_arch(as);
+	return as_destructor_arch((as_t *) obj);
 }
 
@@ -146,5 +141,6 @@
 		panic("Cannot create kernel address space.");
 	
-	/* Make sure the kernel address space
+	/*
+	 * Make sure the kernel address space
 	 * reference count never drops to zero.
 	 */
@@ -195,5 +191,5 @@
 {
 	DEADLOCK_PROBE_INIT(p_asidlock);
-
+	
 	ASSERT(as != AS);
 	ASSERT(atomic_get(&as->refcount) == 0);
@@ -203,5 +199,5 @@
 	 * lock its mutex.
 	 */
-
+	
 	/*
 	 * We need to avoid deadlock between TLB shootdown and asidlock.
@@ -210,5 +206,4 @@
 	 * disabled to prevent nested context switches. We also depend on the
 	 * fact that so far no spinlocks are held.
-	 *
 	 */
 	preemption_disable();
@@ -235,5 +230,5 @@
 	spinlock_unlock(&asidlock);
 	interrupts_restore(ipl);
-
+	
 	
 	/*
@@ -241,5 +236,4 @@
 	 * The B+tree must be walked carefully because it is
 	 * also being destroyed.
-	 *
 	 */
 	bool cond = true;
@@ -268,6 +262,6 @@
 /** Hold a reference to an address space.
  *
- * Holding a reference to an address space prevents destruction of that address
- * space.
+ * Holding a reference to an address space prevents destruction
+ * of that address space.
  *
  * @param as Address space to be held.
@@ -281,6 +275,6 @@
 /** Release a reference to an address space.
  *
- * The last one to release a reference to an address space destroys the address
- * space.
+ * The last one to release a reference to an address space
+ * destroys the address space.
  *
  * @param asAddress space to be released.
@@ -295,22 +289,22 @@
 /** Check area conflicts with other areas.
  *
- * @param as         Address space.
- * @param va         Starting virtual address of the area being tested.
- * @param size       Size of the area being tested.
- * @param avoid_area Do not touch this area.
+ * @param as    Address space.
+ * @param addr  Starting virtual address of the area being tested.
+ * @param count Number of pages in the area being tested.
+ * @param avoid Do not touch this area.
  *
  * @return True if there is no conflict, false otherwise.
  *
  */
-NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
-    as_area_t *avoid_area)
-{
+NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr,
+    size_t count, as_area_t *avoid)
+{
+	ASSERT((addr % PAGE_SIZE) == 0);
 	ASSERT(mutex_locked(&as->lock));
 	
 	/*
 	 * We don't want any area to have conflicts with NULL page.
-	 *
-	 */
-	if (overlaps(va, size, (uintptr_t) NULL, PAGE_SIZE))
+	 */
+	if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
 		return false;
 	
@@ -321,11 +315,10 @@
 	 * record in the left neighbour, the leftmost record in the right
 	 * neighbour and all records in the leaf node itself.
-	 *
 	 */
 	btree_node_t *leaf;
 	as_area_t *area =
-	    (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
+	    (as_area_t *) btree_search(&as->as_area_btree, addr, &leaf);
 	if (area) {
-		if (area != avoid_area)
+		if (area != avoid)
 			return false;
 	}
@@ -337,12 +330,15 @@
 		area = (as_area_t *) node->value[node->keys - 1];
 		
-		mutex_lock(&area->lock);
-		
-		if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
+		if (area != avoid) {
+			mutex_lock(&area->lock);
+			
+			if (overlaps(addr, count << PAGE_WIDTH,
+			    area->base, area->pages << PAGE_WIDTH)) {
+				mutex_unlock(&area->lock);
+				return false;
+			}
+			
 			mutex_unlock(&area->lock);
-			return false;
-		}
-		
-		mutex_unlock(&area->lock);
+		}
 	}
 	
@@ -351,12 +347,15 @@
 		area = (as_area_t *) node->value[0];
 		
-		mutex_lock(&area->lock);
-		
-		if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
+		if (area != avoid) {
+			mutex_lock(&area->lock);
+			
+			if (overlaps(addr, count << PAGE_WIDTH,
+			    area->base, area->pages << PAGE_WIDTH)) {
+				mutex_unlock(&area->lock);
+				return false;
+			}
+			
 			mutex_unlock(&area->lock);
-			return false;
-		}
-		
-		mutex_unlock(&area->lock);
+		}
 	}
 	
@@ -366,10 +365,11 @@
 		area = (as_area_t *) leaf->value[i];
 		
-		if (area == avoid_area)
+		if (area == avoid)
 			continue;
 		
 		mutex_lock(&area->lock);
 		
-		if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
+		if (overlaps(addr, count << PAGE_WIDTH,
+		    area->base, area->pages << PAGE_WIDTH)) {
 			mutex_unlock(&area->lock);
 			return false;
@@ -382,8 +382,7 @@
 	 * So far, the area does not conflict with other areas.
 	 * Check if it doesn't conflict with kernel address space.
-	 *
 	 */
 	if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
-		return !overlaps(va, size,
+		return !overlaps(addr, count << PAGE_WIDTH,
 		    KERNEL_ADDRESS_SPACE_START,
 		    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
@@ -412,9 +411,11 @@
     mem_backend_data_t *backend_data)
 {
-	if (base % PAGE_SIZE)
+	if ((base % PAGE_SIZE) != 0)
 		return NULL;
 	
-	if (!size)
+	if (size == 0)
 		return NULL;
+	
+	size_t pages = SIZE2FRAMES(size);
 	
 	/* Writeable executable areas are not supported. */
@@ -424,5 +425,5 @@
 	mutex_lock(&as->lock);
 	
-	if (!check_area_conflicts(as, base, size, NULL)) {
+	if (!check_area_conflicts(as, base, pages, NULL)) {
 		mutex_unlock(&as->lock);
 		return NULL;
@@ -436,5 +437,6 @@
 	area->flags = flags;
 	area->attributes = attrs;
-	area->pages = SIZE2FRAMES(size);
+	area->pages = pages;
+	area->resident = 0;
 	area->base = base;
 	area->sh_info = NULL;
@@ -479,5 +481,4 @@
 	 * to find out whether this is a miss or va belongs to an address
 	 * space area found there.
-	 *
 	 */
 	
@@ -490,5 +491,6 @@
 		mutex_lock(&area->lock);
 		
-		if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
+		if ((area->base <= va) &&
+		    (va < area->base + (area->pages << PAGE_WIDTH)))
 			return area;
 		
@@ -499,5 +501,4 @@
 	 * Second, locate the left neighbour and test its last record.
 	 * Because of its position in the B+tree, it must have base < va.
-	 *
 	 */
 	btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
@@ -507,5 +508,5 @@
 		mutex_lock(&area->lock);
 		
-		if (va < area->base + area->pages * PAGE_SIZE)
+		if (va < area->base + (area->pages << PAGE_WIDTH))
 			return area;
 		
@@ -534,5 +535,4 @@
 	/*
 	 * Locate the area.
-	 *
 	 */
 	as_area_t *area = find_area_and_lock(as, address);
@@ -546,5 +546,4 @@
 		 * Remapping of address space areas associated
 		 * with memory mapped devices is not supported.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -557,5 +556,4 @@
 		 * Remapping of shared address space areas
 		 * is not supported.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -568,5 +566,4 @@
 		/*
 		 * Zero size address space areas are not allowed.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -576,10 +573,9 @@
 	
 	if (pages < area->pages) {
-		uintptr_t start_free = area->base + pages * PAGE_SIZE;
+		uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
 		
 		/*
 		 * Shrinking the area.
 		 * No need to check for overlaps.
-		 *
 		 */
 		
@@ -588,8 +584,7 @@
 		/*
 		 * Start TLB shootdown sequence.
-		 *
 		 */
 		ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
-		    area->base + pages * PAGE_SIZE, area->pages - pages);
+		    area->base + (pages << PAGE_WIDTH), area->pages - pages);
 		
 		/*
@@ -599,5 +594,4 @@
 		 * is also the right way to remove part of the used_space
 		 * B+tree leaf list.
-		 *
 		 */
 		bool cond = true;
@@ -615,13 +609,12 @@
 				size_t i = 0;
 				
-				if (overlaps(ptr, size * PAGE_SIZE, area->base,
-				    pages * PAGE_SIZE)) {
+				if (overlaps(ptr, size << PAGE_WIDTH, area->base,
+				    pages << PAGE_WIDTH)) {
 					
-					if (ptr + size * PAGE_SIZE <= start_free) {
+					if (ptr + (size << PAGE_WIDTH) <= start_free) {
 						/*
 						 * The whole interval fits
 						 * completely in the resized
 						 * address space area.
-						 *
 						 */
 						break;
@@ -632,5 +625,4 @@
 					 * to b and c overlaps with the resized
 					 * address space area.
-					 *
 					 */
 					
@@ -652,5 +644,5 @@
 				for (; i < size; i++) {
 					pte_t *pte = page_mapping_find(as, ptr +
-					    i * PAGE_SIZE);
+					    (i << PAGE_WIDTH));
 					
 					ASSERT(pte);
@@ -661,10 +653,10 @@
 					    (area->backend->frame_free)) {
 						area->backend->frame_free(area,
-						    ptr + i * PAGE_SIZE,
+						    ptr + (i << PAGE_WIDTH),
 						    PTE_GET_FRAME(pte));
 					}
 					
 					page_mapping_remove(as, ptr +
-					    i * PAGE_SIZE);
+					    (i << PAGE_WIDTH));
 				}
 			}
@@ -673,16 +665,14 @@
 		/*
 		 * Finish TLB shootdown sequence.
-		 *
-		 */
-		
-		tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
+		 */
+		
+		tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
 		    area->pages - pages);
 		
 		/*
 		 * Invalidate software translation caches (e.g. TSB on sparc64).
-		 *
 		 */
 		as_invalidate_translation_cache(as, area->base +
-		    pages * PAGE_SIZE, area->pages - pages);
+		    (pages << PAGE_WIDTH), area->pages - pages);
 		tlb_shootdown_finalize(ipl);
 		
@@ -692,8 +682,6 @@
 		 * Growing the area.
 		 * Check for overlaps with other address space areas.
-		 *
-		 */
-		if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
-		    area)) {
+		 */
+		if (!check_area_conflicts(as, address, pages, area)) {
 			mutex_unlock(&area->lock);
 			mutex_unlock(&as->lock);
@@ -794,5 +782,6 @@
 			
 			for (size = 0; size < (size_t) node->value[i]; size++) {
-				pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
+				pte_t *pte =
+				    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
 				
 				ASSERT(pte);
@@ -803,8 +792,8 @@
 				    (area->backend->frame_free)) {
 					area->backend->frame_free(area,
-					    ptr + size * PAGE_SIZE, PTE_GET_FRAME(pte));
+					    ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
 				}
 				
-				page_mapping_remove(as, ptr + size * PAGE_SIZE);
+				page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
 			}
 		}
@@ -813,5 +802,4 @@
 	/*
 	 * Finish TLB shootdown sequence.
-	 *
 	 */
 	
@@ -821,5 +809,4 @@
 	 * Invalidate potential software translation caches (e.g. TSB on
 	 * sparc64).
-	 *
 	 */
 	as_invalidate_translation_cache(as, area->base, area->pages);
@@ -839,5 +826,4 @@
 	/*
 	 * Remove the empty area from address space.
-	 *
 	 */
 	btree_remove(&as->as_area_btree, base, NULL);
@@ -881,5 +867,4 @@
 		/*
 		 * Could not find the source address space area.
-		 *
 		 */
 		mutex_unlock(&src_as->lock);
@@ -891,5 +876,4 @@
 		 * There is no backend or the backend does not
 		 * know how to share the area.
-		 *
 		 */
 		mutex_unlock(&src_area->lock);
@@ -898,5 +882,5 @@
 	}
 	
-	size_t src_size = src_area->pages * PAGE_SIZE;
+	size_t src_size = src_area->pages << PAGE_WIDTH;
 	unsigned int src_flags = src_area->flags;
 	mem_backend_t *src_backend = src_area->backend;
@@ -918,5 +902,4 @@
 	 * First, prepare the area for sharing.
 	 * Then it will be safe to unlock it.
-	 *
 	 */
 	share_info_t *sh_info = src_area->sh_info;
@@ -930,5 +913,4 @@
 		/*
 		 * Call the backend to setup sharing.
-		 *
 		 */
 		src_area->backend->share(src_area);
@@ -949,5 +931,4 @@
 	 * The flags of the source area are masked against dst_flags_mask
 	 * to support sharing in less privileged mode.
-	 *
 	 */
 	as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask, src_size,
@@ -966,5 +947,4 @@
 	 * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
 	 * attribute and set the sh_info.
-	 *
 	 */
 	mutex_lock(&dst_as->lock);
@@ -989,4 +969,6 @@
 NO_TRACE bool as_area_check_access(as_area_t *area, pf_access_t access)
 {
+	ASSERT(mutex_locked(&area->lock));
+	
 	int flagmap[] = {
 		[PF_ACCESS_READ] = AS_AREA_READ,
@@ -994,6 +976,4 @@
 		[PF_ACCESS_EXEC] = AS_AREA_EXEC
 	};
-
-	ASSERT(mutex_locked(&area->lock));
 	
 	if (!(area->flags & flagmap[access]))
@@ -1066,5 +1046,4 @@
 	/*
 	 * Compute total number of used pages in the used_space B+tree
-	 *
 	 */
 	size_t used_pages = 0;
@@ -1088,5 +1067,4 @@
 	/*
 	 * Start TLB shootdown sequence.
-	 *
 	 */
 	ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
@@ -1096,5 +1074,4 @@
 	 * Remove used pages from page tables and remember their frame
 	 * numbers.
-	 *
 	 */
 	size_t frame_idx = 0;
@@ -1111,5 +1088,6 @@
 			
 			for (size = 0; size < (size_t) node->value[i]; size++) {
-				pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
+				pte_t *pte =
+				    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
 				
 				ASSERT(pte);
@@ -1120,5 +1098,5 @@
 				
 				/* Remove old mapping */
-				page_mapping_remove(as, ptr + size * PAGE_SIZE);
+				page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
 			}
 		}
@@ -1127,5 +1105,4 @@
 	/*
 	 * Finish TLB shootdown sequence.
-	 *
 	 */
 	
@@ -1135,5 +1112,4 @@
 	 * Invalidate potential software translation caches (e.g. TSB on
 	 * sparc64).
-	 *
 	 */
 	as_invalidate_translation_cache(as, area->base, area->pages);
@@ -1168,5 +1144,5 @@
 				
 				/* Insert the new mapping */
-				page_mapping_insert(as, ptr + size * PAGE_SIZE,
+				page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
 				    old_frame[frame_idx++], page_flags);
 				
@@ -1217,5 +1193,4 @@
 		 * No area contained mapping for 'page'.
 		 * Signal page fault to low-level handler.
-		 *
 		 */
 		mutex_unlock(&AS->lock);
@@ -1237,5 +1212,4 @@
 		 * The address space area is not backed by any backend
 		 * or the backend cannot handle page faults.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -1249,5 +1223,4 @@
 	 * To avoid race condition between two page faults on the same address,
 	 * we need to make sure the mapping has not been already inserted.
-	 *
 	 */
 	pte_t *pte;
@@ -1267,5 +1240,4 @@
 	/*
 	 * Resort to the backend page fault handler.
-	 *
 	 */
 	if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
@@ -1322,5 +1294,4 @@
 		 * preemption is disabled. We should not be
 		 * holding any other lock.
-		 *
 		 */
 		(void) interrupts_enable();
@@ -1342,5 +1313,4 @@
 			 * list of inactive address spaces with assigned
 			 * ASID.
-			 *
 			 */
 			ASSERT(old_as->asid != ASID_INVALID);
@@ -1353,5 +1323,4 @@
 		 * Perform architecture-specific tasks when the address space
 		 * is being removed from the CPU.
-		 *
 		 */
 		as_deinstall_arch(old_as);
@@ -1360,5 +1329,4 @@
 	/*
 	 * Second, prepare the new address space.
-	 *
 	 */
 	if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
@@ -1376,5 +1344,4 @@
 	 * Perform architecture-specific steps.
 	 * (e.g. write ASID to hardware register etc.)
-	 *
 	 */
 	as_install_arch(new_as);
@@ -1395,5 +1362,5 @@
 {
 	ASSERT(mutex_locked(&area->lock));
-
+	
 	return area_flags_to_page_flags(area->flags);
 }
@@ -1499,5 +1466,5 @@
 	
 	if (src_area) {
-		size = src_area->pages * PAGE_SIZE;
+		size = src_area->pages << PAGE_WIDTH;
 		mutex_unlock(&src_area->lock);
 	} else
@@ -1516,8 +1483,8 @@
  * @param count Number of page to be marked.
  *
- * @return Zero on failure and non-zero on success.
- *
- */
-int used_space_insert(as_area_t *area, uintptr_t page, size_t count)
+ * @return False on failure or true on success.
+ *
+ */
+bool used_space_insert(as_area_t *area, uintptr_t page, size_t count)
 {
 	ASSERT(mutex_locked(&area->lock));
@@ -1530,12 +1497,11 @@
 		/*
 		 * We hit the beginning of some used space.
-		 *
-		 */
-		return 0;
+		 */
+		return false;
 	}
 	
 	if (!leaf->keys) {
 		btree_insert(&area->used_space, page, (void *) count, leaf);
-		return 1;
+		goto success;
 	}
 	
@@ -1551,54 +1517,49 @@
 		 * somewhere between the rightmost interval of
 		 * the left neigbour and the first interval of the leaf.
-		 *
 		 */
 		
 		if (page >= right_pg) {
 			/* Do nothing. */
-		} else if (overlaps(page, count * PAGE_SIZE, left_pg,
-		    left_cnt * PAGE_SIZE)) {
+		} else if (overlaps(page, count << PAGE_WIDTH, left_pg,
+		    left_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the left interval. */
-			return 0;
-		} else if (overlaps(page, count * PAGE_SIZE, right_pg,
-		    right_cnt * PAGE_SIZE)) {
+			return false;
+		} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
+		    right_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the right interval. */
-			return 0;
-		} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
-		    (page + count * PAGE_SIZE == right_pg)) {
+			return false;
+		} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
+		    (page + (count << PAGE_WIDTH) == right_pg)) {
 			/*
 			 * The interval can be added by merging the two already
 			 * present intervals.
-			 *
 			 */
 			node->value[node->keys - 1] += count + right_cnt;
 			btree_remove(&area->used_space, right_pg, leaf);
-			return 1;
-		} else if (page == left_pg + left_cnt * PAGE_SIZE) {
+			goto success;
+		} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
 			/*
 			 * The interval can be added by simply growing the left
 			 * interval.
-			 *
 			 */
 			node->value[node->keys - 1] += count;
-			return 1;
-		} else if (page + count * PAGE_SIZE == right_pg) {
+			goto success;
+		} else if (page + (count << PAGE_WIDTH) == right_pg) {
 			/*
 			 * The interval can be addded by simply moving base of
 			 * the right interval down and increasing its size
 			 * accordingly.
-			 *
 			 */
 			leaf->value[0] += count;
 			leaf->key[0] = page;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval is between both neigbouring intervals,
 			 * but cannot be merged with any of them.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	} else if (page < leaf->key[0]) {
@@ -1609,30 +1570,27 @@
 		 * Investigate the border case in which the left neighbour does
 		 * not exist but the interval fits from the left.
-		 *
-		 */
-		
-		if (overlaps(page, count * PAGE_SIZE, right_pg,
-		    right_cnt * PAGE_SIZE)) {
+		 */
+		
+		if (overlaps(page, count << PAGE_WIDTH, right_pg,
+		    right_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the right interval. */
-			return 0;
-		} else if (page + count * PAGE_SIZE == right_pg) {
+			return false;
+		} else if (page + (count << PAGE_WIDTH) == right_pg) {
 			/*
 			 * The interval can be added by moving the base of the
 			 * right interval down and increasing its size
 			 * accordingly.
-			 *
 			 */
 			leaf->key[0] = page;
 			leaf->value[0] += count;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval doesn't adjoin with the right interval.
 			 * It must be added individually.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	}
@@ -1649,54 +1607,49 @@
 		 * somewhere between the leftmost interval of
 		 * the right neigbour and the last interval of the leaf.
-		 *
 		 */
 		
 		if (page < left_pg) {
 			/* Do nothing. */
-		} else if (overlaps(page, count * PAGE_SIZE, left_pg,
-		    left_cnt * PAGE_SIZE)) {
+		} else if (overlaps(page, count << PAGE_WIDTH, left_pg,
+		    left_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the left interval. */
-			return 0;
-		} else if (overlaps(page, count * PAGE_SIZE, right_pg,
-		    right_cnt * PAGE_SIZE)) {
+			return false;
+		} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
+		    right_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the right interval. */
-			return 0;
-		} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
-		    (page + count * PAGE_SIZE == right_pg)) {
+			return false;
+		} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
+		    (page + (count << PAGE_WIDTH) == right_pg)) {
 			/*
 			 * The interval can be added by merging the two already
 			 * present intervals.
-			 *
 			 */
 			leaf->value[leaf->keys - 1] += count + right_cnt;
 			btree_remove(&area->used_space, right_pg, node);
-			return 1;
-		} else if (page == left_pg + left_cnt * PAGE_SIZE) {
+			goto success;
+		} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
 			/*
 			 * The interval can be added by simply growing the left
 			 * interval.
-			 *
 			 */
-			leaf->value[leaf->keys - 1] +=  count;
-			return 1;
-		} else if (page + count * PAGE_SIZE == right_pg) {
+			leaf->value[leaf->keys - 1] += count;
+			goto success;
+		} else if (page + (count << PAGE_WIDTH) == right_pg) {
 			/*
 			 * The interval can be addded by simply moving base of
 			 * the right interval down and increasing its size
 			 * accordingly.
-			 *
 			 */
 			node->value[0] += count;
 			node->key[0] = page;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval is between both neigbouring intervals,
 			 * but cannot be merged with any of them.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	} else if (page >= leaf->key[leaf->keys - 1]) {
@@ -1707,28 +1660,25 @@
 		 * Investigate the border case in which the right neighbour
 		 * does not exist but the interval fits from the right.
-		 *
-		 */
-		
-		if (overlaps(page, count * PAGE_SIZE, left_pg,
-		    left_cnt * PAGE_SIZE)) {
+		 */
+		
+		if (overlaps(page, count << PAGE_WIDTH, left_pg,
+		    left_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the left interval. */
-			return 0;
-		} else if (left_pg + left_cnt * PAGE_SIZE == page) {
+			return false;
+		} else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
 			/*
 			 * The interval can be added by growing the left
 			 * interval.
-			 *
 			 */
 			leaf->value[leaf->keys - 1] += count;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval doesn't adjoin with the left interval.
 			 * It must be added individually.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	}
@@ -1738,5 +1688,4 @@
 	 * only between two other intervals of the leaf. The two border cases
 	 * were already resolved.
-	 *
 	 */
 	btree_key_t i;
@@ -1750,51 +1699,45 @@
 			/*
 			 * The interval fits between left_pg and right_pg.
-			 *
 			 */
 			
-			if (overlaps(page, count * PAGE_SIZE, left_pg,
-			    left_cnt * PAGE_SIZE)) {
+			if (overlaps(page, count << PAGE_WIDTH, left_pg,
+			    left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval intersects with the left
 				 * interval.
-				 *
 				 */
-				return 0;
-			} else if (overlaps(page, count * PAGE_SIZE, right_pg,
-			    right_cnt * PAGE_SIZE)) {
+				return false;
+			} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
+			    right_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval intersects with the right
 				 * interval.
-				 *
 				 */
-				return 0;
-			} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
-			    (page + count * PAGE_SIZE == right_pg)) {
+				return false;
+			} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
+			    (page + (count << PAGE_WIDTH) == right_pg)) {
 				/*
 				 * The interval can be added by merging the two
 				 * already present intervals.
-				 *
 				 */
 				leaf->value[i - 1] += count + right_cnt;
 				btree_remove(&area->used_space, right_pg, leaf);
-				return 1;
-			} else if (page == left_pg + left_cnt * PAGE_SIZE) {
+				goto success;
+			} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval can be added by simply growing
 				 * the left interval.
-				 *
 				 */
 				leaf->value[i - 1] += count;
-				return 1;
-			} else if (page + count * PAGE_SIZE == right_pg) {
+				goto success;
+			} else if (page + (count << PAGE_WIDTH) == right_pg) {
 				/*
 				 * The interval can be addded by simply moving
 				 * base of the right interval down and
 				 * increasing its size accordingly.
-				 *
 				 */
 				leaf->value[i] += count;
 				leaf->key[i] = page;
-				return 1;
+				goto success;
 			} else {
 				/*
@@ -1802,9 +1745,8 @@
 				 * intervals, but cannot be merged with any of
 				 * them.
-				 *
 				 */
 				btree_insert(&area->used_space, page,
 				    (void *) count, leaf);
-				return 1;
+				goto success;
 			}
 		}
@@ -1813,4 +1755,8 @@
 	panic("Inconsistency detected while adding %zu pages of used "
 	    "space at %p.", count, (void *) page);
+	
+success:
+	area->resident += count;
+	return true;
 }
 
@@ -1823,8 +1769,8 @@
  * @param count Number of page to be marked.
  *
- * @return Zero on failure and non-zero on success.
- *
- */
-int used_space_remove(as_area_t *area, uintptr_t page, size_t count)
+ * @return False on failure or true on success.
+ *
+ */
+bool used_space_remove(as_area_t *area, uintptr_t page, size_t count)
 {
 	ASSERT(mutex_locked(&area->lock));
@@ -1837,25 +1783,24 @@
 		/*
 		 * We are lucky, page is the beginning of some interval.
-		 *
 		 */
 		if (count > pages) {
-			return 0;
+			return false;
 		} else if (count == pages) {
 			btree_remove(&area->used_space, page, leaf);
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * Find the respective interval.
 			 * Decrease its size and relocate its start address.
-			 *
 			 */
 			btree_key_t i;
 			for (i = 0; i < leaf->keys; i++) {
 				if (leaf->key[i] == page) {
-					leaf->key[i] += count * PAGE_SIZE;
+					leaf->key[i] += count << PAGE_WIDTH;
 					leaf->value[i] -= count;
-					return 1;
+					goto success;
 				}
 			}
+			
 			goto error;
 		}
@@ -1867,8 +1812,8 @@
 		size_t left_cnt = (size_t) node->value[node->keys - 1];
 		
-		if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
-		    count * PAGE_SIZE)) {
-			if (page + count * PAGE_SIZE ==
-			    left_pg + left_cnt * PAGE_SIZE) {
+		if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
+		    count << PAGE_WIDTH)) {
+			if (page + (count << PAGE_WIDTH) ==
+			    left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1876,10 +1821,9 @@
 				 * removed by updating the size of the bigger
 				 * interval.
-				 *
 				 */
 				node->value[node->keys - 1] -= count;
-				return 1;
-			} else if (page + count * PAGE_SIZE <
-			    left_pg + left_cnt*PAGE_SIZE) {
+				goto success;
+			} else if (page + (count << PAGE_WIDTH) <
+			    left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1888,17 +1832,17 @@
 				 * the original interval and also inserting a
 				 * new interval.
-				 *
 				 */
-				size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
-				    (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
+				size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
+				    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
 				node->value[node->keys - 1] -= count + new_cnt;
 				btree_insert(&area->used_space, page +
-				    count * PAGE_SIZE, (void *) new_cnt, leaf);
-				return 1;
+				    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
+				goto success;
 			}
 		}
-		return 0;
+		
+		return false;
 	} else if (page < leaf->key[0])
-		return 0;
+		return false;
 	
 	if (page > leaf->key[leaf->keys - 1]) {
@@ -1906,18 +1850,17 @@
 		size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
 		
-		if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
-		    count * PAGE_SIZE)) {
-			if (page + count * PAGE_SIZE ==
-			    left_pg + left_cnt * PAGE_SIZE) {
+		if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
+		    count << PAGE_WIDTH)) {
+			if (page + (count << PAGE_WIDTH) ==
+			    left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
 				 * interval of the leaf and can be removed by
 				 * updating the size of the bigger interval.
-				 *
 				 */
 				leaf->value[leaf->keys - 1] -= count;
-				return 1;
-			} else if (page + count * PAGE_SIZE < left_pg +
-			    left_cnt * PAGE_SIZE) {
+				goto success;
+			} else if (page + (count << PAGE_WIDTH) < left_pg +
+			    (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1926,20 +1869,20 @@
 				 * original interval and also inserting a new
 				 * interval.
-				 *
 				 */
-				size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
-				    (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
+				size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
+				    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
 				leaf->value[leaf->keys - 1] -= count + new_cnt;
 				btree_insert(&area->used_space, page +
-				    count * PAGE_SIZE, (void *) new_cnt, leaf);
-				return 1;
+				    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
+				goto success;
 			}
 		}
-		return 0;
+		
+		return false;
 	}
 	
 	/*
 	 * The border cases have been already resolved.
-	 * Now the interval can be only between intervals of the leaf. 
+	 * Now the interval can be only between intervals of the leaf.
 	 */
 	btree_key_t i;
@@ -1953,8 +1896,8 @@
 			 * to (i - 1) and i.
 			 */
-			if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
-			    count * PAGE_SIZE)) {
-				if (page + count * PAGE_SIZE ==
-				    left_pg + left_cnt*PAGE_SIZE) {
+			if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
+			    count << PAGE_WIDTH)) {
+				if (page + (count << PAGE_WIDTH) ==
+				    left_pg + (left_cnt << PAGE_WIDTH)) {
 					/*
 					 * The interval is contained in the
@@ -1962,10 +1905,9 @@
 					 * be removed by updating the size of
 					 * the bigger interval.
-					 *
 					 */
 					leaf->value[i - 1] -= count;
-					return 1;
-				} else if (page + count * PAGE_SIZE <
-				    left_pg + left_cnt * PAGE_SIZE) {
+					goto success;
+				} else if (page + (count << PAGE_WIDTH) <
+				    left_pg + (left_cnt << PAGE_WIDTH)) {
 					/*
 					 * The interval is contained in the
@@ -1976,15 +1918,16 @@
 					 */
 					size_t new_cnt = ((left_pg +
-					    left_cnt * PAGE_SIZE) -
-					    (page + count * PAGE_SIZE)) >>
+					    (left_cnt << PAGE_WIDTH)) -
+					    (page + (count << PAGE_WIDTH))) >>
 					    PAGE_WIDTH;
 					leaf->value[i - 1] -= count + new_cnt;
 					btree_insert(&area->used_space, page +
-					    count * PAGE_SIZE, (void *) new_cnt,
+					    (count << PAGE_WIDTH), (void *) new_cnt,
 					    leaf);
-					return 1;
+					goto success;
 				}
 			}
-			return 0;
+			
+			return false;
 		}
 	}
@@ -1993,4 +1936,8 @@
 	panic("Inconsistency detected while removing %zu pages of used "
 	    "space from %p.", count, (void *) page);
+	
+success:
+	area->resident -= count;
+	return true;
 }
 
@@ -2027,4 +1974,70 @@
 }
 
+/** Return pointer to unmapped address space area
+ *
+ * @param base Lowest address bound.
+ * @param size Requested size of the allocation.
+ *
+ * @return Pointer to the beginning of unmapped address space area.
+ *
+ */
+sysarg_t sys_as_get_unmapped_area(uintptr_t base, size_t size)
+{
+	if (size == 0)
+		return 0;
+	
+	/*
+	 * Make sure we allocate from page-aligned
+	 * address. Check for possible overflow in
+	 * each step.
+	 */
+	
+	size_t pages = SIZE2FRAMES(size);
+	uintptr_t ret = 0;
+	
+	/*
+	 * Find the lowest unmapped address aligned on the sz
+	 * boundary, not smaller than base and of the required size.
+	 */
+	
+	mutex_lock(&AS->lock);
+	
+	/* First check the base address itself */
+	uintptr_t addr = ALIGN_UP(base, PAGE_SIZE);
+	if ((addr >= base) &&
+	    (check_area_conflicts(AS, addr, pages, NULL)))
+		ret = addr;
+	
+	/* Eventually check the addresses behind each area */
+	link_t *cur;
+	for (cur = AS->as_area_btree.leaf_head.next;
+	    (ret == 0) && (cur != &AS->as_area_btree.leaf_head);
+	    cur = cur->next) {
+		btree_node_t *node =
+		    list_get_instance(cur, btree_node_t, leaf_link);
+		
+		btree_key_t i;
+		for (i = 0; (ret == 0) && (i < node->keys); i++) {
+			as_area_t *area = (as_area_t *) node->value[i];
+			
+			mutex_lock(&area->lock);
+			
+			uintptr_t addr =
+			    ALIGN_UP(area->base + (area->pages << PAGE_WIDTH),
+			    PAGE_SIZE);
+			
+			if ((addr >= base) && (addr >= area->base) &&
+			    (check_area_conflicts(AS, addr, pages, area)))
+				ret = addr;
+			
+			mutex_unlock(&area->lock);
+		}
+	}
+	
+	mutex_unlock(&AS->lock);
+	
+	return (sysarg_t) ret;
+}
+
 /** Get list of adress space areas.
  *
@@ -2093,5 +2106,5 @@
 	mutex_lock(&as->lock);
 	
-	/* print out info about address space areas */
+	/* Print out info about address space areas */
 	link_t *cur;
 	for (cur = as->as_area_btree.leaf_head.next;
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/generic/src/proc/program.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -171,4 +171,5 @@
 	void *loader = program_loader;
 	if (!loader) {
+		as_destroy(as);
 		printf("Cannot spawn loader as none was registered\n");
 		return ENOENT;
@@ -179,4 +180,5 @@
 	if (rc != EE_OK) {
 		as_destroy(as);
+		printf("Cannot spawn loader (%s)\n", elf_error(rc));
 		return ENOENT;
 	}
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/generic/src/syscall/syscall.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -143,4 +143,5 @@
 	(syshandler_t) sys_as_area_change_flags,
 	(syshandler_t) sys_as_area_destroy,
+	(syshandler_t) sys_as_get_unmapped_area,
 	
 	/* IPC related syscalls. */
Index: kernel/generic/src/sysinfo/stats.c
===================================================================
--- kernel/generic/src/sysinfo/stats.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ kernel/generic/src/sysinfo/stats.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -160,69 +160,17 @@
 static size_t get_task_virtmem(as_t *as)
 {
-	size_t result = 0;
-
 	/*
-	 * We are holding some spinlocks here and therefore are not allowed to
-	 * block. Only attempt to lock the address space and address space area
-	 * mutexes conditionally. If it is not possible to lock either object,
-	 * allow the statistics to be inexact by skipping the respective object.
-	 *
-	 * Note that it may be infinitely better to let the address space
-	 * management code compute these statistics as it proceeds instead of
-	 * having them calculated over and over again here.
+	 * We are holding spinlocks here and therefore are not allowed to
+	 * block. Only attempt to lock the address space and address space
+	 * area mutexes conditionally. If it is not possible to lock either
+	 * object, return inexact statistics by skipping the respective object.
 	 */
-
+	
 	if (SYNCH_FAILED(mutex_trylock(&as->lock)))
-		return result * PAGE_SIZE;
+		return 0;
+	
+	size_t pages = 0;
 	
 	/* Walk the B+ tree and count pages */
-	link_t *cur;
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
-		btree_node_t *node =
-		    list_get_instance(cur, btree_node_t, leaf_link);
-		
-		unsigned int i;
-		for (i = 0; i < node->keys; i++) {
-			as_area_t *area = node->value[i];
-			
-			if (SYNCH_FAILED(mutex_trylock(&area->lock)))
-				continue;
-			result += area->pages;
-			mutex_unlock(&area->lock);
-		}
-	}
-	
-	mutex_unlock(&as->lock);
-	
-	return result * PAGE_SIZE;
-}
-
-/** Get the resident (used) size of a virtual address space
- *
- * @param as Address space.
- *
- * @return Size of the resident (used) virtual address space (bytes).
- *
- */
-static size_t get_task_resmem(as_t *as)
-{
-	size_t result = 0;
-	
-	/*
-	 * We are holding some spinlocks here and therefore are not allowed to
-	 * block. Only attempt to lock the address space and address space area
-	 * mutexes conditionally. If it is not possible to lock either object,
-	 * allow the statistics to be inexact by skipping the respective object.
-	 *
-	 * Note that it may be infinitely better to let the address space
-	 * management code compute these statistics as it proceeds instead of
-	 * having them calculated over and over again here.
-	 */
-	
-	if (SYNCH_FAILED(mutex_trylock(&as->lock)))
-		return result * PAGE_SIZE;
-	
-	/* Walk the B+ tree of AS areas */
 	link_t *cur;
 	for (cur = as->as_area_btree.leaf_head.next;
@@ -238,16 +186,5 @@
 				continue;
 			
-			/* Walk the B+ tree of resident pages */
-			link_t *rcur;
-			for (rcur = area->used_space.leaf_head.next;
-			    rcur != &area->used_space.leaf_head; rcur = rcur->next) {
-				btree_node_t *rnode =
-				    list_get_instance(rcur, btree_node_t, leaf_link);
-				
-				unsigned int j;
-				for (j = 0; j < rnode->keys; j++)
-					result += (size_t) rnode->value[i];
-			}
-			
+			pages += area->pages;
 			mutex_unlock(&area->lock);
 		}
@@ -256,5 +193,50 @@
 	mutex_unlock(&as->lock);
 	
-	return result * PAGE_SIZE;
+	return (pages << PAGE_WIDTH);
+}
+
+/** Get the resident (used) size of a virtual address space
+ *
+ * @param as Address space.
+ *
+ * @return Size of the resident (used) virtual address space (bytes).
+ *
+ */
+static size_t get_task_resmem(as_t *as)
+{
+	/*
+	 * We are holding spinlocks here and therefore are not allowed to
+	 * block. Only attempt to lock the address space and address space
+	 * area mutexes conditionally. If it is not possible to lock either
+	 * object, return inexact statistics by skipping the respective object.
+	 */
+	
+	if (SYNCH_FAILED(mutex_trylock(&as->lock)))
+		return 0;
+	
+	size_t pages = 0;
+	
+	/* Walk the B+ tree and count pages */
+	link_t *cur;
+	for (cur = as->as_area_btree.leaf_head.next;
+	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+		btree_node_t *node =
+		    list_get_instance(cur, btree_node_t, leaf_link);
+		
+		unsigned int i;
+		for (i = 0; i < node->keys; i++) {
+			as_area_t *area = node->value[i];
+			
+			if (SYNCH_FAILED(mutex_trylock(&area->lock)))
+				continue;
+			
+			pages += area->resident;
+			mutex_unlock(&area->lock);
+		}
+	}
+	
+	mutex_unlock(&as->lock);
+	
+	return (pages << PAGE_WIDTH);
 }
 
Index: tools/toolchain.sh
===================================================================
--- tools/toolchain.sh	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ tools/toolchain.sh	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -69,4 +69,8 @@
 	echo " sparc64    SPARC V9"
 	echo " all        build all targets"
+	echo
+	echo "The toolchain will be installed to the directory specified by"
+	echo "the CROSS_PREFIX environment variable. If the variable is not"
+	echo "defined, /usr/local will be used by default."
 	echo
 	
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/Makefile.common	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -135,4 +135,11 @@
 endif
 
+ifeq ($(CONFIG_LINE_DEBUG),y)
+	GCC_CFLAGS += -g
+	ICC_CFLAGS += -g
+	SUNCC_CFLAGS += -g
+	CLANG_CFLAGS += -g
+endif
+
 ## Setup platform configuration
 #
@@ -210,2 +217,8 @@
 	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > $@ 2> /dev/null
 	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
+
+##
+# This explicit dependecy of the output binary on the object files seems to be
+# necessary to prevent parallel build failures (GNU make bug #26893 ???).
+$(OUTPUT): $(OBJECTS)
+
Index: uspace/app/netstart/self_test.c
===================================================================
--- uspace/app/netstart/self_test.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
+++ uspace/app/netstart/self_test.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ * @{
+ */
+
+/** @file
+ * Networking self-tests implementation.
+ *
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+
+#include <net_checksum.h>
+#include <adt/int_map.h>
+#include <adt/char_map.h>
+#include <adt/generic_char_map.h>
+#include <adt/measured_strings.h>
+#include <adt/dynamic_fifo.h>
+
+#include "self_test.h"
+
+/** Test the statement, compare the result and evaluate.
+ *
+ * @param[in] statement The statement to test.
+ * @param[in] result    The expected result.
+ *
+ */
+#define TEST(statement, result) \
+	do { \
+		printf("\n\t%s == %s", #statement, #result); \
+		if ((statement) != (result)) { \
+			printf("\tfailed\n"); \
+			fprintf(stderr, "\nNetwork self-test failed\n"); \
+			return EINVAL; \
+		} else \
+			printf("\tOK"); \
+	} while (0)
+
+#define XMALLOC(var, type) \
+	do { \
+		(var) = (type *) malloc(sizeof(type)); \
+		if ((var) == NULL) { \
+			fprintf(stderr, "\nMemory allocation error\n"); \
+			return ENOMEM; \
+		} \
+	} while (0)
+
+GENERIC_CHAR_MAP_DECLARE(int_char_map, int);
+GENERIC_CHAR_MAP_IMPLEMENT(int_char_map, int);
+
+GENERIC_FIELD_DECLARE(int_field, int);
+GENERIC_FIELD_IMPLEMENT(int_field, int);
+
+INT_MAP_DECLARE(int_map, int);
+INT_MAP_IMPLEMENT(int_map, int);
+
+/** Self-test start function.
+ *
+ * Run all self-tests.
+ *
+ * @returns EOK on success.
+ * @returns The first error occurred.
+ *
+ */
+int self_test(void)
+{
+	printf("Running networking self-tests\n");
+	
+	printf("\nChar map test");
+	char_map_t cm;
+	
+	TEST(char_map_update(&cm, "ucho", 0, 3), EINVAL);
+	TEST(char_map_initialize(&cm), EOK);
+	TEST(char_map_exclude(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_add(&cm, "bla", 0, 1), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 1);
+	TEST(char_map_add(&cm, "bla", 0, 10), EEXISTS);
+	TEST(char_map_update(&cm, "bla", 0, 2), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 2);
+	TEST(char_map_update(&cm, "ucho", 0, 2), EOK);
+	TEST(char_map_exclude(&cm, "bla", 0), 2);
+	TEST(char_map_exclude(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "ucho", 0), 2);
+	TEST(char_map_update(&cm, "ucho", 0, 3), EOK);
+	TEST(char_map_find(&cm, "ucho", 0), 3);
+	TEST(char_map_add(&cm, "blabla", 0, 5), EOK);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "bla", 0, 6), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 6);
+	TEST(char_map_exclude(&cm, "bla", 0), 6);
+	TEST(char_map_find(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "auto", 0, 7), EOK);
+	TEST(char_map_find(&cm, "auto", 0), 7);
+	TEST(char_map_add(&cm, "kara", 0, 8), EOK);
+	TEST(char_map_find(&cm, "kara", 0), 8);
+	TEST(char_map_add(&cm, "nic", 0, 9), EOK);
+	TEST(char_map_find(&cm, "nic", 0), 9);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "micnicnic", 5, 9), EOK);
+	TEST(char_map_find(&cm, "micni", 0), 9);
+	TEST(char_map_find(&cm, "micnicn", 5), 9);
+	TEST(char_map_add(&cm, "\x10\x0\x2\x2", 4, 15), EOK);
+	TEST(char_map_find(&cm, "\x10\x0\x2\x2", 4), 15);
+	
+	TEST((char_map_destroy(&cm), EOK), EOK);
+	TEST(char_map_update(&cm, "ucho", 0, 3), EINVAL);
+	
+	printf("\nCRC computation test");
+	uint32_t value;
+	
+	TEST(value = ~compute_crc32(~0, "123456789", 8 * 9), 0xcbf43926);
+	TEST(value = ~compute_crc32(~0, "1", 8), 0x83dcefb7);
+	TEST(value = ~compute_crc32(~0, "12", 8 * 2), 0x4f5344cd);
+	TEST(value = ~compute_crc32(~0, "123", 8 * 3), 0x884863d2);
+	TEST(value = ~compute_crc32(~0, "1234", 8 * 4), 0x9be3e0a3);
+	TEST(value = ~compute_crc32(~0, "12345678", 8 * 8), 0x9ae0daaf);
+	TEST(value = ~compute_crc32(~0, "ahoj pane", 8 * 9), 0x5fc3d706);
+	
+	printf("\nDynamic fifo test");
+	dyn_fifo_t fifo;
+	
+	TEST(dyn_fifo_push(&fifo, 1, 0), EINVAL);
+	TEST(dyn_fifo_initialize(&fifo, 1), EOK);
+	TEST(dyn_fifo_push(&fifo, 1, 0), EOK);
+	TEST(dyn_fifo_pop(&fifo), 1);
+	TEST(dyn_fifo_pop(&fifo), ENOENT);
+	TEST(dyn_fifo_push(&fifo, 2, 1), EOK);
+	TEST(dyn_fifo_push(&fifo, 3, 1), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 3, 0), EOK);
+	TEST(dyn_fifo_pop(&fifo), 2);
+	TEST(dyn_fifo_pop(&fifo), 3);
+	TEST(dyn_fifo_push(&fifo, 4, 2), EOK);
+	TEST(dyn_fifo_push(&fifo, 5, 2), EOK);
+	TEST(dyn_fifo_push(&fifo, 6, 2), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 6, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 7, 5), EOK);
+	TEST(dyn_fifo_pop(&fifo), 4);
+	TEST(dyn_fifo_pop(&fifo), 5);
+	TEST(dyn_fifo_push(&fifo, 8, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 9, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 10, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 11, 6), EOK);
+	TEST(dyn_fifo_pop(&fifo), 6);
+	TEST(dyn_fifo_pop(&fifo), 7);
+	TEST(dyn_fifo_push(&fifo, 12, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 13, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 14, 6), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 14, 8), EOK);
+	TEST(dyn_fifo_pop(&fifo), 8);
+	TEST(dyn_fifo_pop(&fifo), 9);
+	TEST(dyn_fifo_pop(&fifo), 10);
+	TEST(dyn_fifo_pop(&fifo), 11);
+	TEST(dyn_fifo_pop(&fifo), 12);
+	TEST(dyn_fifo_pop(&fifo), 13);
+	TEST(dyn_fifo_pop(&fifo), 14);
+	TEST(dyn_fifo_destroy(&fifo), EOK);
+	TEST(dyn_fifo_push(&fifo, 1, 0), EINVAL);
+	
+	printf("\nGeneric char map test");
+	
+	int *x;
+	int *y;
+	int *z;
+	int *u;
+	int *v;
+	int *w;
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_char_map_t icm;
+	icm.magic = 0;
+	
+	TEST(int_char_map_add(&icm, "ucho", 0, z), EINVAL);
+	TEST(int_char_map_initialize(&icm), EOK);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), NULL);
+	TEST(int_char_map_add(&icm, "bla", 0, x), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), x);
+	TEST(int_char_map_add(&icm, "bla", 0, y), EEXISTS);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_add(&icm, "blabla", 0, v), EOK);
+	TEST(int_char_map_find(&icm, "blabla", 0), v);
+	TEST(int_char_map_add(&icm, "bla", 0, w), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), w);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), NULL);
+	TEST(int_char_map_find(&icm, "blabla", 0), v);
+	TEST(int_char_map_add(&icm, "auto", 0, u), EOK);
+	TEST(int_char_map_find(&icm, "auto", 0), u);
+	TEST((int_char_map_destroy(&icm), EOK), EOK);
+	TEST(int_char_map_add(&icm, "ucho", 0, z), EINVAL);
+	
+	printf("\nGeneric field test");
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_field_t gf;
+	gf.magic = 0;
+	
+	TEST(int_field_add(&gf, x), EINVAL);
+	TEST(int_field_count(&gf), -1);
+	TEST(int_field_initialize(&gf), EOK);
+	TEST(int_field_count(&gf), 0);
+	TEST(int_field_get_index(&gf, 1), NULL);
+	TEST(int_field_add(&gf, x), 0);
+	TEST(int_field_get_index(&gf, 0), x);
+	TEST((int_field_exclude_index(&gf, 0), EOK), EOK);
+	TEST(int_field_get_index(&gf, 0), NULL);
+	TEST(int_field_add(&gf, y), 1);
+	TEST(int_field_get_index(&gf, 1), y);
+	TEST(int_field_add(&gf, z), 2);
+	TEST(int_field_get_index(&gf, 2), z);
+	TEST(int_field_get_index(&gf, 1), y);
+	TEST(int_field_count(&gf), 3);
+	TEST(int_field_add(&gf, u), 3);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST(int_field_add(&gf, v), 4);
+	TEST(int_field_get_index(&gf, 4), v);
+	TEST(int_field_add(&gf, w), 5);
+	TEST(int_field_get_index(&gf, 5), w);
+	TEST(int_field_count(&gf), 6);
+	TEST((int_field_exclude_index(&gf, 1), EOK), EOK);
+	TEST(int_field_get_index(&gf, 1), NULL);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST((int_field_exclude_index(&gf, 7), EOK), EOK);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST(int_field_get_index(&gf, 5), w);
+	TEST((int_field_exclude_index(&gf, 4), EOK), EOK);
+	TEST(int_field_get_index(&gf, 4), NULL);
+	TEST((int_field_destroy(&gf), EOK), EOK);
+	TEST(int_field_count(&gf), -1);
+	
+	printf("\nInt map test");
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_map_t im;
+	im.magic = 0;
+	
+	TEST(int_map_add(&im, 1, x), EINVAL);
+	TEST(int_map_count(&im), -1);
+	TEST(int_map_initialize(&im), EOK);
+	TEST(int_map_count(&im), 0);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_add(&im, 1, x), 0);
+	TEST(int_map_find(&im, 1), x);
+	TEST((int_map_exclude(&im, 1), EOK), EOK);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_add(&im, 1, y), 1);
+	TEST(int_map_find(&im, 1), y);
+	TEST(int_map_add(&im, 4, z), 2);
+	TEST(int_map_get_index(&im, 2), z);
+	TEST(int_map_find(&im, 4), z);
+	TEST(int_map_find(&im, 1), y);
+	TEST(int_map_count(&im), 3);
+	TEST(int_map_add(&im, 2, u), 3);
+	TEST(int_map_find(&im, 2), u);
+	TEST(int_map_add(&im, 3, v), 4);
+	TEST(int_map_find(&im, 3), v);
+	TEST(int_map_get_index(&im, 4), v);
+	TEST(int_map_add(&im, 6, w), 5);
+	TEST(int_map_find(&im, 6), w);
+	TEST(int_map_count(&im), 6);
+	TEST((int_map_exclude(&im, 1), EOK), EOK);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_find(&im, 2), u);
+	TEST((int_map_exclude(&im, 7), EOK), EOK);
+	TEST(int_map_find(&im, 2), u);
+	TEST(int_map_find(&im, 6), w);
+	TEST((int_map_exclude_index(&im, 4), EOK), EOK);
+	TEST(int_map_get_index(&im, 4), NULL);
+	TEST(int_map_find(&im, 3), NULL);
+	TEST((int_map_destroy(&im), EOK), EOK);
+	TEST(int_map_count(&im), -1);
+	
+	printf("\nMeasured strings test");
+	
+	measured_string_ref string =
+	    measured_string_create_bulk("I am a measured string!", 0);
+	printf("\n%x, %s at %x of %d\n", string, string->value, string->value,
+	    string->length);
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/app/netstart/self_test.h
===================================================================
--- uspace/app/netstart/self_test.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
+++ uspace/app/netstart/self_test.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ * @{
+ */
+
+#ifndef __SELF_TEST_H__
+#define __SELF_TEST_H__
+
+extern int self_test(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/app/taskdump/taskdump.c
===================================================================
--- uspace/app/taskdump/taskdump.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/app/taskdump/taskdump.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -406,4 +406,17 @@
 	}
 
+	rc = asprintf(&file_name, "/drv/%s/%s", app_name, app_name);
+	if (rc < 0) {
+		printf("Memory allocation failure.\n");
+		exit(1);
+	}
+
+	rc = symtab_load(file_name, &app_symtab);
+	if (rc == EOK) {
+		printf("Loaded symbol table from %s\n", file_name);
+		free(file_name);
+		return;
+	}
+
 	free(file_name);
 	printf("Failed autoloading symbol table.\n");
Index: uspace/app/tester/hw/misc/virtchar1.c
===================================================================
--- uspace/app/tester/hw/misc/virtchar1.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/app/tester/hw/misc/virtchar1.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -47,5 +47,5 @@
 #include "../../tester.h"
 
-#define DEVICE_PATH_NORMAL "/dev/devices/\\virt\\null"
+#define DEVICE_PATH_NORMAL "/dev/devices/\\virt\\null\\a"
 #define DEVICE_PATH_CLASSES "/dev/class/virt-null\\1"
 #define BUFFER_SIZE 64
Index: uspace/app/tester/hw/serial/serial1.c
===================================================================
--- uspace/app/tester/hw/serial/serial1.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/app/tester/hw/serial/serial1.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -74,5 +74,5 @@
 	
 	devman_handle_t handle;
-	res = devman_device_get_handle("/hw/pci0/00:01.0/com1", &handle,
+	res = devman_device_get_handle("/hw/pci0/00:01.0/com1/a", &handle,
 	    IPC_FLAG_BLOCKING);
 	if (res != EOK)
Index: uspace/drv/isa/isa.c
===================================================================
--- uspace/drv/isa/isa.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/isa/isa.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -43,4 +44,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <str_error.h>
 #include <ctype.h>
 #include <macros.h>
@@ -50,5 +52,5 @@
 #include <sys/stat.h>
 
-#include <driver.h>
+#include <ddf/driver.h>
 #include <ops/hw_res.h>
 
@@ -58,24 +60,25 @@
 
 #define NAME "isa"
-#define CHILD_DEV_CONF_PATH "/drv/isa/isa.dev"
+#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
+
+/** Obtain soft-state pointer from function node pointer */
+#define ISA_FUN(fnode) ((isa_fun_t *) ((fnode)->driver_data))
 
 #define ISA_MAX_HW_RES 4
 
-typedef struct isa_child_data {
+typedef struct isa_fun {
+	ddf_fun_t *fnode;
 	hw_resource_list_t hw_resources;
-} isa_child_data_t;
-
-static hw_resource_list_t *isa_get_child_resources(device_t *dev)
-{
-	isa_child_data_t *dev_data;
-
-	dev_data = (isa_child_data_t *)dev->driver_data;
-	if (dev_data == NULL)
-		return NULL;
-
-	return &dev_data->hw_resources;
-}
-
-static bool isa_enable_child_interrupt(device_t *dev)
+} isa_fun_t;
+
+static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
+{
+	isa_fun_t *fun = ISA_FUN(fnode);
+	assert(fun != NULL);
+
+	return &fun->hw_resources;
+}
+
+static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
 {
 	// TODO
@@ -84,12 +87,12 @@
 }
 
-static hw_res_ops_t isa_child_hw_res_ops = {
-	&isa_get_child_resources,
-	&isa_enable_child_interrupt
+static hw_res_ops_t isa_fun_hw_res_ops = {
+	&isa_get_fun_resources,
+	&isa_enable_fun_interrupt
 };
 
-static device_ops_t isa_child_dev_ops;
-
-static int isa_add_device(device_t *dev);
+static ddf_dev_ops_t isa_fun_ops;
+
+static int isa_add_device(ddf_dev_t *dev);
 
 /** The isa device driver's standard operations */
@@ -104,33 +107,22 @@
 };
 
-
-static isa_child_data_t *create_isa_child_data() 
-{
-	isa_child_data_t *data;
-
-	data = (isa_child_data_t *) malloc(sizeof(isa_child_data_t));
-	if (data != NULL)
-		memset(data, 0, sizeof(isa_child_data_t));
-
-	return data;
-}
-
-static device_t *create_isa_child_dev()
-{
-	device_t *dev = create_device();
-	if (dev == NULL)
+static isa_fun_t *isa_fun_create(ddf_dev_t *dev, const char *name)
+{
+	isa_fun_t *fun = calloc(1, sizeof(isa_fun_t));
+	if (fun == NULL)
 		return NULL;
 
-	isa_child_data_t *data = create_isa_child_data();
-	if (data == NULL) {
-		delete_device(dev);
+	ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL) {
+		free(fun);
 		return NULL;
 	}
 
-	dev->driver_data = data;
-	return dev;
-}
-
-static char *read_dev_conf(const char *conf_path)
+	fun->fnode = fnode;
+	fnode->driver_data = fun;
+	return fun;
+}
+
+static char *fun_conf_read(const char *conf_path)
 {
 	bool suc = false;
@@ -151,5 +143,5 @@
 	lseek(fd, 0, SEEK_SET);	
 	if (len == 0) {
-		printf(NAME ": read_dev_conf error: configuration file '%s' "
+		printf(NAME ": fun_conf_read error: configuration file '%s' "
 		    "is empty.\n", conf_path);
 		goto cleanup;
@@ -158,10 +150,10 @@
 	buf = malloc(len + 1);
 	if (buf == NULL) {
-		printf(NAME ": read_dev_conf error: memory allocation failed.\n");
+		printf(NAME ": fun_conf_read error: memory allocation failed.\n");
 		goto cleanup;
 	}
 
 	if (0 >= read(fd, buf, len)) {
-		printf(NAME ": read_dev_conf error: unable to read file '%s'.\n",
+		printf(NAME ": fun_conf_read error: unable to read file '%s'.\n",
 		    conf_path);
 		goto cleanup;
@@ -249,10 +241,8 @@
 }
 
-static void isa_child_set_irq(device_t *dev, int irq)
-{
-	isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
-
-	size_t count = data->hw_resources.count;
-	hw_resource_t *resources = data->hw_resources.resources;
+static void isa_fun_set_irq(isa_fun_t *fun, int irq)
+{
+	size_t count = fun->hw_resources.count;
+	hw_resource_t *resources = fun->hw_resources.resources;
 
 	if (count < ISA_MAX_HW_RES) {
@@ -260,16 +250,15 @@
 		resources[count].res.interrupt.irq = irq;
 
-		data->hw_resources.count++;
-
-		printf(NAME ": added irq 0x%x to device %s\n", irq, dev->name);
-	}
-}
-
-static void isa_child_set_io_range(device_t *dev, size_t addr, size_t len)
-{
-	isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
-
-	size_t count = data->hw_resources.count;
-	hw_resource_t *resources = data->hw_resources.resources;
+		fun->hw_resources.count++;
+
+		printf(NAME ": added irq 0x%x to function %s\n", irq,
+		    fun->fnode->name);
+	}
+}
+
+static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
+{
+	size_t count = fun->hw_resources.count;
+	hw_resource_t *resources = fun->hw_resources.resources;
 
 	if (count < ISA_MAX_HW_RES) {
@@ -279,30 +268,30 @@
 		resources[count].res.io_range.endianness = LITTLE_ENDIAN;
 
-		data->hw_resources.count++;
+		fun->hw_resources.count++;
 
 		printf(NAME ": added io range (addr=0x%x, size=0x%x) to "
-		    "device %s\n", (unsigned int) addr, (unsigned int) len,
-		    dev->name);
-	}
-}
-
-static void get_dev_irq(device_t *dev, char *val)
+		    "function %s\n", (unsigned int) addr, (unsigned int) len,
+		    fun->fnode->name);
+	}
+}
+
+static void fun_parse_irq(isa_fun_t *fun, char *val)
 {
 	int irq = 0;
 	char *end = NULL;
 
-	val = skip_spaces(val);	
+	val = skip_spaces(val);
 	irq = (int)strtol(val, &end, 0x10);
 
 	if (val != end)
-		isa_child_set_irq(dev, irq);
-}
-
-static void get_dev_io_range(device_t *dev, char *val)
+		isa_fun_set_irq(fun, irq);
+}
+
+static void fun_parse_io_range(isa_fun_t *fun, char *val)
 {
 	size_t addr, len;
 	char *end = NULL;
 
-	val = skip_spaces(val);	
+	val = skip_spaces(val);
 	addr = strtol(val, &end, 0x10);
 
@@ -310,5 +299,5 @@
 		return;
 
-	val = skip_spaces(end);	
+	val = skip_spaces(end);
 	len = strtol(val, &end, 0x10);
 
@@ -316,5 +305,5 @@
 		return;
 
-	isa_child_set_io_range(dev, addr, len);
+	isa_fun_set_io_range(fun, addr, len);
 }
 
@@ -331,45 +320,38 @@
 }
 
-static void get_dev_match_id(device_t *dev, char *val)
+static void fun_parse_match_id(isa_fun_t *fun, char *val)
 {
 	char *id = NULL;
 	int score = 0;
 	char *end = NULL;
-
-	val = skip_spaces(val);	
+	int rc;
+
+	val = skip_spaces(val);
 
 	score = (int)strtol(val, &end, 10);
 	if (val == end) {
 		printf(NAME " : error - could not read match score for "
-		    "device %s.\n", dev->name);
+		    "function %s.\n", fun->fnode->name);
 		return;
 	}
 
-	match_id_t *match_id = create_match_id();
-	if (match_id == NULL) {
-		printf(NAME " : failed to allocate match id for device %s.\n",
-		    dev->name);
-		return;
-	}
-
-	val = skip_spaces(end);	
+	val = skip_spaces(end);
 	get_match_id(&id, val);
 	if (id == NULL) {
 		printf(NAME " : error - could not read match id for "
-		    "device %s.\n", dev->name);
-		delete_match_id(match_id);
+		    "function %s.\n", fun->fnode->name);
 		return;
 	}
 
-	match_id->id = id;
-	match_id->score = score;
-
-	printf(NAME ": adding match id '%s' with score %d to device %s\n", id,
-	    score, dev->name);
-	add_match_id(&dev->match_ids, match_id);
-}
-
-static bool read_dev_prop(device_t *dev, char *line, const char *prop,
-    void (*read_fn)(device_t *, char *))
+	printf(NAME ": adding match id '%s' with score %d to function %s\n", id,
+	    score, fun->fnode->name);
+
+	rc = ddf_fun_add_match_id(fun->fnode, id, score);
+	if (rc != EOK)
+		printf(NAME ": error adding match ID: %s\n", str_error(rc));
+}
+
+static bool prop_parse(isa_fun_t *fun, char *line, const char *prop,
+    void (*read_fn)(isa_fun_t *, char *))
 {
 	size_t proplen = str_size(prop);
@@ -378,5 +360,5 @@
 		line += proplen;
 		line = skip_spaces(line);
-		(*read_fn)(dev, line);
+		(*read_fn)(fun, line);
 
 		return true;
@@ -386,12 +368,12 @@
 }
 
-static void get_dev_prop(device_t *dev, char *line)
+static void fun_prop_parse(isa_fun_t *fun, char *line)
 {
 	/* Skip leading spaces. */
 	line = skip_spaces(line);
 
-	if (!read_dev_prop(dev, line, "io_range", &get_dev_io_range) &&
-	    !read_dev_prop(dev, line, "irq", &get_dev_irq) &&
-	    !read_dev_prop(dev, line, "match", &get_dev_match_id))
+	if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
+	    !prop_parse(fun, line, "irq", &fun_parse_irq) &&
+	    !prop_parse(fun, line, "match", &fun_parse_match_id))
 	{
 	    printf(NAME " error undefined device property at line '%s'\n",
@@ -400,19 +382,18 @@
 }
 
-static void child_alloc_hw_res(device_t *dev)
-{
-	isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
-	data->hw_resources.resources = 
+static void fun_hw_res_alloc(isa_fun_t *fun)
+{
+	fun->hw_resources.resources = 
 	    (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
 }
 
-static char *read_isa_dev_info(char *dev_conf, device_t *parent)
+static char *isa_fun_read_info(char *fun_conf, ddf_dev_t *dev)
 {
 	char *line;
-	char *dev_name = NULL;
+	char *fun_name = NULL;
 
 	/* Skip empty lines. */
 	while (true) {
-		line = str_get_line(dev_conf, &dev_conf);
+		line = str_get_line(fun_conf, &fun_conf);
 
 		if (line == NULL) {
@@ -426,22 +407,20 @@
 
 	/* Get device name. */
-	dev_name = get_device_name(line);
-	if (dev_name == NULL)
+	fun_name = get_device_name(line);
+	if (fun_name == NULL)
 		return NULL;
 
-	device_t *dev = create_isa_child_dev();
-	if (dev == NULL) {
-		free(dev_name);
+	isa_fun_t *fun = isa_fun_create(dev, fun_name);
+	if (fun == NULL) {
+		free(fun_name);
 		return NULL;
 	}
 
-	dev->name = dev_name;
-
 	/* Allocate buffer for the list of hardware resources of the device. */
-	child_alloc_hw_res(dev);
+	fun_hw_res_alloc(fun);
 
 	/* Get properties of the device (match ids, irq and io range). */
 	while (true) {
-		line = str_get_line(dev_conf, &dev_conf);
+		line = str_get_line(fun_conf, &fun_conf);
 
 		if (line_empty(line)) {
@@ -454,46 +433,58 @@
 		 * and store it in the device structure.
 		 */
-		get_dev_prop(dev, line);
-
-		//printf(NAME ": next line ='%s'\n", dev_conf);
-		//printf(NAME ": current line ='%s'\n", line);
+		fun_prop_parse(fun, line);
 	}
 
 	/* Set device operations to the device. */
-	dev->ops = &isa_child_dev_ops;
-
-	printf(NAME ": child_device_register(dev, parent); device is %s.\n",
-	    dev->name);
-	child_device_register(dev, parent);
-
-	return dev_conf;
-}
-
-static void parse_dev_conf(char *conf, device_t *parent)
+	fun->fnode->ops = &isa_fun_ops;
+
+	printf(NAME ": Binding function %s.\n", fun->fnode->name);
+
+	/* XXX Handle error */
+	(void) ddf_fun_bind(fun->fnode);
+
+	return fun_conf;
+}
+
+static void fun_conf_parse(char *conf, ddf_dev_t *dev)
 {
 	while (conf != NULL && *conf != '\0') {
-		conf = read_isa_dev_info(conf, parent);
-	}
-}
-
-static void add_legacy_children(device_t *parent)
-{
-	char *dev_conf;
-
-	dev_conf = read_dev_conf(CHILD_DEV_CONF_PATH);
-	if (dev_conf != NULL) {
-		parse_dev_conf(dev_conf, parent);
-		free(dev_conf);
-	}
-}
-
-static int isa_add_device(device_t *dev)
+		conf = isa_fun_read_info(conf, dev);
+	}
+}
+
+static void isa_functions_add(ddf_dev_t *dev)
+{
+	char *fun_conf;
+
+	fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
+	if (fun_conf != NULL) {
+		fun_conf_parse(fun_conf, dev);
+		free(fun_conf);
+	}
+}
+
+static int isa_add_device(ddf_dev_t *dev)
 {
 	printf(NAME ": isa_add_device, device handle = %d\n",
 	    (int) dev->handle);
 
-	/* Add child devices. */
-	add_legacy_children(dev);
-	printf(NAME ": finished the enumeration of legacy devices\n");
+	/* Make the bus device more visible. Does not do anything. */
+	printf(NAME ": adding a 'ctl' function\n");
+
+	ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl");
+	if (ctl == NULL) {
+		printf(NAME ": Error creating control function.\n");
+		return EXDEV;
+	}
+
+	if (ddf_fun_bind(ctl) != EOK) {
+		printf(NAME ": Error binding control function.\n");
+		return EXDEV;
+	}
+
+	/* Add functions as specified in the configuration file. */
+	isa_functions_add(dev);
+	printf(NAME ": finished the enumeration of legacy functions\n");
 
 	return EOK;
@@ -502,5 +493,5 @@
 static void isa_init() 
 {
-	isa_child_dev_ops.interfaces[HW_RES_DEV_IFACE] = &isa_child_hw_res_ops;
+	isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
 }
 
@@ -509,5 +500,5 @@
 	printf(NAME ": HelenOS ISA bus driver\n");
 	isa_init();
-	return driver_main(&isa_driver);
+	return ddf_driver_main(&isa_driver);
 }
 
@@ -515,3 +506,2 @@
  * @}
  */
- 
Index: uspace/drv/ns8250/ns8250.c
===================================================================
--- uspace/drv/ns8250/ns8250.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/ns8250/ns8250.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -52,5 +53,6 @@
 #include <libarch/ddi.h>
 
-#include <driver.h>
+#include <ddf/driver.h>
+#include <ddf/interrupt.h>
 #include <ops/char_dev.h>
 
@@ -67,4 +69,10 @@
 #define MAX_BAUD_RATE 115200
 #define DLAB_MASK (1 << 7)
+
+/** Obtain soft-state structure from function node */
+#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
+
+/** Obtain soft-state structure from device node */
+#define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data))
 
 /** The number of bits of one data unit send by the serial port. */
@@ -85,5 +93,9 @@
 
 /** The driver data for the serial port devices. */
-typedef struct ns8250_dev_data {
+typedef struct ns8250 {
+	/** DDF device node */
+	ddf_dev_t *dev;
+	/** DDF function node */
+	ddf_fun_t *fun;
 	/** Is there any client conntected to the device? */
 	bool client_connected;
@@ -98,30 +110,30 @@
 	/** The fibril mutex for synchronizing the access to the device. */
 	fibril_mutex_t mutex;
-} ns8250_dev_data_t;
-
-/** Create driver data for a device.
- *
- * @return		The driver data.
- */
-static ns8250_dev_data_t *create_ns8250_dev_data(void)
-{
-	ns8250_dev_data_t *data;
-	
-	data = (ns8250_dev_data_t *) malloc(sizeof(ns8250_dev_data_t));
-	if (NULL != data) {
-		memset(data, 0, sizeof(ns8250_dev_data_t));
-		fibril_mutex_initialize(&data->mutex);
-	}
-	return data;
-}
-
-/** Delete driver data.
- *
- * @param data		The driver data structure.
- */
-static void delete_ns8250_dev_data(ns8250_dev_data_t *data)
-{
-	if (data != NULL)
-		free(data);
+} ns8250_t;
+
+/** Create per-device soft-state structure.
+ *
+ * @return	Pointer to soft-state structure.
+ */
+static ns8250_t *ns8250_new(void)
+{
+	ns8250_t *ns;
+	
+	ns = (ns8250_t *) calloc(1, sizeof(ns8250_t));
+	if (ns == NULL)
+		return NULL;
+	
+	fibril_mutex_initialize(&ns->mutex);
+	return ns;
+}
+
+/** Delete soft-state structure.
+ *
+ * @param ns	The driver data structure.
+ */
+static void ns8250_delete(ns8250_t *ns)
+{
+	assert(ns != NULL);
+	free(ns);
 }
 
@@ -171,5 +183,5 @@
 /** Read data from the serial port device.
  *
- * @param dev		The serial port device.
+ * @param fun		The serial port function
  * @param buf		The ouput buffer for read data.
  * @param count		The number of bytes to be read.
@@ -178,15 +190,15 @@
  *			error number otherwise.
  */
-static int ns8250_read(device_t *dev, char *buf, size_t count)
-{
+static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count)
+{
+	ns8250_t *ns = NS8250(fun);
 	int ret = EOK;
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	
-	fibril_mutex_lock(&data->mutex);
-	while (!buf_is_empty(&data->input_buffer) && (size_t)ret < count) {
-		buf[ret] = (char)buf_pop_front(&data->input_buffer);
+	
+	fibril_mutex_lock(&ns->mutex);
+	while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
+		buf[ret] = (char)buf_pop_front(&ns->input_buffer);
 		ret++;
 	}
-	fibril_mutex_unlock(&data->mutex);
+	fibril_mutex_unlock(&ns->mutex);
 	
 	return ret;
@@ -195,33 +207,33 @@
 /** Write a character to the serial port.
  *
- * @param data		The serial port device's driver data.
- * @param c		The character to be written.
- */
-static inline void ns8250_putchar(ns8250_dev_data_t *data, uint8_t c)
-{
-	fibril_mutex_lock(&data->mutex);
-	ns8250_write_8(data->port, c);
-	fibril_mutex_unlock(&data->mutex);
+ * @param ns		Serial port device
+ * @param c		The character to be written
+ */
+static inline void ns8250_putchar(ns8250_t *ns, uint8_t c)
+{
+	fibril_mutex_lock(&ns->mutex);
+	ns8250_write_8(ns->port, c);
+	fibril_mutex_unlock(&ns->mutex);
 }
 
 /** Write data to the serial port.
  *
- * @param dev		The serial port device.
- * @param buf		The data to be written.
- * @param count		The number of bytes to be written.
- * @return		Zero on success.
- */
-static int ns8250_write(device_t *dev, char *buf, size_t count) 
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
+ * @param fun		The serial port function
+ * @param buf		The data to be written
+ * @param count		The number of bytes to be written
+ * @return		Zero on success
+ */
+static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
+{
+	ns8250_t *ns = NS8250(fun);
 	size_t idx;
 	
 	for (idx = 0; idx < count; idx++)
-		ns8250_putchar(data, (uint8_t) buf[idx]);
+		ns8250_putchar(ns, (uint8_t) buf[idx]);
 	
 	return 0;
 }
 
-static device_ops_t ns8250_dev_ops;
+static ddf_dev_ops_t ns8250_dev_ops;
 
 /** The character interface's callbacks. */
@@ -231,5 +243,5 @@
 };
 
-static int ns8250_add_device(device_t *dev);
+static int ns8250_add_device(ddf_dev_t *dev);
 
 /** The serial port device driver's standard operations. */
@@ -244,18 +256,13 @@
 };
 
-/** Clean up the serial port device structure.
- *
- * @param dev		The device structure.
- */
-static void ns8250_dev_cleanup(device_t *dev)
-{
-	if (dev->driver_data != NULL) {
-		delete_ns8250_dev_data((ns8250_dev_data_t*) dev->driver_data);
-		dev->driver_data = NULL;
-	}
-	
-	if (dev->parent_phone > 0) {
-		async_hangup(dev->parent_phone);
-		dev->parent_phone = 0;
+/** Clean up the serial port soft-state
+ *
+ * @param ns		Serial port device
+ */
+static void ns8250_dev_cleanup(ns8250_t *ns)
+{
+	if (ns->dev->parent_phone > 0) {
+		async_hangup(ns->dev->parent_phone);
+		ns->dev->parent_phone = 0;
 	}
 }
@@ -263,18 +270,16 @@
 /** Enable the i/o ports of the device.
  *
- * @param dev		The serial port device.
- * @return		True on success, false otherwise.
- */
-static bool ns8250_pio_enable(device_t *dev)
-{
-	printf(NAME ": ns8250_pio_enable %s\n", dev->name);
-	
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+ * @param ns		Serial port device
+ * @return		True on success, false otherwise
+ */
+static bool ns8250_pio_enable(ns8250_t *ns)
+{
+	printf(NAME ": ns8250_pio_enable %s\n", ns->dev->name);
 	
 	/* Gain control over port's registers. */
-	if (pio_enable((void *)(uintptr_t) data->io_addr, REG_COUNT,
-	    (void **) &data->port)) {
+	if (pio_enable((void *)(uintptr_t) ns->io_addr, REG_COUNT,
+	    (void **) &ns->port)) {
 		printf(NAME ": error - cannot gain the port %#" PRIx32 " for device "
-		    "%s.\n", data->io_addr, dev->name);
+		    "%s.\n", ns->io_addr, ns->dev->name);
 		return false;
 	}
@@ -285,13 +290,12 @@
 /** Probe the serial port device for its presence.
  *
- * @param dev		The serial port device.
- * @return		True if the device is present, false otherwise.
- */
-static bool ns8250_dev_probe(device_t *dev)
-{
-	printf(NAME ": ns8250_dev_probe %s\n", dev->name);
-	
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	ioport8_t *port_addr = data->port;
+ * @param ns		Serial port device
+ * @return		True if the device is present, false otherwise
+ */
+static bool ns8250_dev_probe(ns8250_t *ns)
+{
+	printf(NAME ": ns8250_dev_probe %s\n", ns->dev->name);
+	
+	ioport8_t *port_addr = ns->port;
 	bool res = true;
 	uint8_t olddata;
@@ -310,5 +314,5 @@
 	
 	if (!res)
-		printf(NAME ": device %s is not present.\n", dev->name);
+		printf(NAME ": device %s is not present.\n", ns->dev->name);
 	
 	return res;
@@ -317,10 +321,10 @@
 /** Initialize serial port device.
  *
- * @param dev		The serial port device.
- * @return		Zero on success, negative error number otherwise.
- */
-static int ns8250_dev_initialize(device_t *dev)
-{
-	printf(NAME ": ns8250_dev_initialize %s\n", dev->name);
+ * @param ns		Serial port device
+ * @return		Zero on success, negative error number otherwise
+ */
+static int ns8250_dev_initialize(ns8250_t *ns)
+{
+	printf(NAME ": ns8250_dev_initialize %s\n", ns->dev->name);
 	
 	int ret = EOK;
@@ -329,25 +333,19 @@
 	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
 	
-	/* Allocate driver data for the device. */
-	ns8250_dev_data_t *data = create_ns8250_dev_data();
-	if (data == NULL)
-		return ENOMEM;
-	dev->driver_data = data;
-	
 	/* Connect to the parent's driver. */
-	dev->parent_phone = devman_parent_device_connect(dev->handle,
+	ns->dev->parent_phone = devman_parent_device_connect(ns->dev->handle,
 	    IPC_FLAG_BLOCKING);
-	if (dev->parent_phone < 0) {
+	if (ns->dev->parent_phone < 0) {
 		printf(NAME ": failed to connect to the parent driver of the "
-		    "device %s.\n", dev->name);
-		ret = dev->parent_phone;
+		    "device %s.\n", ns->dev->name);
+		ret = ns->dev->parent_phone;
 		goto failed;
 	}
 	
 	/* Get hw resources. */
-	ret = hw_res_get_resource_list(dev->parent_phone, &hw_resources);
+	ret = hw_res_get_resource_list(ns->dev->parent_phone, &hw_resources);
 	if (ret != EOK) {
 		printf(NAME ": failed to get hw resources for the device "
-		    "%s.\n", dev->name);
+		    "%s.\n", ns->dev->name);
 		goto failed;
 	}
@@ -362,15 +360,15 @@
 		switch (res->type) {
 		case INTERRUPT:
-			data->irq = res->res.interrupt.irq;
+			ns->irq = res->res.interrupt.irq;
 			irq = true;
 			printf(NAME ": the %s device was asigned irq = 0x%x.\n",
-			    dev->name, data->irq);
+			    ns->dev->name, ns->irq);
 			break;
 			
 		case IO_RANGE:
-			data->io_addr = res->res.io_range.address;
+			ns->io_addr = res->res.io_range.address;
 			if (res->res.io_range.size < REG_COUNT) {
 				printf(NAME ": i/o range assigned to the device "
-				    "%s is too small.\n", dev->name);
+				    "%s is too small.\n", ns->dev->name);
 				ret = ELIMIT;
 				goto failed;
@@ -378,5 +376,5 @@
 			ioport = true;
 			printf(NAME ": the %s device was asigned i/o address = "
-			    "0x%x.\n", dev->name, data->io_addr);
+			    "0x%x.\n", ns->dev->name, ns->io_addr);
 			break;
 			
@@ -388,5 +386,5 @@
 	if (!irq || !ioport) {
 		printf(NAME ": missing hw resource(s) for the device %s.\n",
-		    dev->name);
+		    ns->dev->name);
 		ret = ENOENT;
 		goto failed;
@@ -397,5 +395,5 @@
 	
 failed:
-	ns8250_dev_cleanup(dev);
+	ns8250_dev_cleanup(ns);
 	hw_res_clean_resource_list(&hw_resources);
 	return ret;
@@ -404,10 +402,10 @@
 /** Enable interrupts on the serial port device.
  *
- * Interrupt when data is received.
+ * Interrupt when data is received
  *
  * @param port		The base address of the serial port device's ports.
  */
 static inline void ns8250_port_interrupts_enable(ioport8_t *port)
-{	
+{
 	pio_write_8(port + 1, 0x1);	/* Interrupt when data received. */
 	pio_write_8(port + 4, 0xB);
@@ -416,5 +414,5 @@
 /** Disable interrupts on the serial port device.
  *
- * @param port		The base address of the serial port device's ports.
+ * @param port		The base address of the serial port device's ports
  */
 static inline void ns8250_port_interrupts_disable(ioport8_t *port)
@@ -425,13 +423,11 @@
 /** Enable interrupts for the serial port device.
  *
- * @param dev		The device.
- * @return		Zero on success, negative error number otherwise.
- */
-static int ns8250_interrupt_enable(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	
+ * @param ns		Serial port device
+ * @return		Zero on success, negative error number otherwise
+ */
+static int ns8250_interrupt_enable(ns8250_t *ns)
+{
 	/* Enable interrupt on the serial port. */
-	ns8250_port_interrupts_enable(data->port);
+	ns8250_port_interrupts_enable(ns->port);
 	
 	return EOK;
@@ -618,10 +614,9 @@
  * Set the default parameters of the serial communication.
  *
- * @param dev		The serial port device.
- */
-static void ns8250_initialize_port(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
-	ioport8_t *port = data->port;
+ * @param ns		Serial port device
+ */
+static void ns8250_initialize_port(ns8250_t *ns)
+{
+	ioport8_t *port = ns->port;
 	
 	/* Disable interrupts. */
@@ -643,14 +638,13 @@
  * buffer.
  *
- * @param dev		The serial port device.
- */
-static void ns8250_read_from_device(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	ioport8_t *port = data->port;
+ * @param ns		Serial port device
+ */
+static void ns8250_read_from_device(ns8250_t *ns)
+{
+	ioport8_t *port = ns->port;
 	bool cont = true;
 	
 	while (cont) {
-		fibril_mutex_lock(&data->mutex);
+		fibril_mutex_lock(&ns->mutex);
 		
 		cont = ns8250_received(port);
@@ -658,17 +652,17 @@
 			uint8_t val = ns8250_read_8(port);
 			
-			if (data->client_connected) {
-				if (!buf_push_back(&data->input_buffer, val)) {
+			if (ns->client_connected) {
+				if (!buf_push_back(&ns->input_buffer, val)) {
 					printf(NAME ": buffer overflow on "
-					    "%s.\n", dev->name);
+					    "%s.\n", ns->dev->name);
 				} else {
 					printf(NAME ": the character %c saved "
 					    "to the buffer of %s.\n",
-					    val, dev->name);
+					    val, ns->dev->name);
 				}
 			}
 		}
 		
-		fibril_mutex_unlock(&data->mutex);
+		fibril_mutex_unlock(&ns->mutex);
 		fibril_yield();
 	}
@@ -682,83 +676,107 @@
  * @param dev		The serial port device.
  */
-static inline void ns8250_interrupt_handler(device_t *dev, ipc_callid_t iid,
+static inline void ns8250_interrupt_handler(ddf_dev_t *dev, ipc_callid_t iid,
     ipc_call_t *icall)
 {
-	ns8250_read_from_device(dev);
+	ns8250_read_from_device(NS8250_FROM_DEV(dev));
 }
 
 /** Register the interrupt handler for the device.
  *
+ * @param ns		Serial port device
+ */
+static inline int ns8250_register_interrupt_handler(ns8250_t *ns)
+{
+	return register_interrupt_handler(ns->dev, ns->irq,
+	    ns8250_interrupt_handler, NULL);
+}
+
+/** Unregister the interrupt handler for the device.
+ *
+ * @param ns		Serial port device
+ */
+static inline int ns8250_unregister_interrupt_handler(ns8250_t *ns)
+{
+	return unregister_interrupt_handler(ns->dev, ns->irq);
+}
+
+/** The add_device callback method of the serial port driver.
+ *
+ * Probe and initialize the newly added device.
+ *
  * @param dev		The serial port device.
  */
-static inline int ns8250_register_interrupt_handler(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	
-	return register_interrupt_handler(dev, data->irq,
-	    ns8250_interrupt_handler, NULL);
-}
-
-/** Unregister the interrupt handler for the device.
- *
- * @param dev		The serial port device.
- */
-static inline int ns8250_unregister_interrupt_handler(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
-	
-	return unregister_interrupt_handler(dev, data->irq);
-}
-
-/** The add_device callback method of the serial port driver.
- *
- * Probe and initialize the newly added device.
- *
- * @param dev		The serial port device.
- */
-static int ns8250_add_device(device_t *dev)
-{
+static int ns8250_add_device(ddf_dev_t *dev)
+{
+	ns8250_t *ns = NULL;
+	ddf_fun_t *fun = NULL;
+	bool need_cleanup = false;
+	int rc;
+	
 	printf(NAME ": ns8250_add_device %s (handle = %d)\n",
 	    dev->name, (int) dev->handle);
 	
-	int res = ns8250_dev_initialize(dev);
-	if (res != EOK)
-		return res;
-	
-	if (!ns8250_pio_enable(dev)) {
-		ns8250_dev_cleanup(dev);
-		return EADDRNOTAVAIL;
+	/* Allocate soft-state for the device */
+	ns = ns8250_new();
+	if (ns == NULL) {
+		rc = ENOMEM;
+		goto fail;
+	}
+	
+	ns->dev = dev;
+	dev->driver_data = ns;
+	
+	rc = ns8250_dev_initialize(ns);
+	if (rc != EOK)
+		goto fail;
+	
+	need_cleanup = true;
+	
+	if (!ns8250_pio_enable(ns)) {
+		rc = EADDRNOTAVAIL;
+		goto fail;
 	}
 	
 	/* Find out whether the device is present. */
-	if (!ns8250_dev_probe(dev)) {
-		ns8250_dev_cleanup(dev);
-		return ENOENT;
+	if (!ns8250_dev_probe(ns)) {
+		rc = ENOENT;
+		goto fail;
 	}
 	
 	/* Serial port initialization (baud rate etc.). */
-	ns8250_initialize_port(dev);
+	ns8250_initialize_port(ns);
 	
 	/* Register interrupt handler. */
-	if (ns8250_register_interrupt_handler(dev) != EOK) {
+	if (ns8250_register_interrupt_handler(ns) != EOK) {
 		printf(NAME ": failed to register interrupt handler.\n");
-		ns8250_dev_cleanup(dev);
-		return res;
+		rc = EADDRNOTAVAIL;
+		goto fail;
 	}
 	
 	/* Enable interrupt. */
-	res = ns8250_interrupt_enable(dev);
-	if (res != EOK) {
+	rc = ns8250_interrupt_enable(ns);
+	if (rc != EOK) {
 		printf(NAME ": failed to enable the interrupt. Error code = "
-		    "%d.\n", res);
-		ns8250_dev_cleanup(dev);
-		ns8250_unregister_interrupt_handler(dev);
-		return res;
+		    "%d.\n", rc);
+		goto fail;
+	}
+	
+	fun = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun == NULL) {
+		printf(NAME ": error creating function.\n");
+		goto fail;
 	}
 	
 	/* Set device operations. */
-	dev->ops = &ns8250_dev_ops;
-	
-	add_device_to_class(dev, "serial");
+	fun->ops = &ns8250_dev_ops;
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function.\n");
+		goto fail;
+	}
+
+	ns->fun = fun;
+	
+	ddf_fun_add_to_class(fun, "serial");
 	
 	printf(NAME ": the %s device has been successfully initialized.\n",
@@ -766,4 +784,12 @@
 	
 	return EOK;
+fail:
+	if (fun != NULL)
+		ddf_fun_destroy(fun);
+	if (need_cleanup)
+		ns8250_dev_cleanup(ns);
+	if (ns != NULL)
+		ns8250_delete(ns);
+	return rc;
 }
 
@@ -775,7 +801,7 @@
  * @param dev		The device.
  */
-static int ns8250_open(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
+static int ns8250_open(ddf_fun_t *fun)
+{
+	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
 	int res;
 	
@@ -788,5 +814,5 @@
 	}
 	fibril_mutex_unlock(&data->mutex);
-
+	
 	return res;
 }
@@ -799,7 +825,7 @@
  * @param dev		The device.
  */
-static void ns8250_close(device_t *dev)
-{
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
+static void ns8250_close(ddf_fun_t *fun)
+{
+	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
 	
 	fibril_mutex_lock(&data->mutex);
@@ -823,8 +849,8 @@
  */
 static void
-ns8250_get_props(device_t *dev, unsigned int *baud_rate, unsigned int *parity,
+ns8250_get_props(ddf_dev_t *dev, unsigned int *baud_rate, unsigned int *parity,
     unsigned int *word_length, unsigned int* stop_bits)
 {
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
+	ns8250_t *data = (ns8250_t *) dev->driver_data;
 	ioport8_t *port = data->port;
 	
@@ -850,5 +876,5 @@
  * @param stop_bits	The number of stop bits to be used.
  */
-static int ns8250_set_props(device_t *dev, unsigned int baud_rate,
+static int ns8250_set_props(ddf_dev_t *dev, unsigned int baud_rate,
     unsigned int parity, unsigned int word_length, unsigned int stop_bits)
 {
@@ -857,5 +883,5 @@
 	    stop_bits);
 	
-	ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
+	ns8250_t *data = (ns8250_t *) dev->driver_data;
 	ioport8_t *port = data->port;
 	int ret;
@@ -877,5 +903,5 @@
  * Configure the parameters of the serial communication.
  */
-static void ns8250_default_handler(device_t *dev, ipc_callid_t callid,
+static void ns8250_default_handler(ddf_fun_t *fun, ipc_callid_t callid,
     ipc_call_t *call)
 {
@@ -886,5 +912,5 @@
 	switch (method) {
 	case SERIAL_GET_COM_PROPS:
-		ns8250_get_props(dev, &baud_rate, &parity, &word_length,
+		ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
 		    &stop_bits);
 		async_answer_4(callid, EOK, baud_rate, parity, word_length,
@@ -897,5 +923,5 @@
 		word_length = IPC_GET_ARG3(*call);
 		stop_bits = IPC_GET_ARG4(*call);
-		ret = ns8250_set_props(dev, baud_rate, parity, word_length,
+		ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length,
 		    stop_bits);
 		async_answer_0(callid, ret);
@@ -925,5 +951,5 @@
 	printf(NAME ": HelenOS serial port driver\n");
 	ns8250_init();
-	return driver_main(&ns8250_driver);
+	return ddf_driver_main(&ns8250_driver);
 }
 
Index: uspace/drv/pciintel/pci.c
===================================================================
--- uspace/drv/pciintel/pci.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/pciintel/pci.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -44,6 +45,7 @@
 #include <ctype.h>
 #include <macros.h>
-
-#include <driver.h>
+#include <str_error.h>
+
+#include <ddf/driver.h>
 #include <devman.h>
 #include <ipc/devman.h>
@@ -61,14 +63,23 @@
 	((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
 
-static hw_resource_list_t *pciintel_get_child_resources(device_t *dev)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	
-	if (dev_data == NULL)
+/** Obtain PCI function soft-state from DDF function node */
+#define PCI_FUN(fnode) ((pci_fun_t *) (fnode)->driver_data)
+
+/** Obtain PCI bus soft-state from DDF device node */
+#define PCI_BUS(dnode) ((pci_bus_t *) (dnode)->driver_data)
+
+/** Obtain PCI bus soft-state from function soft-state */
+#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
+
+static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
+{
+	pci_fun_t *fun = PCI_FUN(fnode);
+	
+	if (fun == NULL)
 		return NULL;
-	return &dev_data->hw_resources;
-}
-
-static bool pciintel_enable_child_interrupt(device_t *dev)
+	return &fun->hw_resources;
+}
+
+static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
 {
 	/* TODO */
@@ -77,19 +88,19 @@
 }
 
-static hw_res_ops_t pciintel_child_hw_res_ops = {
-	&pciintel_get_child_resources,
-	&pciintel_enable_child_interrupt
+static hw_res_ops_t pciintel_hw_res_ops = {
+	&pciintel_get_resources,
+	&pciintel_enable_interrupt
 };
 
-static device_ops_t pci_child_ops;
-
-static int pci_add_device(device_t *);
-
-/** The pci bus driver's standard operations. */
+static ddf_dev_ops_t pci_fun_ops;
+
+static int pci_add_device(ddf_dev_t *);
+
+/** PCI bus driver standard operations */
 static driver_ops_t pci_ops = {
 	.add_device = &pci_add_device
 };
 
-/** The pci bus driver structure. */
+/** PCI bus driver structure */
 static driver_t pci_driver = {
 	.name = NAME,
@@ -97,43 +108,33 @@
 };
 
-typedef struct pciintel_bus_data {
-	uint32_t conf_io_addr;
-	void *conf_data_port;
-	void *conf_addr_port;
-	fibril_mutex_t conf_mutex;
-} pci_bus_data_t;
-
-static pci_bus_data_t *create_pci_bus_data(void)
-{
-	pci_bus_data_t *bus_data;
-	
-	bus_data = (pci_bus_data_t *) malloc(sizeof(pci_bus_data_t));
-	if (bus_data != NULL) {
-		memset(bus_data, 0, sizeof(pci_bus_data_t));
-		fibril_mutex_initialize(&bus_data->conf_mutex);
-	}
-
-	return bus_data;
-}
-
-static void delete_pci_bus_data(pci_bus_data_t *bus_data)
-{
-	free(bus_data);
-}
-
-static void pci_conf_read(device_t *dev, int reg, uint8_t *buf, size_t len)
-{
-	assert(dev->parent != NULL);
-	
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data;
-	
-	fibril_mutex_lock(&bus_data->conf_mutex);
+static pci_bus_t *pci_bus_new(void)
+{
+	pci_bus_t *bus;
+	
+	bus = (pci_bus_t *) calloc(1, sizeof(pci_bus_t));
+	if (bus == NULL)
+		return NULL;
+	
+	fibril_mutex_initialize(&bus->conf_mutex);
+	return bus;
+}
+
+static void pci_bus_delete(pci_bus_t *bus)
+{
+	assert(bus != NULL);
+	free(bus);
+}
+
+static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
+{
+	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	
+	fibril_mutex_lock(&bus->conf_mutex);
 	
 	uint32_t conf_addr;
-	conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg);
-	void *addr = bus_data->conf_data_port + (reg & 3);
-	
-	pio_write_32(bus_data->conf_addr_port, conf_addr);
+	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
+	void *addr = bus->conf_data_port + (reg & 3);
+	
+	pio_write_32(bus->conf_addr_port, conf_addr);
 	
 	switch (len) {
@@ -149,21 +150,18 @@
 	}
 	
-	fibril_mutex_unlock(&bus_data->conf_mutex);
-}
-
-static void pci_conf_write(device_t *dev, int reg, uint8_t *buf, size_t len)
-{
-	assert(dev->parent != NULL);
-	
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data;
-	
-	fibril_mutex_lock(&bus_data->conf_mutex);
+	fibril_mutex_unlock(&bus->conf_mutex);
+}
+
+static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
+{
+	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	
+	fibril_mutex_lock(&bus->conf_mutex);
 	
 	uint32_t conf_addr;
-	conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg);
-	void *addr = bus_data->conf_data_port + (reg & 3);
-	
-	pio_write_32(bus_data->conf_addr_port, conf_addr);
+	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
+	void *addr = bus->conf_data_port + (reg & 3);
+	
+	pio_write_32(bus->conf_addr_port, conf_addr);
 	
 	switch (len) {
@@ -179,66 +177,69 @@
 	}
 	
-	fibril_mutex_unlock(&bus_data->conf_mutex);
-}
-
-uint8_t pci_conf_read_8(device_t *dev, int reg)
+	fibril_mutex_unlock(&bus->conf_mutex);
+}
+
+uint8_t pci_conf_read_8(pci_fun_t *fun, int reg)
 {
 	uint8_t res;
-	pci_conf_read(dev, reg, &res, 1);
+	pci_conf_read(fun, reg, &res, 1);
 	return res;
 }
 
-uint16_t pci_conf_read_16(device_t *dev, int reg)
+uint16_t pci_conf_read_16(pci_fun_t *fun, int reg)
 {
 	uint16_t res;
-	pci_conf_read(dev, reg, (uint8_t *) &res, 2);
+	pci_conf_read(fun, reg, (uint8_t *) &res, 2);
 	return res;
 }
 
-uint32_t pci_conf_read_32(device_t *dev, int reg)
+uint32_t pci_conf_read_32(pci_fun_t *fun, int reg)
 {
 	uint32_t res;
-	pci_conf_read(dev, reg, (uint8_t *) &res, 4);
+	pci_conf_read(fun, reg, (uint8_t *) &res, 4);
 	return res;
 }
 
-void pci_conf_write_8(device_t *dev, int reg, uint8_t val)
-{
-	pci_conf_write(dev, reg, (uint8_t *) &val, 1);
-}
-
-void pci_conf_write_16(device_t *dev, int reg, uint16_t val)
-{
-	pci_conf_write(dev, reg, (uint8_t *) &val, 2);
-}
-
-void pci_conf_write_32(device_t *dev, int reg, uint32_t val)
-{
-	pci_conf_write(dev, reg, (uint8_t *) &val, 4);
-}
-
-void create_pci_match_ids(device_t *dev)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	match_id_t *match_id = NULL;
+void pci_conf_write_8(pci_fun_t *fun, int reg, uint8_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 1);
+}
+
+void pci_conf_write_16(pci_fun_t *fun, int reg, uint16_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 2);
+}
+
+void pci_conf_write_32(pci_fun_t *fun, int reg, uint32_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 4);
+}
+
+void pci_fun_create_match_ids(pci_fun_t *fun)
+{
 	char *match_id_str;
-	
-	match_id = create_match_id();
-	if (match_id != NULL) {
-		asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
-		    dev_data->vendor_id, dev_data->device_id);
-		match_id->id = match_id_str;
-		match_id->score = 90;
-		add_match_id(&dev->match_ids, match_id);
-	}
-
+	int rc;
+	
+	asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
+	    fun->vendor_id, fun->device_id);
+
+	if (match_id_str == NULL) {
+		printf(NAME ": out of memory creating match ID.\n");
+		return;
+	}
+
+	rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90);
+	if (rc != EOK) {
+		printf(NAME ": error adding match ID: %s\n",
+		    str_error(rc));
+	}
+	
 	/* TODO add more ids (with subsys ids, using class id etc.) */
 }
 
-void
-pci_add_range(device_t *dev, uint64_t range_addr, size_t range_size, bool io)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	hw_resource_list_t *hw_res_list = &dev_data->hw_resources;
+void pci_add_range(pci_fun_t *fun, uint64_t range_addr, size_t range_size,
+    bool io)
+{
+	hw_resource_list_t *hw_res_list = &fun->hw_resources;
 	hw_resource_t *hw_resources =  hw_res_list->resources;
 	size_t count = hw_res_list->count;
@@ -265,11 +266,11 @@
  * address add it to the devices hw resource list.
  *
- * @param dev	The pci device.
+ * @param fun	PCI function
  * @param addr	The address of the BAR in the PCI configuration address space of
- *		the device.
- * @return	The addr the address of the BAR which should be read next.
+ *		the device
+ * @return	The addr the address of the BAR which should be read next
  */
-int pci_read_bar(device_t *dev, int addr)
-{	
+int pci_read_bar(pci_fun_t *fun, int addr)
+{
 	/* Value of the BAR */
 	uint32_t val, mask;
@@ -285,5 +286,5 @@
 	
 	/* Get the value of the BAR. */
-	val = pci_conf_read_32(dev, addr);
+	val = pci_conf_read_32(fun, addr);
 	
 	io = (bool) (val & 1);
@@ -305,15 +306,15 @@
 	
 	/* Get the address mask. */
-	pci_conf_write_32(dev, addr, 0xffffffff);
-	mask = pci_conf_read_32(dev, addr);
+	pci_conf_write_32(fun, addr, 0xffffffff);
+	mask = pci_conf_read_32(fun, addr);
 	
 	/* Restore the original value. */
-	pci_conf_write_32(dev, addr, val);
-	val = pci_conf_read_32(dev, addr);
+	pci_conf_write_32(fun, addr, val);
+	val = pci_conf_read_32(fun, addr);
 	
 	range_size = pci_bar_mask_to_size(mask);
 	
 	if (addrw64) {
-		range_addr = ((uint64_t)pci_conf_read_32(dev, addr + 4) << 32) |
+		range_addr = ((uint64_t)pci_conf_read_32(fun, addr + 4) << 32) |
 		    (val & 0xfffffff0);
 	} else {
@@ -322,10 +323,10 @@
 	
 	if (range_addr != 0) {
-		printf(NAME ": device %s : ", dev->name);
+		printf(NAME ": function %s : ", fun->fnode->name);
 		printf("address = %" PRIx64, range_addr);
 		printf(", size = %x\n", (unsigned int) range_size);
 	}
 	
-	pci_add_range(dev, range_addr, range_size, io);
+	pci_add_range(fun, range_addr, range_size, io);
 	
 	if (addrw64)
@@ -335,8 +336,7 @@
 }
 
-void pci_add_interrupt(device_t *dev, int irq)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	hw_resource_list_t *hw_res_list = &dev_data->hw_resources;
+void pci_add_interrupt(pci_fun_t *fun, int irq)
+{
+	hw_resource_list_t *hw_res_list = &fun->hw_resources;
 	hw_resource_t *hw_resources = hw_res_list->resources;
 	size_t count = hw_res_list->count;
@@ -350,40 +350,40 @@
 	hw_res_list->count++;
 	
-	printf(NAME ": device %s uses irq %x.\n", dev->name, irq);
-}
-
-void pci_read_interrupt(device_t *dev)
-{
-	uint8_t irq = pci_conf_read_8(dev, PCI_BRIDGE_INT_LINE);
+	printf(NAME ": function %s uses irq %x.\n", fun->fnode->name, irq);
+}
+
+void pci_read_interrupt(pci_fun_t *fun)
+{
+	uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
 	if (irq != 0xff)
-		pci_add_interrupt(dev, irq);
+		pci_add_interrupt(fun, irq);
 }
 
 /** Enumerate (recursively) and register the devices connected to a pci bus.
  *
- * @param parent	The host-to-pci bridge device.
- * @param bus_num	The bus number.
+ * @param bus		Host-to-PCI bridge
+ * @param bus_num	Bus number
  */
-void pci_bus_scan(device_t *parent, int bus_num) 
-{
-	device_t *dev = create_device();
-	pci_dev_data_t *dev_data = create_pci_dev_data();
-	dev->driver_data = dev_data;
-	dev->parent = parent;
+void pci_bus_scan(pci_bus_t *bus, int bus_num) 
+{
+	ddf_fun_t *fnode;
+	pci_fun_t *fun;
 	
 	int child_bus = 0;
 	int dnum, fnum;
 	bool multi;
-	uint8_t header_type; 
+	uint8_t header_type;
+	
+	fun = pci_fun_new(bus);
 	
 	for (dnum = 0; dnum < 32; dnum++) {
 		multi = true;
 		for (fnum = 0; multi && fnum < 8; fnum++) {
-			init_pci_dev_data(dev_data, bus_num, dnum, fnum);
-			dev_data->vendor_id = pci_conf_read_16(dev,
+			pci_fun_init(fun, bus_num, dnum, fnum);
+			fun->vendor_id = pci_conf_read_16(fun,
 			    PCI_VENDOR_ID);
-			dev_data->device_id = pci_conf_read_16(dev,
+			fun->device_id = pci_conf_read_16(fun,
 			    PCI_DEVICE_ID);
-			if (dev_data->vendor_id == 0xffff) {
+			if (fun->vendor_id == 0xffff) {
 				/*
 				 * The device is not present, go on scanning the
@@ -396,5 +396,5 @@
 			}
 			
-			header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE);
+			header_type = pci_conf_read_8(fun, PCI_HEADER_TYPE);
 			if (fnum == 0) {
 				/* Is the device multifunction? */
@@ -404,22 +404,36 @@
 			header_type = header_type & 0x7F;
 			
-			create_pci_dev_name(dev);
-			
-			pci_alloc_resource_list(dev);
-			pci_read_bars(dev);
-			pci_read_interrupt(dev);
-			
-			dev->ops = &pci_child_ops;
-			
-			printf(NAME ": adding new child device %s.\n",
-			    dev->name);
-			
-			create_pci_match_ids(dev);
-			
-			if (child_device_register(dev, parent) != EOK) {
-				pci_clean_resource_list(dev);
-				clean_match_ids(&dev->match_ids);
-				free((char *) dev->name);
-				dev->name = NULL;
+			char *fun_name = pci_fun_create_name(fun);
+			if (fun_name == NULL) {
+				printf(NAME ": out of memory.\n");
+				return;
+			}
+			
+			fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
+			if (fnode == NULL) {
+				printf(NAME ": error creating function.\n");
+				return;
+			}
+			
+			free(fun_name);
+			fun->fnode = fnode;
+			
+			pci_alloc_resource_list(fun);
+			pci_read_bars(fun);
+			pci_read_interrupt(fun);
+			
+			fnode->ops = &pci_fun_ops;
+			fnode->driver_data = fun;
+			
+			printf(NAME ": adding new function %s.\n",
+			    fnode->name);
+			
+			pci_fun_create_match_ids(fun);
+			
+			if (ddf_fun_bind(fnode) != EOK) {
+				pci_clean_resource_list(fun);
+				clean_match_ids(&fnode->match_ids);
+				free((char *) fnode->name);
+				fnode->name = NULL;
 				continue;
 			}
@@ -427,58 +441,59 @@
 			if (header_type == PCI_HEADER_TYPE_BRIDGE ||
 			    header_type == PCI_HEADER_TYPE_CARDBUS) {
-				child_bus = pci_conf_read_8(dev,
+				child_bus = pci_conf_read_8(fun,
 				    PCI_BRIDGE_SEC_BUS_NUM);
 				printf(NAME ": device is pci-to-pci bridge, "
 				    "secondary bus number = %d.\n", bus_num);
 				if (child_bus > bus_num)
-					pci_bus_scan(parent, child_bus);
+					pci_bus_scan(bus, child_bus);
 			}
 			
-			/* Alloc new aux. dev. structure. */
-			dev = create_device();
-			dev_data = create_pci_dev_data();
-			dev->driver_data = dev_data;
-			dev->parent = parent;
+			fun = pci_fun_new(bus);
 		}
 	}
 	
-	if (dev_data->vendor_id == 0xffff) {
-		delete_device(dev);
-		/* Free the auxiliary device structure. */
-		delete_pci_dev_data(dev_data);
-	}
-}
-
-static int pci_add_device(device_t *dev)
-{
+	if (fun->vendor_id == 0xffff) {
+		/* Free the auxiliary function structure. */
+		pci_fun_delete(fun);
+	}
+}
+
+static int pci_add_device(ddf_dev_t *dnode)
+{
+	pci_bus_t *bus = NULL;
+	ddf_fun_t *ctl = NULL;
+	bool got_res = false;
 	int rc;
-
+	
 	printf(NAME ": pci_add_device\n");
-	
-	pci_bus_data_t *bus_data = create_pci_bus_data();
-	if (bus_data == NULL) {
+	dnode->parent_phone = -1;
+	
+	bus = pci_bus_new();
+	if (bus == NULL) {
 		printf(NAME ": pci_add_device allocation failed.\n");
-		return ENOMEM;
-	}
-	
-	dev->parent_phone = devman_parent_device_connect(dev->handle,
+		rc = ENOMEM;
+		goto fail;
+	}
+	bus->dnode = dnode;
+	dnode->driver_data = bus;
+	
+	dnode->parent_phone = devman_parent_device_connect(dnode->handle,
 	    IPC_FLAG_BLOCKING);
-	if (dev->parent_phone < 0) {
+	if (dnode->parent_phone < 0) {
 		printf(NAME ": pci_add_device failed to connect to the "
 		    "parent's driver.\n");
-		delete_pci_bus_data(bus_data);
-		return dev->parent_phone;
+		rc = dnode->parent_phone;
+		goto fail;
 	}
 	
 	hw_resource_list_t hw_resources;
 	
-	rc = hw_res_get_resource_list(dev->parent_phone, &hw_resources);
+	rc = hw_res_get_resource_list(dnode->parent_phone, &hw_resources);
 	if (rc != EOK) {
 		printf(NAME ": pci_add_device failed to get hw resources for "
 		    "the device.\n");
-		delete_pci_bus_data(bus_data);
-		async_hangup(dev->parent_phone);
-		return rc;
-	}	
+		goto fail;
+	}
+	got_res = true;
 	
 	printf(NAME ": conf_addr = %" PRIx64 ".\n",
@@ -489,92 +504,113 @@
 	assert(hw_resources.resources[0].res.io_range.size == 8);
 	
-	bus_data->conf_io_addr =
+	bus->conf_io_addr =
 	    (uint32_t) hw_resources.resources[0].res.io_range.address;
 	
-	if (pio_enable((void *)(uintptr_t)bus_data->conf_io_addr, 8,
-	    &bus_data->conf_addr_port)) {
+	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 8,
+	    &bus->conf_addr_port)) {
 		printf(NAME ": failed to enable configuration ports.\n");
-		delete_pci_bus_data(bus_data);
-		async_hangup(dev->parent_phone);
+		rc = EADDRNOTAVAIL;
+		goto fail;
+	}
+	bus->conf_data_port = (char *) bus->conf_addr_port + 4;
+	
+	/* Make the bus device more visible. It has no use yet. */
+	printf(NAME ": adding a 'ctl' function\n");
+	
+	ctl = ddf_fun_create(bus->dnode, fun_exposed, "ctl");
+	if (ctl == NULL) {
+		printf(NAME ": error creating control function.\n");
+		rc = ENOMEM;
+		goto fail;
+	}
+	
+	rc = ddf_fun_bind(ctl);
+	if (rc != EOK) {
+		printf(NAME ": error binding control function.\n");
+		goto fail;
+	}
+	
+	/* Enumerate functions. */
+	printf(NAME ": scanning the bus\n");
+	pci_bus_scan(bus, 0);
+	
+	hw_res_clean_resource_list(&hw_resources);
+	
+	return EOK;
+	
+fail:
+	if (bus != NULL)
+		pci_bus_delete(bus);
+	if (dnode->parent_phone >= 0)
+		async_hangup(dnode->parent_phone);
+	if (got_res)
 		hw_res_clean_resource_list(&hw_resources);
-		return EADDRNOTAVAIL;
-	}
-	bus_data->conf_data_port = (char *) bus_data->conf_addr_port + 4;
-	
-	dev->driver_data = bus_data;
-	
-	/* Enumerate child devices. */
-	printf(NAME ": scanning the bus\n");
-	pci_bus_scan(dev, 0);
-	
-	hw_res_clean_resource_list(&hw_resources);
-	
-	return EOK;
+	if (ctl != NULL)
+		ddf_fun_destroy(ctl);
+
+	return rc;
 }
 
 static void pciintel_init(void)
 {
-	pci_child_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_child_hw_res_ops;
-}
-
-pci_dev_data_t *create_pci_dev_data(void)
-{
-	pci_dev_data_t *res = (pci_dev_data_t *) malloc(sizeof(pci_dev_data_t));
-	
-	if (res != NULL)
-		memset(res, 0, sizeof(pci_dev_data_t));
-	return res;
-}
-
-void init_pci_dev_data(pci_dev_data_t *dev_data, int bus, int dev, int fn)
-{
-	dev_data->bus = bus;
-	dev_data->dev = dev;
-	dev_data->fn = fn;
-}
-
-void delete_pci_dev_data(pci_dev_data_t *dev_data)
-{
-	if (dev_data != NULL) {
-		hw_res_clean_resource_list(&dev_data->hw_resources);
-		free(dev_data);
-	}
-}
-
-void create_pci_dev_name(device_t *dev)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
+	pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
+}
+
+pci_fun_t *pci_fun_new(pci_bus_t *bus)
+{
+	pci_fun_t *fun;
+	
+	fun = (pci_fun_t *) calloc(1, sizeof(pci_fun_t));
+	if (fun == NULL)
+		return NULL;
+
+	fun->busptr = bus;
+	return fun;
+}
+
+void pci_fun_init(pci_fun_t *fun, int bus, int dev, int fn)
+{
+	fun->bus = bus;
+	fun->dev = dev;
+	fun->fn = fn;
+}
+
+void pci_fun_delete(pci_fun_t *fun)
+{
+	assert(fun != NULL);
+	hw_res_clean_resource_list(&fun->hw_resources);
+	free(fun);
+}
+
+char *pci_fun_create_name(pci_fun_t *fun)
+{
 	char *name = NULL;
 	
-	asprintf(&name, "%02x:%02x.%01x", dev_data->bus, dev_data->dev,
-	    dev_data->fn);
-	dev->name = name;
-}
-
-bool pci_alloc_resource_list(device_t *dev)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
-	
-	dev_data->hw_resources.resources =
+	asprintf(&name, "%02x:%02x.%01x", fun->bus, fun->dev,
+	    fun->fn);
+	return name;
+}
+
+bool pci_alloc_resource_list(pci_fun_t *fun)
+{
+	fun->hw_resources.resources =
 	    (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
-	return dev_data->hw_resources.resources != NULL;
-}
-
-void pci_clean_resource_list(device_t *dev)
-{
-	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
-	
-	if (dev_data->hw_resources.resources != NULL) {
-		free(dev_data->hw_resources.resources);
-		dev_data->hw_resources.resources = NULL;
-	}
-}
-
-/** Read the base address registers (BARs) of the device and adds the addresses
- * to its hw resource list.
+	return fun->hw_resources.resources != NULL;
+}
+
+void pci_clean_resource_list(pci_fun_t *fun)
+{
+	if (fun->hw_resources.resources != NULL) {
+		free(fun->hw_resources.resources);
+		fun->hw_resources.resources = NULL;
+	}
+}
+
+/** Read the base address registers (BARs) of the function and add the addresses
+ * to its HW resource list.
  *
- * @param dev the pci device.
+ * @param fun	PCI function
  */
-void pci_read_bars(device_t *dev)
+void pci_read_bars(pci_fun_t *fun)
 {
 	/*
@@ -585,5 +621,5 @@
 	
 	while (addr <= PCI_BASE_ADDR_5)
-		addr = pci_read_bar(dev, addr);
+		addr = pci_read_bar(fun, addr);
 }
 
@@ -597,5 +633,5 @@
 	printf(NAME ": HelenOS pci bus driver (intel method 1).\n");
 	pciintel_init();
-	return driver_main(&pci_driver);
+	return ddf_driver_main(&pci_driver);
 }
 
Index: uspace/drv/pciintel/pci.h
===================================================================
--- uspace/drv/pciintel/pci.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/pciintel/pci.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,13 +37,22 @@
 #define PCI_H_
 
-#include <stdlib.h>
-#include <driver.h>
-#include <malloc.h>
-
+#include <ddf/driver.h>
 #include "pci_regs.h"
 
 #define PCI_MAX_HW_RES 8
 
-typedef struct pci_dev_data {
+typedef struct pciintel_bus {
+	/** DDF device node */
+	ddf_dev_t *dnode;
+	uint32_t conf_io_addr;
+	void *conf_data_port;
+	void *conf_addr_port;
+	fibril_mutex_t conf_mutex;
+} pci_bus_t;
+
+typedef struct pci_fun_data {
+	pci_bus_t *busptr;
+	ddf_fun_t *fnode;
+
 	int bus;
 	int dev;
@@ -51,31 +61,31 @@
 	int device_id;
 	hw_resource_list_t hw_resources;
-} pci_dev_data_t;
+} pci_fun_t;
 
-extern void create_pci_match_ids(device_t *);
+extern void pci_fun_create_match_ids(pci_fun_t *);
 
-extern uint8_t pci_conf_read_8(device_t *, int);
-extern uint16_t pci_conf_read_16(device_t *, int);
-extern uint32_t pci_conf_read_32(device_t *, int);
-extern void pci_conf_write_8(device_t *, int, uint8_t);
-extern void pci_conf_write_16(device_t *, int, uint16_t);
-extern void pci_conf_write_32(device_t *, int, uint32_t);
+extern uint8_t pci_conf_read_8(pci_fun_t *, int);
+extern uint16_t pci_conf_read_16(pci_fun_t *, int);
+extern uint32_t pci_conf_read_32(pci_fun_t *, int);
+extern void pci_conf_write_8(pci_fun_t *, int, uint8_t);
+extern void pci_conf_write_16(pci_fun_t *, int, uint16_t);
+extern void pci_conf_write_32(pci_fun_t *, int, uint32_t);
 
-extern void pci_add_range(device_t *, uint64_t, size_t, bool);
-extern int pci_read_bar(device_t *, int);
-extern void pci_read_interrupt(device_t *);
-extern void pci_add_interrupt(device_t *, int);
+extern void pci_add_range(pci_fun_t *, uint64_t, size_t, bool);
+extern int pci_read_bar(pci_fun_t *, int);
+extern void pci_read_interrupt(pci_fun_t *);
+extern void pci_add_interrupt(pci_fun_t *, int);
 
-extern void pci_bus_scan(device_t *, int);
+extern pci_fun_t *pci_fun_new(pci_bus_t *);
+extern void pci_fun_init(pci_fun_t *, int, int, int);
+extern void pci_fun_delete(pci_fun_t *);
+extern char *pci_fun_create_name(pci_fun_t *);
 
-extern pci_dev_data_t *create_pci_dev_data(void);
-extern void init_pci_dev_data(pci_dev_data_t *, int, int, int);
-extern void delete_pci_dev_data(pci_dev_data_t *);
-extern void create_pci_dev_name(device_t *);
+extern void pci_bus_scan(pci_bus_t *, int);
 
-extern bool pci_alloc_resource_list(device_t *);
-extern void pci_clean_resource_list(device_t *);
+extern bool pci_alloc_resource_list(pci_fun_t *);
+extern void pci_clean_resource_list(pci_fun_t *);
 
-extern void pci_read_bars(device_t *);
+extern void pci_read_bars(pci_fun_t *);
 extern size_t pci_bar_mask_to_size(uint32_t);
 
Index: uspace/drv/root/root.c
===================================================================
--- uspace/drv/root/root.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/root/root.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -2,4 +2,5 @@
  * Copyright (c) 2010 Lenka Trochtova
  * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -44,4 +45,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <str_error.h>
 #include <ctype.h>
 #include <macros.h>
@@ -49,5 +51,5 @@
 #include <sysinfo.h>
 
-#include <driver.h>
+#include <ddf/driver.h>
 #include <devman.h>
 #include <ipc/devman.h>
@@ -55,13 +57,13 @@
 #define NAME "root"
 
-#define PLATFORM_DEVICE_NAME "hw"
-#define PLATFORM_DEVICE_MATCH_ID_FMT "platform/%s"
-#define PLATFORM_DEVICE_MATCH_SCORE 100
-
-#define VIRTUAL_DEVICE_NAME "virt"
-#define VIRTUAL_DEVICE_MATCH_ID "rootvirt"
-#define VIRTUAL_DEVICE_MATCH_SCORE 100
-
-static int root_add_device(device_t *dev);
+#define PLATFORM_FUN_NAME "hw"
+#define PLATFORM_FUN_MATCH_ID_FMT "platform/%s"
+#define PLATFORM_FUN_MATCH_SCORE 100
+
+#define VIRTUAL_FUN_NAME "virt"
+#define VIRTUAL_FUN_MATCH_ID "rootvirt"
+#define VIRTUAL_FUN_MATCH_SCORE 100
+
+static int root_add_device(ddf_dev_t *dev);
 
 /** The root device driver's standard operations. */
@@ -76,35 +78,60 @@
 };
 
-/** Create the device which represents the root of virtual device tree.
- *
- * @param parent Parent of the newly created device.
- * @return Error code.
- */
-static int add_virtual_root_child(device_t *parent)
-{
-	printf(NAME ": adding new child for virtual devices.\n");
-	printf(NAME ":   device node is `%s' (%d %s)\n", VIRTUAL_DEVICE_NAME,
-	    VIRTUAL_DEVICE_MATCH_SCORE, VIRTUAL_DEVICE_MATCH_ID);
-
-	int res = child_device_register_wrapper(parent, VIRTUAL_DEVICE_NAME,
-	    VIRTUAL_DEVICE_MATCH_ID, VIRTUAL_DEVICE_MATCH_SCORE);
-
-	return res;
-}
-
-/** Create the device which represents the root of HW device tree.
- *
- * @param parent	Parent of the newly created device.
- * @return 0 on success, negative error number otherwise.
- */
-static int add_platform_child(device_t *parent)
+/** Create the function which represents the root of virtual device tree.
+ *
+ * @param dev	Device
+ * @return	EOK on success or negative error code
+ */
+static int add_virtual_root_fun(ddf_dev_t *dev)
+{
+	const char *name = VIRTUAL_FUN_NAME;
+	ddf_fun_t *fun;
+	int rc;
+
+	printf(NAME ": adding new function for virtual devices.\n");
+	printf(NAME ":   function node is `%s' (%d %s)\n", name,
+	    VIRTUAL_FUN_MATCH_SCORE, VIRTUAL_FUN_MATCH_ID);
+
+	fun = ddf_fun_create(dev, fun_inner, name);
+	if (fun == NULL) {
+		printf(NAME ": error creating function %s\n", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, VIRTUAL_FUN_MATCH_ID,
+	    VIRTUAL_FUN_MATCH_SCORE);
+	if (rc != EOK) {
+		printf(NAME ": error adding match IDs to function %s\n", name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function %s: %s\n", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Create the function which represents the root of HW device tree.
+ *
+ * @param dev	Device
+ * @return	EOK on success or negative error code
+ */
+static int add_platform_fun(ddf_dev_t *dev)
 {
 	char *match_id;
 	char *platform;
 	size_t platform_size;
-	int res;
+
+	const char *name = PLATFORM_FUN_NAME;
+	ddf_fun_t *fun;
+	int rc;
 
 	/* Get platform name from sysinfo. */
-
 	platform = sysinfo_get_data("platform", &platform_size);
 	if (platform == NULL) {
@@ -123,20 +150,36 @@
 
 	/* Construct match ID. */
-
-	if (asprintf(&match_id, PLATFORM_DEVICE_MATCH_ID_FMT, platform) == -1) {
+	if (asprintf(&match_id, PLATFORM_FUN_MATCH_ID_FMT, platform) == -1) {
 		printf(NAME ": Memory allocation failed.\n");
 		return ENOMEM;
 	}
 
-	/* Add child. */
-
-	printf(NAME ": adding new child for platform device.\n");
-	printf(NAME ":   device node is `%s' (%d %s)\n", PLATFORM_DEVICE_NAME,
-	    PLATFORM_DEVICE_MATCH_SCORE, match_id);
-
-	res = child_device_register_wrapper(parent, PLATFORM_DEVICE_NAME,
-	    match_id, PLATFORM_DEVICE_MATCH_SCORE);
-
-	return res;
+	/* Add function. */
+	printf(NAME ": adding platform function\n");
+	printf(NAME ":   function node is `%s' (%d %s)\n", PLATFORM_FUN_NAME,
+	    PLATFORM_FUN_MATCH_SCORE, match_id);
+
+	fun = ddf_fun_create(dev, fun_inner, name);
+	if (fun == NULL) {
+		printf(NAME ": error creating function %s\n", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, PLATFORM_FUN_MATCH_SCORE);
+	if (rc != EOK) {
+		printf(NAME ": error adding match IDs to function %s\n", name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function %s: %s\n", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	return EOK;
 }
 
@@ -146,9 +189,9 @@
  *			of HW and pseudo devices).
  */
-static int root_add_device(device_t *dev)
+static int root_add_device(ddf_dev_t *dev)
 {
 	printf(NAME ": root_add_device, device handle=%" PRIun "\n",
 	    dev->handle);
-	
+
 	/*
 	 * Register virtual devices root.
@@ -156,11 +199,11 @@
 	 * vital for the system.
 	 */
-	add_virtual_root_child(dev);
+	add_virtual_root_fun(dev);
 
 	/* Register root device's children. */
-	int res = add_platform_child(dev);
+	int res = add_platform_fun(dev);
 	if (EOK != res)
 		printf(NAME ": failed to add child device for platform.\n");
-	
+
 	return res;
 }
@@ -169,5 +212,5 @@
 {
 	printf(NAME ": HelenOS root device driver\n");
-	return driver_main(&root_driver);
+	return ddf_driver_main(&root_driver);
 }
 
Index: uspace/drv/rootpc/rootpc.c
===================================================================
--- uspace/drv/rootpc/rootpc.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/rootpc/rootpc.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -46,5 +46,5 @@
 #include <macros.h>
 
-#include <driver.h>
+#include <ddf/driver.h>
 #include <devman.h>
 #include <ipc/devman.h>
@@ -55,9 +55,12 @@
 #define NAME "rootpc"
 
-typedef struct rootpc_child_dev_data {
+/** Obtain function soft-state from DDF function node */
+#define ROOTPC_FUN(fnode) ((rootpc_fun_t *) (fnode)->driver_data)
+
+typedef struct rootpc_fun {
 	hw_resource_list_t hw_resources;
-} rootpc_child_dev_data_t;
-
-static int rootpc_add_device(device_t *dev);
+} rootpc_fun_t;
+
+static int rootpc_add_device(ddf_dev_t *dev);
 static void root_pc_init(void);
 
@@ -82,5 +85,5 @@
 };
 
-static rootpc_child_dev_data_t pci_data = {
+static rootpc_fun_t pci_data = {
 	.hw_resources = {
 		1,
@@ -89,16 +92,13 @@
 };
 
-static hw_resource_list_t *rootpc_get_child_resources(device_t *dev)
-{
-	rootpc_child_dev_data_t *data;
-	
-	data = (rootpc_child_dev_data_t *) dev->driver_data;
-	if (NULL == data)
-		return NULL;
-	
-	return &data->hw_resources;
-}
-
-static bool rootpc_enable_child_interrupt(device_t *dev)
+static hw_resource_list_t *rootpc_get_resources(ddf_fun_t *fnode)
+{
+	rootpc_fun_t *fun = ROOTPC_FUN(fnode);
+	
+	assert(fun != NULL);
+	return &fun->hw_resources;
+}
+
+static bool rootpc_enable_interrupt(ddf_fun_t *fun)
 {
 	/* TODO */
@@ -107,64 +107,63 @@
 }
 
-static hw_res_ops_t child_hw_res_ops = {
-	&rootpc_get_child_resources,
-	&rootpc_enable_child_interrupt
+static hw_res_ops_t fun_hw_res_ops = {
+	&rootpc_get_resources,
+	&rootpc_enable_interrupt
 };
 
 /* Initialized in root_pc_init() function. */
-static device_ops_t rootpc_child_ops;
+static ddf_dev_ops_t rootpc_fun_ops;
 
 static bool
-rootpc_add_child(device_t *parent, const char *name, const char *str_match_id,
-    rootpc_child_dev_data_t *drv_data)
-{
-	printf(NAME ": adding new child device '%s'.\n", name);
-	
-	device_t *child = NULL;
+rootpc_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
+    rootpc_fun_t *fun)
+{
+	printf(NAME ": adding new function '%s'.\n", name);
+	
+	ddf_fun_t *fnode = NULL;
 	match_id_t *match_id = NULL;
 	
 	/* Create new device. */
-	child = create_device();
-	if (NULL == child)
+	fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL)
 		goto failure;
 	
-	child->name = name;
-	child->driver_data = drv_data;
+	fnode->driver_data = fun;
 	
 	/* Initialize match id list */
 	match_id = create_match_id();
-	if (NULL == match_id)
+	if (match_id == NULL)
 		goto failure;
 	
 	match_id->id = str_match_id;
 	match_id->score = 100;
-	add_match_id(&child->match_ids, match_id);
+	add_match_id(&fnode->match_ids, match_id);
 	
 	/* Set provided operations to the device. */
-	child->ops = &rootpc_child_ops;
-	
-	/* Register child device. */
-	if (EOK != child_device_register(child, parent))
+	fnode->ops = &rootpc_fun_ops;
+	
+	/* Register function. */
+	if (ddf_fun_bind(fnode) != EOK) {
+		printf(NAME ": error binding function %s.\n", name);
 		goto failure;
+	}
 	
 	return true;
 	
 failure:
-	if (NULL != match_id)
+	if (match_id != NULL)
 		match_id->id = NULL;
 	
-	if (NULL != child) {
-		child->name = NULL;
-		delete_device(child);
-	}
-	
-	printf(NAME ": failed to add child device '%s'.\n", name);
+	if (fnode != NULL)
+		ddf_fun_destroy(fnode);
+	
+	printf(NAME ": failed to add function '%s'.\n", name);
 	
 	return false;
 }
 
-static bool rootpc_add_children(device_t *dev)
-{
-	return rootpc_add_child(dev, "pci0", "intel_pci", &pci_data);
+static bool rootpc_add_functions(ddf_dev_t *dev)
+{
+	return rootpc_add_fun(dev, "pci0", "intel_pci", &pci_data);
 }
 
@@ -175,12 +174,12 @@
  * @return		Zero on success, negative error number otherwise.
  */
-static int rootpc_add_device(device_t *dev)
+static int rootpc_add_device(ddf_dev_t *dev)
 {
 	printf(NAME ": rootpc_add_device, device handle = %d\n",
 	    (int)dev->handle);
 	
-	/* Register child devices. */
-	if (!rootpc_add_children(dev)) {
-		printf(NAME ": failed to add child devices for PC platform.\n");
+	/* Register functions. */
+	if (!rootpc_add_functions(dev)) {
+		printf(NAME ": failed to add functions for PC platform.\n");
 	}
 	
@@ -190,5 +189,5 @@
 static void root_pc_init(void)
 {
-	rootpc_child_ops.interfaces[HW_RES_DEV_IFACE] = &child_hw_res_ops;
+	rootpc_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
 }
 
@@ -197,5 +196,5 @@
 	printf(NAME ": HelenOS PC platform driver\n");
 	root_pc_init();
-	return driver_main(&rootpc_driver);
+	return ddf_driver_main(&rootpc_driver);
 }
 
Index: uspace/drv/rootvirt/rootvirt.c
===================================================================
--- uspace/drv/rootvirt/rootvirt.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/rootvirt/rootvirt.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -39,20 +39,20 @@
 #include <errno.h>
 #include <str_error.h>
-#include <driver.h>
+#include <ddf/driver.h>
 
 #define NAME "rootvirt"
 
-/** Virtual device entry. */
+/** Virtual function entry */
 typedef struct {
-	/** Device name. */
+	/** Function name */
 	const char *name;
-	/** Device match id. */
+	/** Function match ID */
 	const char *match_id;
-} virtual_device_t;
+} virtual_function_t;
 
-/** List of existing virtual devices. */
-virtual_device_t virtual_devices[] = {
+/** List of existing virtual functions */
+virtual_function_t virtual_functions[] = {
 #include "devices.def"
-	/* Terminating item. */
+	/* Terminating item */
 	{
 		.name = NULL,
@@ -61,8 +61,8 @@
 };
 
-static int add_device(device_t *dev);
+static int rootvirt_add_device(ddf_dev_t *dev);
 
 static driver_ops_t rootvirt_ops = {
-	.add_device = &add_device
+	.add_device = &rootvirt_add_device
 };
 
@@ -72,30 +72,45 @@
 };
 
-/** Add child device.
+/** Add function to the virtual device.
  *
- * @param parent Parent device.
- * @param virt_dev Virtual device to add.
- * @return Error code.
+ * @param vdev		The virtual device
+ * @param vfun		Virtual function description
+ * @return		EOK on success or negative error code.
  */
-static int add_child(device_t *parent, virtual_device_t *virt_dev)
+static int rootvirt_add_fun(ddf_dev_t *vdev, virtual_function_t *vfun)
 {
-	printf(NAME ": registering child device `%s' (match \"%s\")\n",
-	    virt_dev->name, virt_dev->match_id);
+	ddf_fun_t *fun;
+	int rc;
 
-	int rc = child_device_register_wrapper(parent, virt_dev->name,
-	    virt_dev->match_id, 10);
+	printf(NAME ": registering function `%s' (match \"%s\")\n",
+	    vfun->name, vfun->match_id);
 
-	if (rc == EOK) {
-		printf(NAME ": registered child device `%s'\n",
-		    virt_dev->name);
-	} else {
-		printf(NAME ": failed to register child device `%s': %s\n",
-		    virt_dev->name, str_error(rc));
+	fun = ddf_fun_create(vdev, fun_inner, vfun->name);
+	if (fun == NULL) {
+		printf(NAME ": error creating function %s\n", vfun->name);
+		return ENOMEM;
 	}
 
-	return rc;
+	rc = ddf_fun_add_match_id(fun, vfun->match_id, 10);
+	if (rc != EOK) {
+		printf(NAME ": error adding match IDs to function %s\n",
+		    vfun->name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function %s: %s\n", vfun->name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	printf(NAME ": registered child device `%s'\n", vfun->name);
+	return EOK;
 }
 
-static int add_device(device_t *dev)
+static int rootvirt_add_device(ddf_dev_t *dev)
 {
 	static int instances = 0;
@@ -109,15 +124,14 @@
 	}
 
-	printf(NAME ": add_device(name=\"%s\", handle=%d)\n",
-	    dev->name, (int)dev->handle);
-	
+	printf(NAME ": add_device(handle=%d)\n", (int)dev->handle);
+
 	/*
-	 * Go through all virtual devices and try to add them.
+	 * Go through all virtual functions and try to add them.
 	 * We silently ignore failures.
 	 */
-	virtual_device_t *virt_dev = virtual_devices;
-	while (virt_dev->name != NULL) {
-		(void) add_child(dev, virt_dev);
-		virt_dev++;
+	virtual_function_t *vfun = virtual_functions;
+	while (vfun->name != NULL) {
+		(void) rootvirt_add_fun(dev, vfun);
+		vfun++;
 	}
 
@@ -128,5 +142,5 @@
 {
 	printf(NAME ": HelenOS virtual devices root driver\n");
-	return driver_main(&rootvirt_driver);
+	return ddf_driver_main(&rootvirt_driver);
 }
 
Index: uspace/drv/test1/char.c
===================================================================
--- uspace/drv/test1/char.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/test1/char.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -37,10 +37,10 @@
 #include "test1.h"
 
-static int impl_char_read(device_t *dev, char *buf, size_t count) {
+static int impl_char_read(ddf_fun_t *fun, char *buf, size_t count) {
 	memset(buf, 0, count);
 	return count;
 }
 
-static int imp_char_write(device_t *dev, char *buf, size_t count) {
+static int imp_char_write(ddf_fun_t *fun, char *buf, size_t count) {
 	return count;
 }
@@ -51,5 +51,5 @@
 };
 
-device_ops_t char_device_ops = {
+ddf_dev_ops_t char_device_ops = {
 	.interfaces[CHAR_DEV_IFACE] = &char_dev_ops
 };
Index: uspace/drv/test1/test1.c
===================================================================
--- uspace/drv/test1/test1.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/test1/test1.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -34,13 +34,15 @@
 #include <errno.h>
 #include <str_error.h>
+#include <ddf/driver.h>
+
 #include "test1.h"
 
-static int add_device(device_t *dev);
+static int test1_add_device(ddf_dev_t *dev);
 
 static driver_ops_t driver_ops = {
-	.add_device = &add_device
+	.add_device = &test1_add_device
 };
 
-static driver_t the_driver = {
+static driver_t test1_driver = {
 	.name = NAME,
 	.driver_ops = &driver_ops
@@ -55,19 +57,35 @@
  * @param score Device match score.
  */
-static void register_child_verbose(device_t *parent, const char *message,
+static int register_fun_verbose(ddf_dev_t *parent, const char *message,
     const char *name, const char *match_id, int match_score)
 {
-	printf(NAME ": registering child device `%s': %s.\n",
-	   name, message);
+	ddf_fun_t *fun;
+	int rc;
 
-	int rc = child_device_register_wrapper(parent, name,
-	    match_id, match_score);
+	printf(NAME ": registering function `%s': %s.\n", name, message);
 
-	if (rc == EOK) {
-		printf(NAME ": registered child device `%s'.\n", name);
-	} else {
-		printf(NAME ": failed to register child `%s' (%s).\n",
-		    name, str_error(rc));
+	fun = ddf_fun_create(parent, fun_inner, name);
+	if (fun == NULL) {
+		printf(NAME ": error creating function %s\n", name);
+		return ENOMEM;
 	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, match_score);
+	if (rc != EOK) {
+		printf(NAME ": error adding match IDs to function %s\n", name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function %s: %s\n", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	printf(NAME ": registered child device `%s'\n", name);
+	return EOK;
 }
 
@@ -89,19 +107,34 @@
  * @return Error code reporting success of the operation.
  */
-static int add_device(device_t *dev)
+static int test1_add_device(ddf_dev_t *dev)
 {
+	ddf_fun_t *fun_a;
+	int rc;
+
 	printf(NAME ": add_device(name=\"%s\", handle=%d)\n",
 	    dev->name, (int) dev->handle);
 
-	add_device_to_class(dev, "virtual");
+	fun_a = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun_a == NULL) {
+		printf(NAME ": error creating function 'a'.\n");
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_bind(fun_a);
+	if (rc != EOK) {
+		printf(NAME ": error binding function 'a'.\n");
+		return rc;
+	}
+
+	ddf_fun_add_to_class(fun_a, "virtual");
 
 	if (str_cmp(dev->name, "null") == 0) {
-		dev->ops = &char_device_ops;
-		add_device_to_class(dev, "virt-null");
-	} else if (dev->parent == NULL) {
-		register_child_verbose(dev, "cloning myself ;-)", "clone",
+		fun_a->ops = &char_device_ops;
+		ddf_fun_add_to_class(fun_a, "virt-null");
+	} else if (str_cmp(dev->name, "test1") == 0) {
+		(void) register_fun_verbose(dev, "cloning myself ;-)", "clone",
 		    "virtual&test1", 10);
 	} else if (str_cmp(dev->name, "clone") == 0) {
-		register_child_verbose(dev, "run by the same task", "child",
+		(void) register_fun_verbose(dev, "run by the same task", "child",
 		    "virtual&test1&child", 10);
 	}
@@ -115,5 +148,5 @@
 {
 	printf(NAME ": HelenOS test1 virtual device driver\n");
-	return driver_main(&the_driver);
+	return ddf_driver_main(&test1_driver);
 }
 
Index: uspace/drv/test1/test1.h
===================================================================
--- uspace/drv/test1/test1.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/test1/test1.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -32,9 +32,9 @@
 #define DRV_TEST1_TEST1_H_
 
-#include <driver.h>
+#include <ddf/driver.h>
 
 #define NAME "test1"
 
-extern device_ops_t char_device_ops;
+extern ddf_dev_ops_t char_device_ops;
 
 #endif
Index: uspace/drv/test2/test2.c
===================================================================
--- uspace/drv/test2/test2.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/drv/test2/test2.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -31,18 +31,19 @@
 
 #include <assert.h>
+#include <async.h>
 #include <stdio.h>
 #include <errno.h>
 #include <str_error.h>
-#include <driver.h>
+#include <ddf/driver.h>
 
 #define NAME "test2"
 
-static int add_device(device_t *dev);
+static int test2_add_device(ddf_dev_t *dev);
 
 static driver_ops_t driver_ops = {
-	.add_device = &add_device
+	.add_device = &test2_add_device
 };
 
-static driver_t the_driver = {
+static driver_t test2_driver = {
 	.name = NAME,
 	.driver_ops = &driver_ops
@@ -57,53 +58,86 @@
  * @param score Device match score.
  */
-static void register_child_verbose(device_t *parent, const char *message,
+static int register_fun_verbose(ddf_dev_t *parent, const char *message,
     const char *name, const char *match_id, int match_score)
 {
-	printf(NAME ": registering child device `%s': %s.\n",
-	   name, message);
+	ddf_fun_t *fun;
+	int rc;
 
-	int rc = child_device_register_wrapper(parent, name,
-	    match_id, match_score);
+	printf(NAME ": registering function `%s': %s.\n", name, message);
 
-	if (rc == EOK) {
-		printf(NAME ": registered child device `%s'.\n", name);
-	} else {
-		printf(NAME ": failed to register child `%s' (%s).\n",
-		    name, str_error(rc));
+	fun = ddf_fun_create(parent, fun_inner, name);
+	if (fun == NULL) {
+		printf(NAME ": error creating function %s\n", name);
+		return ENOMEM;
 	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, match_score);
+	if (rc != EOK) {
+		printf(NAME ": error adding match IDs to function %s\n", name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		printf(NAME ": error binding function %s: %s\n", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	printf(NAME ": registered child device `%s'\n", name);
+	return EOK;
 }
 
 /** Add child devices after some sleep.
  *
- * @param arg Parent device structure (device_t *).
+ * @param arg Parent device structure (ddf_dev_t *).
  * @return Always EOK.
  */
 static int postponed_birth(void *arg)
 {
-	device_t *dev = (device_t *) arg;
+	ddf_dev_t *dev = (ddf_dev_t *) arg;
+	ddf_fun_t *fun_a;
+	int rc;
 
 	async_usleep(1000);
 
-	register_child_verbose(dev, "child driven by the same task",
+	(void) register_fun_verbose(dev, "child driven by the same task",
 	    "child", "virtual&test2", 10);
-	register_child_verbose(dev, "child driven by test1",
+	(void) register_fun_verbose(dev, "child driven by test1",
 	    "test1", "virtual&test1", 10);
 
-	add_device_to_class(dev, "virtual");
+	fun_a = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun_a == NULL) {
+		printf(NAME ": error creating function 'a'.\n");
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_bind(fun_a);
+	if (rc != EOK) {
+		printf(NAME ": error binding function 'a'.\n");
+		return rc;
+	}
+
+	ddf_fun_add_to_class(fun_a, "virtual");
 
 	return EOK;
 }
 
-
-static int add_device(device_t *dev)
+static int test2_add_device(ddf_dev_t *dev)
 {
-	printf(NAME ": add_device(name=\"%s\", handle=%d)\n",
+	printf(NAME ": test2_add_device(name=\"%s\", handle=%d)\n",
 	    dev->name, (int) dev->handle);
 
-	if (dev->parent == NULL) {
+	if (str_cmp(dev->name, "child") != 0) {
 		fid_t postpone = fibril_create(postponed_birth, dev);
+		if (postpone == 0) {
+			printf(NAME ": fibril_create() error\n");
+			return ENOMEM;
+		}
 		fibril_add_ready(postpone);
 	} else {
-		register_child_verbose(dev, "child without available driver",
+		(void) register_fun_verbose(dev, "child without available driver",
 		    "ERROR", "non-existent.match.id", 10);
 	}
@@ -115,5 +149,5 @@
 {
 	printf(NAME ": HelenOS test2 virtual device driver\n");
-	return driver_main(&the_driver);
+	return ddf_driver_main(&test2_driver);
 }
 
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/Makefile	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -91,6 +91,6 @@
 	generic/loader.c \
 	generic/getopt.c \
-	generic/adt/list.o \
-	generic/adt/hash_table.o \
+	generic/adt/list.c \
+	generic/adt/hash_table.c \
 	generic/adt/dynamic_fifo.c \
 	generic/adt/measured_strings.c \
Index: pace/lib/c/Makefile.toolchain
===================================================================
--- uspace/lib/c/Makefile.toolchain	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,128 +1,0 @@
-#
-# Copyright (C) 2005 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.
-#
-
-GCC_CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \
-	-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \
-	-finput-charset=UTF-8 -ffreestanding -fno-builtin -nostdlib -nostdinc \
-	-Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \
-	-Werror-implicit-function-declaration -pipe -g -D__$(ENDIANESS)__
-
-ICC_CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \
-	-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \
-	-finput-charset=UTF-8 -ffreestanding -fno-builtin -nostdlib -nostdinc \
-	-Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \
-	-Werror-implicit-function-declaration -pipe -g -D__$(ENDIANESS)__
-
-CLANG_CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \
-	-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \
-	-finput-charset=UTF-8 -ffreestanding -fno-builtin -nostdlib -nostdinc \
-	-Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \
-	-Werror-implicit-function-declaration -pipe -g -arch $(CLANG_ARCH) \
-	-D__$(ENDIANESS)__
-
-LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a
-AFLAGS =
-
-## Cross-toolchain prefix
-#
-
-ifndef CROSS_PREFIX
-	CROSS_PREFIX = /usr/local
-endif
-
-## Setup platform configuration
-#
-
--include $(LIBC_PREFIX)/../../../Makefile.config
--include $(LIBC_PREFIX)/../../../config.defs
--include $(LIBC_PREFIX)/arch/$(UARCH)/Makefile.inc
-
-## Simple detection of the host system
-#
-HOST = $(shell uname)
-
-## On Solaris, some utilities have different names
-#
-ifeq ($(HOST),SunOS)
-	BINUTILS_PREFIX = "g"
-else
-	BINUTILS_PREFIX = ""
-endif
-
-## Toolchain configuration
-#
-
-JOBFILE = $(LIBC_PREFIX)/../../../tools/jobfile.py
-
-ifeq ($(COMPILER),gcc_cross)
-	CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc
-	GCC = $(CC)
-	AS = $(TOOLCHAIN_DIR)/$(TARGET)-as
-	LD = $(TOOLCHAIN_DIR)/$(TARGET)-ld
-	AR = $(TOOLCHAIN_DIR)/$(TARGET)-ar
-	OBJCOPY = $(TOOLCHAIN_DIR)/$(TARGET)-objcopy
-	OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
-	CFLAGS = $(GCC_CFLAGS)
-	DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
-endif
-
-ifeq ($(COMPILER),gcc_native)
-	CC = gcc
-	GCC = $(CC)
-	AS = $(BINUTILS_PREFIX)as
-	LD = $(BINUTILS_PREFIX)ld
-	AR = $(BINUTILS_PREFIX)ar
-	OBJCOPY = $(BINUTILS_PREFIX)objcopy
-	OBJDUMP = $(BINUTILS_PREFIX)objdump
-	CFLAGS = $(GCC_CFLAGS)
-	DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
-endif
-
-ifeq ($(COMPILER),icc)
-	CC = icc
-	GCC = gcc
-	AS = as
-	LD = ld
-	AR = ar
-	OBJCOPY = objcopy
-	OBJDUMP = objdump
-	CFLAGS = $(ICC_CFLAGS)
-	DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
-endif
-
-ifeq ($(COMPILER),clang)
-	CC = clang
-	GCC = gcc
-	AS = $(BINUTILS_PREFIX)as
-	LD = $(BINUTILS_PREFIX)ld
-	AR = $(BINUTILS_PREFIX)ar
-	OBJCOPY = $(BINUTILS_PREFIX)objcopy
-	OBJDUMP = $(BINUTILS_PREFIX)objdump
-	CFLAGS = $(CLANG_CFLAGS)
-	DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
-endif
Index: uspace/lib/c/arch/abs32le/_link.ld.in
===================================================================
--- uspace/lib/c/arch/abs32le/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/arch/abs32le/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -44,8 +44,4 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	
-	_heap = .;
-	
 	/DISCARD/ : {
 		*(*);
Index: uspace/lib/c/arch/amd64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/amd64/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/arch/amd64/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -5,4 +5,5 @@
 	text PT_LOAD FLAGS(5);
 	data PT_LOAD FLAGS(6);
+	debug PT_NOTE;
 }
 
@@ -13,14 +14,16 @@
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x1000;
-
+	
 	.data : {
 		*(.data);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -31,16 +34,27 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(COMMON);
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x1000);
-	_heap = .;
+	
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); } :debug
+	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
+	.debug_aranges 0 : { *(.debug_aranges); } :debug
+	.debug_info 0 : { *(.debug_info); } :debug
+	.debug_line 0 : { *(.debug_line); } :debug
+	.debug_loc 0 : { *(.debug_loc); } :debug
+	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
+	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
+	.debug_ranges 0 : { *(.debug_ranges); } :debug
+	.debug_str 0 : { *(.debug_str); } :debug
+#endif
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: pace/lib/c/arch/amd64/include/limits.h
===================================================================
--- uspace/lib/c/arch/amd64/include/limits.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 libcamd64
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_amd64_LIMITS_H_
-#define LIBC_amd64_LIMITS_H_
-
-# define LONG_MIN MIN_INT64
-# define LONG_MAX MAX_INT64
-# define ULONG_MIN MIN_UINT64
-# define ULONG_MAX MAX_UINT64
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/arch/arm32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/arm32/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/arch/arm32/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -9,15 +9,16 @@
 SECTIONS {
 	. = 0x1000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
-        *(.rodata*);
+		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x1000;
-
+	
 	.data : {
 		*(.opd);
@@ -25,4 +26,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -33,18 +35,16 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
 		*(.scommon);
-        *(COMMON);
-        *(.bss);
+		*(COMMON);
+		*(.bss);
 	} :data
-	
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: pace/lib/c/arch/arm32/include/limits.h
===================================================================
--- uspace/lib/c/arch/arm32/include/limits.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2007 Michal Kebrt
- * 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 libcarm32	
- * @{
- */
-/** @file 
- *  @brief Limits declarations.
- */
-
-#ifndef LIBC_arm32__LIMITS_H_
-#define LIBC_arm32__LIMITS_H_
-
-#define LONG_MIN MIN_INT32
-#define LONG_MAX MAX_INT32
-#define ULONG_MIN MIN_UINT32
-#define ULONG_MAX MAX_UINT32
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/arch/ia32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia32/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/arch/ia32/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -5,4 +5,5 @@
 	text PT_LOAD FLAGS(5);
 	data PT_LOAD FLAGS(6);
+	debug PT_NOTE;
 }
 
@@ -42,7 +43,16 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	
-	_heap = .;
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); } :debug
+	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
+	.debug_aranges 0 : { *(.debug_aranges); } :debug
+	.debug_info 0 : { *(.debug_info); } :debug
+	.debug_line 0 : { *(.debug_line); } :debug
+	.debug_loc 0 : { *(.debug_loc); } :debug
+	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
+	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
+	.debug_ranges 0 : { *(.debug_ranges); } :debug
+	.debug_str 0 : { *(.debug_str); } :debug
+#endif
 	
 	/DISCARD/ : {
Index: pace/lib/c/arch/ia32/include/limits.h
===================================================================
--- uspace/lib/c/arch/ia32/include/limits.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 libcia32
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ia32__LIMITS_H_
-#define LIBC_ia32__LIMITS_H_
-
-# define LONG_MIN MIN_INT32
-# define LONG_MAX MAX_INT32
-# define ULONG_MIN MIN_UINT32
-# define ULONG_MAX MAX_UINT32
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/arch/ia64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia64/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/arch/ia64/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -9,19 +9,21 @@
 SECTIONS {
 	. = 0x4000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		_gp = .;
 		*(.got*);
-	} :data	
+	} :data
+	
 	.data : {
 		*(.opd);
@@ -29,4 +31,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -37,5 +40,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
@@ -44,10 +49,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
- 
+	
 	/DISCARD/ : {
 		*(*);
-        }
+	}
 }
Index: pace/lib/c/arch/ia64/include/limits.h
===================================================================
--- uspace/lib/c/arch/ia64/include/limits.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 libcia64	
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ia64_LIMITS_H_
-#define LIBC_ia64_LIMITS_H_
-
-# define LONG_MIN MIN_INT64
-# define LONG_MAX MAX_INT64
-# define ULONG_MIN MIN_UINT64
-# define ULONG_MAX MAX_UINT64
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/arch/mips32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/mips32/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/arch/mips32/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -13,43 +13,46 @@
 		*(.init);
 	} :text
+	
 	.text : {
-	        *(.text);
+		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.data : {
 		*(.data);
 		*(.data.rel*);
 	} :data
-
+	
 	.got : {
 		_gp = .;
 		*(.got);
 	} :data
-
+	
 	.tdata : {
 		_tdata_start = .;
 		*(.tdata);
 		_tdata_end = .;
+	} :data
+	
+	.tbss : {
 		_tbss_start = .;
 		*(.tbss);
 		_tbss_end = .;
 	} :data
-	_tls_alignment = ALIGNOF(.tdata);
-
+	
+	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.sbss : {
 		*(.scommon);
 		*(.sbss);
-	}	
+	}
+	
 	.bss : {
 		*(.bss);
 		*(COMMON);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
-
+	
 	/DISCARD/ : {
 		*(*);
Index: pace/lib/c/arch/mips32/include/limits.h
===================================================================
--- uspace/lib/c/arch/mips32/include/limits.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 libcmips32	
- * @{
- */
-/** @file
- * @ingroup libcmips32eb	
- */
-
-#ifndef LIBC_mips32__LIMITS_H_
-#define LIBC_mips32__LIMITS_H_
-
-# define LONG_MIN MIN_INT32
-# define LONG_MAX MAX_INT32
-# define ULONG_MIN MIN_UINT32
-# define ULONG_MAX MAX_UINT32
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/arch/mips32/src/entry.s
===================================================================
--- uspace/lib/c/arch/mips32/src/entry.s	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/arch/mips32/src/entry.s	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -29,6 +29,7 @@
 .text
 .section .init, "ax"
+
 .global __entry
-.global __entry_driver
+
 .set noreorder
 .option pic2
@@ -57,6 +58,2 @@
 	nop
 .end
-
-# Alignment of output section data to 0x4000
-.section .data
-.align 14
Index: pace/lib/c/arch/mips32eb/include/limits.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/limits.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../../mips32/include/limits.h
Index: uspace/lib/c/arch/ppc32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ppc32/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/arch/ppc32/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -9,19 +9,21 @@
 SECTIONS {
 	. = 0x1000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x1000;
-
+	
 	.data : {
 		*(.data);
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -32,5 +34,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
@@ -38,11 +42,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: pace/lib/c/arch/ppc32/include/limits.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/limits.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 libcppc32	
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ppc32_LIMITS_H_
-#define LIBC_ppc32_LIMITS_H_
-
-#define LONG_MIN MIN_INT32
-#define LONG_MAX MAX_INT32
-#define ULONG_MIN MIN_UINT32
-#define ULONG_MAX MAX_UINT32
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/arch/sparc64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/sparc64/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/arch/sparc64/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -9,23 +9,26 @@
 SECTIONS {
 	. = 0x4000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		 _gp = .;
 		 *(.got*);
 	} :data
+	
 	.data : {
 		*(.data);
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -36,5 +39,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
@@ -42,11 +47,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: pace/lib/c/arch/sparc64/include/limits.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/limits.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 libcsparc64	
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_sparc64_LIMITS_H_
-#define LIBC_sparc64_LIMITS_H_
-
-#define LONG_MIN MIN_INT64
-#define LONG_MAX MAX_INT64
-#define ULONG_MIN MIN_UINT64
-#define ULONG_MAX MAX_UINT64
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/generic/as.c
===================================================================
--- uspace/lib/c/generic/as.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/generic/as.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -40,7 +40,5 @@
 #include <bitops.h>
 #include <malloc.h>
-
-/** Last position allocated by as_get_mappable_page */
-static uintptr_t last_allocated = 0;
+#include "private/libc.h"
 
 /** Create address space area.
@@ -103,27 +101,15 @@
 }
 
-/** Return pointer to some unmapped area, where fits new as_area
+/** Return pointer to unmapped address space area
  *
  * @param size Requested size of the allocation.
  *
- * @return pointer to the beginning
+ * @return Pointer to the beginning of unmapped address space area.
  *
  */
 void *as_get_mappable_page(size_t size)
 {
-	if (size == 0)
-		return NULL;
-	
-	size_t sz = 1 << (fnzb(size - 1) + 1);
-	if (last_allocated == 0)
-		last_allocated = get_max_heap_addr();
-	
-	/*
-	 * Make sure we allocate from naturally aligned address.
-	 */
-	uintptr_t res = ALIGN_UP(last_allocated, sz);
-	last_allocated = res + ALIGN_UP(size, PAGE_SIZE);
-	
-	return ((void *) res);
+	return (void *) __SYSCALL2(SYS_AS_GET_UNMAPPED_AREA,
+	    (sysarg_t) __entry, (sysarg_t) size);
 }
 
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/generic/async.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -430,4 +430,10 @@
 	
 	fid_t fid = fibril_create(notification_fibril, msg);
+	if (fid == 0) {
+		free(msg);
+		futex_up(&async_futex);
+		return false;
+	}
+	
 	fibril_add_ready(fid);
 	
@@ -681,8 +687,10 @@
 	conn->wdata.fid = fibril_create(connection_fibril, conn);
 	
-	if (!conn->wdata.fid) {
+	if (conn->wdata.fid == 0) {
 		free(conn);
+		
 		if (callid)
 			ipc_answer_0(callid, ENOMEM);
+		
 		return (uintptr_t) NULL;
 	}
@@ -853,5 +861,6 @@
 {
 	fid_t fid = fibril_create(async_manager_fibril, NULL);
-	fibril_add_manager(fid);
+	if (fid != 0)
+		fibril_add_manager(fid);
 }
 
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/generic/devman.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -123,9 +123,13 @@
 }
 
-static int devman_send_match_id(int phone, match_id_t *match_id) \
-{
-	ipc_call_t answer;
-	aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score, &answer);
-	int retval = async_data_write_start(phone, match_id->id, str_size(match_id->id));
+static int devman_send_match_id(int phone, match_id_t *match_id)
+{
+	ipc_call_t answer;
+
+	aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score,
+	    &answer);
+	int retval = async_data_write_start(phone, match_id->id,
+	    str_size(match_id->id));
+
 	async_wait_for(req, NULL);
 	return retval;
@@ -133,26 +137,43 @@
 
 
-static int devman_send_match_ids(int phone, match_id_list_t *match_ids) 
+static int devman_send_match_ids(int phone, match_id_list_t *match_ids)
 {
 	link_t *link = match_ids->ids.next;
 	match_id_t *match_id = NULL;
 	int ret = EOK;
-	
+
 	while (link != &match_ids->ids) {
 		match_id = list_get_instance(link, match_id_t, link); 
-		if (EOK != (ret = devman_send_match_id(phone, match_id))) 
-		{
-			printf("Driver failed to send match id, error number = %d\n", ret);
-			return ret;			
-		}
+		ret = devman_send_match_id(phone, match_id);
+		if (ret != EOK) {
+			printf("Driver failed to send match id, error %d\n",
+			    ret);
+			return ret;
+		}
+
 		link = link->next;
 	}
-	return ret;	
-}
-
-int devman_child_device_register(
-	const char *name, match_id_list_t *match_ids, devman_handle_t parent_handle, devman_handle_t *handle)
-{		
+
+	return ret;
+}
+
+/** Add function to a device.
+ *
+ * Request devman to add a new function to the specified device owned by
+ * this driver task.
+ *
+ * @param name		Name of the new function
+ * @param ftype		Function type, fun_inner or fun_exposed
+ * @param match_ids	Match IDs (should be empty for fun_exposed)
+ * @param devh		Devman handle of the device
+ * @param funh		Place to store handle of the new function
+ *
+ * @return		EOK on success or negative error code.
+ */
+int devman_add_function(const char *name, fun_type_t ftype,
+    match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
+{
 	int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
+	int fun_handle;
 	
 	if (phone < 0)
@@ -161,7 +182,9 @@
 	async_serialize_start();
 	
-	int match_count = list_count(&match_ids->ids);	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAN_ADD_CHILD_DEVICE, parent_handle, match_count, &answer);
+	int match_count = list_count(&match_ids->ids);
+	ipc_call_t answer;
+
+	aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
+	    devh, match_count, &answer);
 
 	sysarg_t retval = async_data_write_start(phone, name, str_size(name));
@@ -178,18 +201,16 @@
 	async_serialize_end();
 	
-	if (retval != EOK) {
-		if (handle != NULL) {
-			*handle = -1;
-		}
-		return retval;
-	}	
-	
-	if (handle != NULL)
-		*handle = (int) IPC_GET_ARG1(answer);	
-		
-	return retval;
-}
-
-int devman_add_device_to_class(devman_handle_t devman_handle, const char *class_name)
+	if (retval == EOK)
+		fun_handle = (int) IPC_GET_ARG1(answer);
+	else
+		fun_handle = -1;
+	
+	*funh = fun_handle;
+
+	return retval;
+}
+
+int devman_add_device_to_class(devman_handle_t devman_handle,
+    const char *class_name)
 {
 	int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
@@ -200,7 +221,9 @@
 	async_serialize_start();
 	ipc_call_t answer;
-	aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS, devman_handle, &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, class_name, str_size(class_name));
+	aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS,
+	    devman_handle, &answer);
+	
+	sysarg_t retval = async_data_write_start(phone, class_name,
+	    str_size(class_name));
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
@@ -212,5 +235,5 @@
 	async_serialize_end();
 	
-	return retval;	
+	return retval;
 }
 
@@ -265,5 +288,6 @@
 }
 
-int devman_device_get_handle(const char *pathname, devman_handle_t *handle, unsigned int flags)
+int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
+    unsigned int flags)
 {
 	int phone = devman_get_phone(DEVMAN_CLIENT, flags);
@@ -278,5 +302,6 @@
 	    &answer);
 	
-	sysarg_t retval = async_data_write_start(phone, pathname, str_size(pathname));
+	sysarg_t retval = async_data_write_start(phone, pathname,
+	    str_size(pathname));
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/generic/fibril.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -115,4 +115,6 @@
 	fibril->retval = 0;
 	fibril->flags = 0;
+	
+	fibril->waits_for = NULL;
 	
 	return fibril;
@@ -276,6 +278,4 @@
 	fibril->arg = arg;
 
-	fibril->waits_for = NULL;
-	
 	context_save(&fibril->ctx);
 	context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack,
Index: uspace/lib/c/generic/loader.c
===================================================================
--- uspace/lib/c/generic/loader.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/generic/loader.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -160,4 +160,5 @@
 	int rc = async_data_write_start(ldr->phone_id, (void *) pa, pa_len);
 	if (rc != EOK) {
+		free(pa);
 		async_wait_for(req, NULL);
 		return rc;
Index: uspace/lib/c/generic/malloc.c
===================================================================
--- uspace/lib/c/generic/malloc.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/generic/malloc.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -47,33 +47,77 @@
 #include "private/malloc.h"
 
-/* Magic used in heap headers. */
-#define HEAP_BLOCK_HEAD_MAGIC  0xBEEF0101
-
-/* Magic used in heap footers. */
-#define HEAP_BLOCK_FOOT_MAGIC  0xBEEF0202
-
-/** Allocation alignment (this also covers the alignment of fields
-    in the heap header and footer) */
+/** Magic used in heap headers. */
+#define HEAP_BLOCK_HEAD_MAGIC  UINT32_C(0xBEEF0101)
+
+/** Magic used in heap footers. */
+#define HEAP_BLOCK_FOOT_MAGIC  UINT32_C(0xBEEF0202)
+
+/** Magic used in heap descriptor. */
+#define HEAP_AREA_MAGIC  UINT32_C(0xBEEFCAFE)
+
+/** Allocation alignment.
+ *
+ * This also covers the alignment of fields
+ * in the heap header and footer.
+ *
+ */
 #define BASE_ALIGN  16
 
-/**
- * Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures
- */
-#define MAX_HEAP_SIZE  (sizeof(uintptr_t) << 28)
-
-/**
- *
- */
-#define STRUCT_OVERHEAD  (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
-
-/**
- * Calculate real size of a heap block (with header and footer)
+/** Overhead of each heap block. */
+#define STRUCT_OVERHEAD \
+	(sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
+
+/** Calculate real size of a heap block.
+ *
+ * Add header and footer size.
+ *
  */
 #define GROSS_SIZE(size)  ((size) + STRUCT_OVERHEAD)
 
-/**
- * Calculate net size of a heap block (without header and footer)
+/** Calculate net size of a heap block.
+ *
+ * Subtract header and footer size.
+ *
  */
 #define NET_SIZE(size)  ((size) - STRUCT_OVERHEAD)
+
+/** Get first block in heap area.
+ *
+ */
+#define AREA_FIRST_BLOCK(area) \
+	(ALIGN_UP(((uintptr_t) (area)) + sizeof(heap_area_t), BASE_ALIGN))
+
+/** Get footer in heap block.
+ *
+ */
+#define BLOCK_FOOT(head) \
+	((heap_block_foot_t *) \
+	    (((uintptr_t) head) + head->size - sizeof(heap_block_foot_t)))
+
+/** Heap area.
+ *
+ * The memory managed by the heap allocator is divided into
+ * multiple discontinuous heaps. Each heap is represented
+ * by a separate address space area which has this structure
+ * at its very beginning.
+ *
+ */
+typedef struct heap_area {
+	/** Start of the heap area (including this structure)
+	 *
+	 * Aligned on page boundary.
+	 *
+	 */
+	void *start;
+	
+	/** End of the heap area (aligned on page boundary) */
+	void *end;
+	
+	/** Next heap area */
+	struct heap_area *next;
+	
+	/** A magic value */
+	uint32_t magic;
+} heap_area_t;
 
 /** Header of a heap block
@@ -87,4 +131,7 @@
 	bool free;
 	
+	/** Heap area this block belongs to */
+	heap_area_t *area;
+	
 	/* A magic value to detect overwrite of heap header */
 	uint32_t magic;
@@ -102,25 +149,19 @@
 } heap_block_foot_t;
 
-/** Linker heap symbol */
-extern char _heap;
+/** First heap area */
+static heap_area_t *first_heap_area = NULL;
+
+/** Last heap area */
+static heap_area_t *last_heap_area = NULL;
+
+/** Next heap block to examine (next fit algorithm) */
+static heap_block_head_t *next = NULL;
 
 /** Futex for thread-safe heap manipulation */
 static futex_t malloc_futex = FUTEX_INITIALIZER;
 
-/** Address of heap start */
-static void *heap_start = 0;
-
-/** Address of heap end */
-static void *heap_end = 0;
-
-/** Maximum heap size */
-static size_t max_heap_size = (size_t) -1;
-
-/** Current number of pages of heap area */
-static size_t heap_pages = 0;
-
 /** Initialize a heap block
  *
- * Fills in the structures related to a heap block.
+ * Fill in the structures related to a heap block.
  * Should be called only inside the critical section.
  *
@@ -128,16 +169,18 @@
  * @param size Size of the block including the header and the footer.
  * @param free Indication of a free block.
- *
- */
-static void block_init(void *addr, size_t size, bool free)
+ * @param area Heap area the block belongs to.
+ *
+ */
+static void block_init(void *addr, size_t size, bool free, heap_area_t *area)
 {
 	/* Calculate the position of the header and the footer */
 	heap_block_head_t *head = (heap_block_head_t *) addr;
-	heap_block_foot_t *foot =
-	    (heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t));
 	
 	head->size = size;
 	head->free = free;
+	head->area = area;
 	head->magic = HEAP_BLOCK_HEAD_MAGIC;
+	
+	heap_block_foot_t *foot = BLOCK_FOOT(head);
 	
 	foot->size = size;
@@ -160,6 +203,5 @@
 	assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
 	
-	heap_block_foot_t *foot =
-	    (heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t));
+	heap_block_foot_t *foot = BLOCK_FOOT(head);
 	
 	assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
@@ -167,49 +209,130 @@
 }
 
-/** Increase the heap area size
- *
- * Should be called only inside the critical section.
- *
- * @param size Number of bytes to grow the heap by.
- *
- */
-static bool grow_heap(size_t size)
+/** Check a heap area structure
+ *
+ * @param addr Address of the heap area.
+ *
+ */
+static void area_check(void *addr)
+{
+	heap_area_t *area = (heap_area_t *) addr;
+	
+	assert(area->magic == HEAP_AREA_MAGIC);
+	assert(area->start < area->end);
+	assert(((uintptr_t) area->start % PAGE_SIZE) == 0);
+	assert(((uintptr_t) area->end % PAGE_SIZE) == 0);
+}
+
+/** Create new heap area
+ *
+ * @param start Preffered starting address of the new area.
+ * @param size  Size of the area.
+ *
+ */
+static bool area_create(size_t size)
+{
+	void *start = as_get_mappable_page(size);
+	if (start == NULL)
+		return false;
+	
+	/* Align the heap area on page boundary */
+	void *astart = (void *) ALIGN_UP((uintptr_t) start, PAGE_SIZE);
+	size_t asize = ALIGN_UP(size, PAGE_SIZE);
+	
+	astart = as_area_create(astart, asize, AS_AREA_WRITE | AS_AREA_READ);
+	if (astart == (void *) -1)
+		return false;
+	
+	heap_area_t *area = (heap_area_t *) astart;
+	
+	area->start = astart;
+	area->end = (void *)
+	    ALIGN_DOWN((uintptr_t) astart + asize, BASE_ALIGN);
+	area->next = NULL;
+	area->magic = HEAP_AREA_MAGIC;
+	
+	void *block = (void *) AREA_FIRST_BLOCK(area);
+	size_t bsize = (size_t) (area->end - block);
+	
+	block_init(block, bsize, true, area);
+	
+	if (last_heap_area == NULL) {
+		first_heap_area = area;
+		last_heap_area = area;
+	} else {
+		last_heap_area->next = area;
+		last_heap_area = area;
+	}
+	
+	return true;
+}
+
+/** Try to enlarge a heap area
+ *
+ * @param area Heap area to grow.
+ * @param size Gross size of item to allocate (bytes).
+ *
+ */
+static bool area_grow(heap_area_t *area, size_t size)
 {
 	if (size == 0)
+		return true;
+	
+	area_check(area);
+	
+	size_t asize = ALIGN_UP((size_t) (area->end - area->start) + size,
+	    PAGE_SIZE);
+	
+	/* New heap area size */
+	void *end = (void *)
+	    ALIGN_DOWN((uintptr_t) area->start + asize, BASE_ALIGN);
+	
+	/* Check for overflow */
+	if (end < area->start)
 		return false;
-
-	if ((heap_start + size < heap_start) || (heap_end + size < heap_end))
+	
+	/* Resize the address space area */
+	int ret = as_area_resize(area->start, asize, 0);
+	if (ret != EOK)
 		return false;
 	
-	size_t heap_size = (size_t) (heap_end - heap_start);
-	
-	if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size))
-		return false;
-	
-	size_t pages = (size - 1) / PAGE_SIZE + 1;
-	
-	if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0)
-	    == EOK) {
-		void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) +
-		    (heap_pages + pages) * PAGE_SIZE, BASE_ALIGN);
-		block_init(heap_end, end - heap_end, true);
-		heap_pages += pages;
-		heap_end = end;
+	/* Add new free block */
+	block_init(area->end, (size_t) (end - area->end), true, area);
+	
+	/* Update heap area parameters */
+	area->end = end;
+	
+	return true;
+}
+
+/** Try to enlarge any of the heap areas
+ *
+ * @param size Gross size of item to allocate (bytes).
+ *
+ */
+static bool heap_grow(size_t size)
+{
+	if (size == 0)
 		return true;
-	}
-	
-	return false;
-}
-
-/** Decrease the heap area
- *
- * Should be called only inside the critical section.
- *
- * @param size Number of bytes to shrink the heap by.
- *
- */
-static void shrink_heap(void)
-{
-	// TODO
+	
+	/* First try to enlarge some existing area */
+	heap_area_t *area;
+	for (area = first_heap_area; area != NULL; area = area->next) {
+		if (area_grow(area, size))
+			return true;
+	}
+	
+	/* Eventually try to create a new area */
+	return area_create(AREA_FIRST_BLOCK(size));
+}
+
+/** Try to shrink heap space
+ *
+ * In all cases the next pointer is reset.
+ *
+ */
+static void heap_shrink(void)
+{
+	next = NULL;
 }
 
@@ -223,33 +346,6 @@
 void __malloc_init(void)
 {
-	if (!as_area_create((void *) &_heap, PAGE_SIZE,
-	    AS_AREA_WRITE | AS_AREA_READ))
+	if (!area_create(PAGE_SIZE))
 		abort();
-	
-	heap_pages = 1;
-	heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN);
-	heap_end =
-	    (void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN);
-	
-	/* Make the entire area one large block. */
-	block_init(heap_start, heap_end - heap_start, true);
-}
-
-/** Get maximum heap address
- *
- */
-uintptr_t get_max_heap_addr(void)
-{
-	futex_down(&malloc_futex);
-	
-	if (max_heap_size == (size_t) -1)
-		max_heap_size =
-		    max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE);
-	
-	uintptr_t max_heap_addr = (uintptr_t) heap_start + max_heap_size;
-	
-	futex_up(&malloc_futex);
-	
-	return max_heap_addr;
 }
 
@@ -273,6 +369,6 @@
 		/* Block big enough -> split. */
 		void *next = ((void *) cur) + size;
-		block_init(next, cur->size - size, true);
-		block_init(cur, size, false);
+		block_init(next, cur->size - size, true, cur->area);
+		block_init(cur, size, false, cur->area);
 	} else {
 		/* Block too small -> use as is. */
@@ -281,43 +377,53 @@
 }
 
-/** Allocate a memory block
+/** Allocate memory from heap area starting from given block
  *
  * Should be called only inside the critical section.
- *
- * @param size  The size of the block to allocate.
- * @param align Memory address alignment.
- *
- * @return the address of the block or NULL when not enough memory.
- *
- */
-static void *malloc_internal(const size_t size, const size_t align)
-{
-	if (align == 0)
-		return NULL;
-	
-	size_t falign = lcm(align, BASE_ALIGN);
-	size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
-	
-	bool grown = false;
-	void *result;
-	
-loop:
-	result = NULL;
-	heap_block_head_t *cur = (heap_block_head_t *) heap_start;
-	
-	while ((result == NULL) && ((void *) cur < heap_end)) {
+ * As a side effect this function also sets the current
+ * pointer on successful allocation.
+ *
+ * @param area        Heap area where to allocate from.
+ * @param first_block Starting heap block.
+ * @param final_block Heap block where to finish the search
+ *                    (may be NULL).
+ * @param real_size   Gross number of bytes to allocate.
+ * @param falign      Physical alignment of the block.
+ *
+ * @return Address of the allocated block or NULL on not enough memory.
+ *
+ */
+static void *malloc_area(heap_area_t *area, heap_block_head_t *first_block,
+    heap_block_head_t *final_block, size_t real_size, size_t falign)
+{
+	area_check((void *) area);
+	assert((void *) first_block >= (void *) AREA_FIRST_BLOCK(area));
+	assert((void *) first_block < area->end);
+	
+	heap_block_head_t *cur;
+	for (cur = first_block; (void *) cur < area->end;
+	    cur = (heap_block_head_t *) (((void *) cur) + cur->size)) {
 		block_check(cur);
+		
+		/* Finish searching on the final block */
+		if ((final_block != NULL) && (cur == final_block))
+			break;
 		
 		/* Try to find a block that is free and large enough. */
 		if ((cur->free) && (cur->size >= real_size)) {
-			/* We have found a suitable block.
-			   Check for alignment properties. */
-			void *addr = ((void *) cur) + sizeof(heap_block_head_t);
-			void *aligned = (void *) ALIGN_UP(addr, falign);
+			/*
+			 * We have found a suitable block.
+			 * Check for alignment properties.
+			 */
+			void *addr = (void *)
+			    ((uintptr_t) cur + sizeof(heap_block_head_t));
+			void *aligned = (void *)
+			    ALIGN_UP((uintptr_t) addr, falign);
 			
 			if (addr == aligned) {
 				/* Exact block start including alignment. */
 				split_mark(cur, real_size);
-				result = addr;
+				
+				next = cur;
+				return addr;
 			} else {
 				/* Block start has to be aligned */
@@ -325,15 +431,19 @@
 				
 				if (cur->size >= real_size + excess) {
-					/* The current block is large enough to fit
-					   data in including alignment */
-					if ((void *) cur > heap_start) {
-						/* There is a block before the current block.
-						   This previous block can be enlarged to compensate
-						   for the alignment excess */
-						heap_block_foot_t *prev_foot =
-						    ((void *) cur) - sizeof(heap_block_foot_t);
+					/*
+					 * The current block is large enough to fit
+					 * data in (including alignment).
+					 */
+					if ((void *) cur > (void *) AREA_FIRST_BLOCK(area)) {
+						/*
+						 * There is a block before the current block.
+						 * This previous block can be enlarged to
+						 * compensate for the alignment excess.
+						 */
+						heap_block_foot_t *prev_foot = (heap_block_foot_t *)
+						    ((void *) cur - sizeof(heap_block_foot_t));
 						
-						heap_block_head_t *prev_head =
-						    (heap_block_head_t *) (((void *) cur) - prev_foot->size);
+						heap_block_head_t *prev_head = (heap_block_head_t *)
+						    ((void *) cur - prev_foot->size);
 						
 						block_check(prev_head);
@@ -342,25 +452,38 @@
 						heap_block_head_t *next_head = ((void *) cur) + excess;
 						
-						if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) {
-							/* The previous block is not free and there is enough
-							   space to fill in a new free block between the previous
-							   and current block */
-							block_init(cur, excess, true);
+						if ((!prev_head->free) &&
+						    (excess >= STRUCT_OVERHEAD)) {
+							/*
+							 * The previous block is not free and there
+							 * is enough free space left to fill in
+							 * a new free block between the previous
+							 * and current block.
+							 */
+							block_init(cur, excess, true, area);
 						} else {
-							/* The previous block is free (thus there is no need to
-							   induce additional fragmentation to the heap) or the
-							   excess is small, thus just enlarge the previous block */
-							block_init(prev_head, prev_head->size + excess, prev_head->free);
+							/*
+							 * The previous block is free (thus there
+							 * is no need to induce additional
+							 * fragmentation to the heap) or the
+							 * excess is small. Therefore just enlarge
+							 * the previous block.
+							 */
+							block_init(prev_head, prev_head->size + excess,
+							    prev_head->free, area);
 						}
 						
-						block_init(next_head, reduced_size, true);
+						block_init(next_head, reduced_size, true, area);
 						split_mark(next_head, real_size);
-						result = aligned;
-						cur = next_head;
+						
+						next = next_head;
+						return aligned;
 					} else {
-						/* The current block is the first block on the heap.
-						   We have to make sure that the alignment excess
-						   is large enough to fit a new free block just
-						   before the current block */
+						/*
+						 * The current block is the first block
+						 * in the heap area. We have to make sure
+						 * that the alignment excess is large enough
+						 * to fit a new free block just before the
+						 * current block.
+						 */
 						while (excess < STRUCT_OVERHEAD) {
 							aligned += falign;
@@ -371,10 +494,14 @@
 						if (cur->size >= real_size + excess) {
 							size_t reduced_size = cur->size - excess;
-							cur = (heap_block_head_t *) (heap_start + excess);
+							cur = (heap_block_head_t *)
+							    (AREA_FIRST_BLOCK(area) + excess);
 							
-							block_init(heap_start, excess, true);
-							block_init(cur, reduced_size, true);
+							block_init((void *) AREA_FIRST_BLOCK(area), excess,
+							    true, area);
+							block_init(cur, reduced_size, true, area);
 							split_mark(cur, real_size);
-							result = aligned;
+							
+							next = cur;
+							return aligned;
 						}
 					}
@@ -382,17 +509,67 @@
 			}
 		}
-		
-		/* Advance to the next block. */
-		cur = (heap_block_head_t *) (((void *) cur) + cur->size);
-	}
-	
-	if ((result == NULL) && (!grown)) {
-		if (grow_heap(real_size)) {
-			grown = true;
+	}
+	
+	return NULL;
+}
+
+/** Allocate a memory block
+ *
+ * Should be called only inside the critical section.
+ *
+ * @param size  The size of the block to allocate.
+ * @param align Memory address alignment.
+ *
+ * @return Address of the allocated block or NULL on not enough memory.
+ *
+ */
+static void *malloc_internal(const size_t size, const size_t align)
+{
+	assert(first_heap_area != NULL);
+	
+	if (align == 0)
+		return NULL;
+	
+	size_t falign = lcm(align, BASE_ALIGN);
+	size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
+	
+	bool retry = false;
+	heap_block_head_t *split;
+	
+loop:
+	
+	/* Try the next fit approach */
+	split = next;
+	
+	if (split != NULL) {
+		void *addr = malloc_area(split->area, split, NULL, real_size,
+		    falign);
+		
+		if (addr != NULL)
+			return addr;
+	}
+	
+	/* Search the entire heap */
+	heap_area_t *area;
+	for (area = first_heap_area; area != NULL; area = area->next) {
+		heap_block_head_t *first = (heap_block_head_t *)
+		    AREA_FIRST_BLOCK(area);
+		
+		void *addr = malloc_area(area, first, split, real_size,
+		    falign);
+		
+		if (addr != NULL)
+			return addr;
+	}
+	
+	if (!retry) {
+		/* Try to grow the heap space */
+		if (heap_grow(real_size)) {
+			retry = true;
 			goto loop;
 		}
 	}
 	
-	return result;
+	return NULL;
 }
 
@@ -473,9 +650,12 @@
 	    (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
 	
-	assert((void *) head >= heap_start);
-	assert((void *) head < heap_end);
-	
 	block_check(head);
 	assert(!head->free);
+	
+	heap_area_t *area = head->area;
+	
+	area_check(area);
+	assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
+	assert((void *) head < area->end);
 	
 	void *ptr = NULL;
@@ -487,29 +667,34 @@
 		/* Shrink */
 		if (orig_size - real_size >= STRUCT_OVERHEAD) {
-			/* Split the original block to a full block
-			   and a trailing free block */
-			block_init((void *) head, real_size, false);
+			/*
+			 * Split the original block to a full block
+			 * and a trailing free block.
+			 */
+			block_init((void *) head, real_size, false, area);
 			block_init((void *) head + real_size,
-			    orig_size - real_size, true);
-			shrink_heap();
+			    orig_size - real_size, true, area);
+			heap_shrink();
 		}
 		
 		ptr = ((void *) head) + sizeof(heap_block_head_t);
 	} else {
-		/* Look at the next block. If it is free and the size is
-		   sufficient then merge the two. Otherwise just allocate
-		   a new block, copy the original data into it and
-		   free the original block. */
+		/*
+		 * Look at the next block. If it is free and the size is
+		 * sufficient then merge the two. Otherwise just allocate
+		 * a new block, copy the original data into it and
+		 * free the original block.
+		 */
 		heap_block_head_t *next_head =
 		    (heap_block_head_t *) (((void *) head) + head->size);
 		
-		if (((void *) next_head < heap_end) &&
+		if (((void *) next_head < area->end) &&
 		    (head->size + next_head->size >= real_size) &&
 		    (next_head->free)) {
 			block_check(next_head);
-			block_init(head, head->size + next_head->size, false);
+			block_init(head, head->size + next_head->size, false, area);
 			split_mark(head, real_size);
 			
 			ptr = ((void *) head) + sizeof(heap_block_head_t);
+			next = NULL;
 		} else
 			reloc = true;
@@ -542,9 +727,12 @@
 	    = (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
 	
-	assert((void *) head >= heap_start);
-	assert((void *) head < heap_end);
-	
 	block_check(head);
 	assert(!head->free);
+	
+	heap_area_t *area = head->area;
+	
+	area_check(area);
+	assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
+	assert((void *) head < area->end);
 	
 	/* Mark the block itself as free. */
@@ -555,12 +743,12 @@
 	    = (heap_block_head_t *) (((void *) head) + head->size);
 	
-	if ((void *) next_head < heap_end) {
+	if ((void *) next_head < area->end) {
 		block_check(next_head);
 		if (next_head->free)
-			block_init(head, head->size + next_head->size, true);
+			block_init(head, head->size + next_head->size, true, area);
 	}
 	
 	/* Look at the previous block. If it is free, merge the two. */
-	if ((void *) head > heap_start) {
+	if ((void *) head > (void *) AREA_FIRST_BLOCK(area)) {
 		heap_block_foot_t *prev_foot =
 		    (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
@@ -572,8 +760,9 @@
 		
 		if (prev_head->free)
-			block_init(prev_head, prev_head->size + head->size, true);
-	}
-	
-	shrink_heap();
+			block_init(prev_head, prev_head->size + head->size, true,
+			    area);
+	}
+	
+	heap_shrink();
 	
 	futex_up(&malloc_futex);
Index: uspace/lib/c/generic/private/libc.h
===================================================================
--- uspace/lib/c/generic/private/libc.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/generic/private/libc.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -36,6 +36,7 @@
 #define LIBC_PRIVATE_LIBC_H_
 
+extern void __entry(void);
+extern void __main(void *) __attribute__((noreturn));
 extern int main(int, char *[]);
-extern void __main(void *) __attribute__((noreturn));
 
 #endif
Index: uspace/lib/c/include/as.h
===================================================================
--- uspace/lib/c/include/as.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/include/as.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -41,4 +41,17 @@
 #include <libarch/config.h>
 
+static inline size_t SIZE2PAGES(size_t size)
+{
+	if (size == 0)
+		return 0;
+	
+	return (size_t) ((size - 1) >> PAGE_WIDTH) + 1;
+}
+
+static inline size_t PAGES2SIZE(size_t pages)
+{
+	return (size_t) (pages << PAGE_WIDTH);
+}
+
 extern void *as_area_create(void *address, size_t size, int flags);
 extern int as_area_resize(void *address, size_t size, int flags);
Index: uspace/lib/c/include/devman.h
===================================================================
--- uspace/lib/c/include/devman.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/include/devman.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -45,5 +45,5 @@
 
 extern int devman_driver_register(const char *, async_client_conn_t);
-extern int devman_child_device_register(const char *, match_id_list_t *,
+extern int devman_add_function(const char *, fun_type_t, match_id_list_t *,
     devman_handle_t, devman_handle_t *);
 
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/include/ipc/devman.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -42,4 +42,13 @@
 
 typedef sysarg_t devman_handle_t;
+
+typedef enum {
+	/** Invalid value for debugging purposes */
+	fun_invalid = 0,
+	/** Function to which child devices attach */
+	fun_inner,
+	/** Fuction exported to external clients (leaf function) */
+	fun_exposed
+} fun_type_t;
 
 /** Ids of device models used for device-to-driver matching.
@@ -127,5 +136,5 @@
 typedef enum {
 	DEVMAN_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
-	DEVMAN_ADD_CHILD_DEVICE,
+	DEVMAN_ADD_FUNCTION,
 	DEVMAN_ADD_MATCH_ID,
 	DEVMAN_ADD_DEVICE_TO_CLASS
Index: pace/lib/c/include/limits.h
===================================================================
--- uspace/lib/c/include/limits.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,74 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_LIMITS_H_
-#define LIBC_LIMITS_H_
-
-#include <stdint.h>
-#include <libarch/limits.h>
-
-/* char */
-#define SCHAR_MIN MIN_INT8
-#define SCHAR_MAX MAX_INT8
-#define UCHAR_MIN MIN_UINT8
-#define UCHAR_MAX MAX_UINT8
-
-#ifdef __CHAR_UNSIGNED__
-# define CHAR_MIN UCHAR_MIN
-# define CHAR_MAX UCHAR_MAX
-#else
-# define CHAR_MIN SCHAR_MIN
-# define CHAR_MAX SCHAR_MAX
-#endif
-
-/* short int */
-#define SHRT_MIN MIN_INT16
-#define SHRT_MAX MAX_INT16
-#define USHRT_MIN MIN_UINT16
-#define USHRT_MAX MAX_UINT16
-
-#define INT_MIN MIN_INT32
-#define INT_MAX MAX_INT32
-#define UINT_MIN MIN_UINT32
-#define UINT_MAX MAX_UINT32
-
-#define LLONG_MIN MIN_INT64
-#define LLONG_MAX MAX_INT64
-#define ULLONG_MIN MIN_UINT64
-#define ULLONG_MAX MAX_UINT64
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/malloc.h
===================================================================
--- uspace/lib/c/include/malloc.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/include/malloc.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -38,6 +38,4 @@
 #include <sys/types.h>
 
-extern uintptr_t get_max_heap_addr(void);
-
 extern void *malloc(const size_t size)
     __attribute__((malloc));
Index: uspace/lib/c/include/unistd.h
===================================================================
--- uspace/lib/c/include/unistd.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/c/include/unistd.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -44,6 +44,4 @@
 #endif
 
-#define getpagesize()  (PAGE_SIZE)
-
 #ifndef SEEK_SET
 	#define SEEK_SET  0
@@ -57,4 +55,6 @@
 	#define SEEK_END  2
 #endif
+
+#define getpagesize()  (PAGE_SIZE)
 
 extern int dup2(int oldfd, int newfd);
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/drv/generic/driver.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -49,9 +50,11 @@
 #include <errno.h>
 #include <inttypes.h>
+#include <devman.h>
 
 #include <ipc/driver.h>
 
 #include "dev_iface.h"
-#include "driver.h"
+#include "ddf/driver.h"
+#include "ddf/interrupt.h"
 
 /** Driver structure */
@@ -59,6 +62,6 @@
 
 /** Devices */
-LIST_INITIALIZE(devices);
-FIBRIL_MUTEX_INITIALIZE(devices_mutex);
+LIST_INITIALIZE(functions);
+FIBRIL_MUTEX_INITIALIZE(functions_mutex);
 
 /** Interrupts */
@@ -76,4 +79,8 @@
 };
 
+static ddf_dev_t *create_device(void);
+static void delete_device(ddf_dev_t *);
+static remote_handler_t *function_get_default_handler(ddf_fun_t *);
+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)
@@ -150,5 +157,5 @@
 
 interrupt_context_t *
-find_interrupt_context(interrupt_context_list_t *list, device_t *dev, int irq)
+find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
 {
 	fibril_mutex_lock(&list->mutex);
@@ -172,5 +179,5 @@
 
 int
-register_interrupt_handler(device_t *dev, int irq, interrupt_handler_t *handler,
+register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler,
     irq_code_t *pseudocode)
 {
@@ -195,5 +202,5 @@
 }
 
-int unregister_interrupt_handler(device_t *dev, int irq)
+int unregister_interrupt_handler(ddf_dev_t *dev, int irq)
 {
 	interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
@@ -209,35 +216,36 @@
 }
 
-static void add_to_devices_list(device_t *dev)
-{
-	fibril_mutex_lock(&devices_mutex);
-	list_append(&dev->link, &devices);
-	fibril_mutex_unlock(&devices_mutex);
-}
-
-static void remove_from_devices_list(device_t *dev)
-{
-	fibril_mutex_lock(&devices_mutex);
-	list_remove(&dev->link);
-	fibril_mutex_unlock(&devices_mutex);
-}
-
-static device_t *driver_get_device(link_t *devices, devman_handle_t handle)
-{
-	device_t *dev = NULL;
-	
-	fibril_mutex_lock(&devices_mutex);
-	link_t *link = devices->next;
-	
-	while (link != devices) {
-		dev = list_get_instance(link, device_t, link);
-		if (dev->handle == handle) {
-			fibril_mutex_unlock(&devices_mutex);
-			return dev;
+static void add_to_functions_list(ddf_fun_t *fun)
+{
+	fibril_mutex_lock(&functions_mutex);
+	list_append(&fun->link, &functions);
+	fibril_mutex_unlock(&functions_mutex);
+}
+
+static void remove_from_functions_list(ddf_fun_t *fun)
+{
+	fibril_mutex_lock(&functions_mutex);
+	list_remove(&fun->link);
+	fibril_mutex_unlock(&functions_mutex);
+}
+
+static ddf_fun_t *driver_get_function(link_t *functions, devman_handle_t handle)
+{
+	ddf_fun_t *fun = NULL;
+	
+	fibril_mutex_lock(&functions_mutex);
+	link_t *link = functions->next;
+	
+	while (link != functions) {
+		fun = list_get_instance(link, ddf_fun_t, link);
+		if (fun->handle == handle) {
+			fibril_mutex_unlock(&functions_mutex);
+			return fun;
 		}
+		
 		link = link->next;
 	}
 	
-	fibril_mutex_unlock(&devices_mutex);
+	fibril_mutex_unlock(&functions_mutex);
 	
 	return NULL;
@@ -250,14 +258,17 @@
 	
 	devman_handle_t dev_handle = IPC_GET_ARG1(*icall);
-    	devman_handle_t parent_dev_handle = IPC_GET_ARG2(*icall);
-	
-	device_t *dev = create_device();
+    	devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);
+	
+	ddf_dev_t *dev = create_device();
 	dev->handle = dev_handle;
-	
+
 	async_data_write_accept((void **) &dev_name, true, 0, 0, 0, 0);
 	dev->name = dev_name;
-	
-	add_to_devices_list(dev);
-	dev->parent = driver_get_device(&devices, parent_dev_handle);
+
+	/*
+	 * Currently not used, parent fun handle is stored in context
+	 * of the connection to the parent device driver.
+	 */
+	(void) parent_fun_handle;
 	
 	res = driver->driver_ops->add_device(dev);
@@ -268,5 +279,4 @@
 		printf("%s: failed to add a new device with handle = %" PRIun ".\n",
 		    driver->name, dev_handle);
-		remove_from_devices_list(dev);
 		delete_device(dev);
 	}
@@ -311,8 +321,8 @@
 	 */
 	devman_handle_t handle = IPC_GET_ARG2(*icall);
-	device_t *dev = driver_get_device(&devices, handle);
-
-	if (dev == NULL) {
-		printf("%s: driver_connection_gen error - no device with handle"
+	ddf_fun_t *fun = driver_get_function(&functions, handle);
+
+	if (fun == NULL) {
+		printf("%s: driver_connection_gen error - no function with handle"
 		    " %" PRIun " was found.\n", driver->name, handle);
 		async_answer_0(iid, ENOENT);
@@ -327,7 +337,7 @@
 	
 	int ret = EOK;
-	/* open the device */
-	if (dev->ops != NULL && dev->ops->open != NULL)
-		ret = (*dev->ops->open)(dev);
+	/* Open device function */
+	if (fun->ops != NULL && fun->ops->open != NULL)
+		ret = (*fun->ops->open)(fun);
 	
 	async_answer_0(iid, ret);
@@ -344,7 +354,7 @@
 		switch  (method) {
 		case IPC_M_PHONE_HUNGUP:
-			/* close the device */
-			if (dev->ops != NULL && dev->ops->close != NULL)
-				(*dev->ops->close)(dev);
+			/* Close device function */
+			if (fun->ops != NULL && fun->ops->close != NULL)
+				(*fun->ops->close)(fun);
 			async_answer_0(callid, EOK);
 			return;
@@ -356,11 +366,12 @@
 			if (!is_valid_iface_idx(iface_idx)) {
 				remote_handler_t *default_handler =
-				    device_get_default_handler(dev);
+				    function_get_default_handler(fun);
 				if (default_handler != NULL) {
-					(*default_handler)(dev, callid, &call);
+					(*default_handler)(fun, callid, &call);
 					break;
 				}
+				
 				/*
-				 * This is not device's interface and the
+				 * Function has no such interface and
 				 * default handler is not provided.
 				 */
@@ -372,12 +383,12 @@
 			}
 			
-			/* calling one of the device's interfaces */
+			/* calling one of the function's interfaces */
 			
 			/* Get the interface ops structure. */
-			void *ops = device_get_ops(dev, iface_idx);
+			void *ops = function_get_ops(fun, iface_idx);
 			if (ops == NULL) {
 				printf("%s: driver_connection_gen error - ",
 				    driver->name);
-				printf("device with handle %" PRIun " has no interface "
+				printf("Function with handle %" PRIun " has no interface "
 				    "with id %d.\n", handle, iface_idx);
 				async_answer_0(callid, ENOTSUP);
@@ -408,7 +419,7 @@
 			 * receive parameters from the remote client and it will
 			 * pass it to the corresponding local interface method
-			 * associated with the device by its driver.
+			 * associated with the function by its driver.
 			 */
-			(*iface_method_ptr)(dev, ops, callid, &call);
+			(*iface_method_ptr)(fun, ops, callid, &call);
 			break;
 		}
@@ -425,5 +436,4 @@
 	driver_connection_gen(iid, icall, false);
 }
-
 
 /** Function for handling connections to device driver. */
@@ -454,120 +464,200 @@
  * @return		The device structure.
  */
-device_t *create_device(void)
-{
-	device_t *dev = malloc(sizeof(device_t));
-
-	if (dev != NULL) {
-		memset(dev, 0, sizeof(device_t));
-		init_match_ids(&dev->match_ids);
-	}
-
+static ddf_dev_t *create_device(void)
+{
+	ddf_dev_t *dev;
+
+	dev = malloc(sizeof(ddf_dev_t));
+	if (dev == NULL)
+		return NULL;
+
+	memset(dev, 0, sizeof(ddf_dev_t));
 	return dev;
 }
 
+/** Create new function structure.
+ *
+ * @return		The device structure.
+ */
+static ddf_fun_t *create_function(void)
+{
+	ddf_fun_t *fun;
+
+	fun = calloc(1, sizeof(ddf_fun_t));
+	if (fun == NULL)
+		return NULL;
+
+	init_match_ids(&fun->match_ids);
+	link_initialize(&fun->link);
+
+	return fun;
+}
+
 /** Delete device structure.
  *
  * @param dev		The device structure.
  */
-void delete_device(device_t *dev)
-{
-	clean_match_ids(&dev->match_ids);
-	if (dev->name != NULL)
-		free(dev->name);
+static void delete_device(ddf_dev_t *dev)
+{
 	free(dev);
 }
 
-void *device_get_ops(device_t *dev, dev_inferface_idx_t idx)
+/** Delete device structure.
+ *
+ * @param dev		The device structure.
+ */
+static void delete_function(ddf_fun_t *fun)
+{
+	clean_match_ids(&fun->match_ids);
+	if (fun->name != NULL)
+		free(fun->name);
+	free(fun);
+}
+
+/** Create a DDF function node.
+ *
+ * Create a DDF function (in memory). Both child devices and external clients
+ * communicate with a device via its functions.
+ *
+ * The created function node is fully formed, but only exists in the memory
+ * of the client task. In order to be visible to the system, the function
+ * must be bound using ddf_fun_bind().
+ *
+ * This function should only fail if there is not enough free memory.
+ * Specifically, this function succeeds even if @a dev already has
+ * a (bound) function with the same name.
+ *
+ * Type: A function of type fun_inner indicates that DDF should attempt
+ * to attach child devices to the function. fun_exposed means that
+ * the function should be exported to external clients (applications).
+ *
+ * @param dev		Device to which we are adding function
+ * @param ftype		Type of function (fun_inner or fun_exposed)
+ * @param name		Name of function
+ *
+ * @return		New function or @c NULL if memory is not available
+ */
+ddf_fun_t *ddf_fun_create(ddf_dev_t *dev, fun_type_t ftype, const char *name)
+{
+	ddf_fun_t *fun;
+
+	fun = create_function();
+	if (fun == NULL)
+		return NULL;
+
+	fun->bound = false;
+	fun->dev = dev;
+	fun->ftype = ftype;
+
+	fun->name = str_dup(name);
+	if (fun->name == NULL) {
+		delete_function(fun);
+		return NULL;
+	}
+
+	return fun;
+}
+
+/** Destroy DDF function node.
+ *
+ * Destroy a function previously created with ddf_fun_create(). The function
+ * must not be bound.
+ *
+ * @param fun		Function to destroy
+ */
+void ddf_fun_destroy(ddf_fun_t *fun)
+{
+	assert(fun->bound == false);
+	delete_function(fun);
+}
+
+static void *function_get_ops(ddf_fun_t *fun, dev_inferface_idx_t idx)
 {
 	assert(is_valid_iface_idx(idx));
-	if (dev->ops == NULL)
+	if (fun->ops == NULL)
 		return NULL;
-	return dev->ops->interfaces[idx];
-}
-
-int child_device_register(device_t *child, device_t *parent)
-{
-	assert(child->name != NULL);
+	return fun->ops->interfaces[idx];
+}
+
+/** Bind a function node.
+ *
+ * Bind the specified function to the system. This effectively makes
+ * the function visible to the system (uploads it to the server).
+ *
+ * This function can fail for several reasons. Specifically,
+ * it will fail if the device already has a bound function of
+ * the same name.
+ *
+ * @param fun		Function to bind
+ * @return		EOK on success or negative error code
+ */
+int ddf_fun_bind(ddf_fun_t *fun)
+{
+	assert(fun->name != NULL);
 	
 	int res;
 	
-	add_to_devices_list(child);
-	res = devman_child_device_register(child->name, &child->match_ids,
-	    parent->handle, &child->handle);
+	add_to_functions_list(fun);
+	res = devman_add_function(fun->name, fun->ftype, &fun->match_ids,
+	    fun->dev->handle, &fun->handle);
 	if (res != EOK) {
-		remove_from_devices_list(child);
+		remove_from_functions_list(fun);
 		return res;
 	}
 	
+	fun->bound = true;
 	return res;
 }
 
-/** Wrapper for child_device_register for devices with single match id.
- *
- * @param parent Parent device.
- * @param child_name Child device name.
- * @param child_match_id Child device match id.
- * @param child_match_score Child device match score.
- * @return Error code.
- */
-int child_device_register_wrapper(device_t *parent, const char *child_name,
-    const char *child_match_id, int child_match_score)
-{
-	device_t *child = NULL;
-	match_id_t *match_id = NULL;
-	int rc;
-	
-	child = create_device();
-	if (child == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-	
-	child->name = child_name;
+/** Add single match ID to inner function.
+ *
+ * Construct and add a single match ID to the specified function.
+ * Cannot be called when the function node is bound.
+ *
+ * @param fun			Function
+ * @param match_id_str		Match string
+ * @param match_score		Match score
+ * @return			EOK on success, ENOMEM if out of memory.
+ */
+int ddf_fun_add_match_id(ddf_fun_t *fun, const char *match_id_str,
+    int match_score)
+{
+	match_id_t *match_id;
+	
+	assert(fun->bound == false);
+	assert(fun->ftype == fun_inner);
 	
 	match_id = create_match_id();
-	if (match_id == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-	
-	match_id->id = child_match_id;
-	match_id->score = child_match_score;
-	add_match_id(&child->match_ids, match_id);
-	
-	rc = child_device_register(child, parent);
-	if (rc != EOK)
-		goto failure;
-	
+	if (match_id == NULL)
+		return ENOMEM;
+	
+	match_id->id = match_id_str;
+	match_id->score = 90;
+	
+	add_match_id(&fun->match_ids, match_id);
 	return EOK;
-	
-failure:
-	if (match_id != NULL) {
-		match_id->id = NULL;
-		delete_match_id(match_id);
-	}
-	
-	if (child != NULL) {
-		child->name = NULL;
-		delete_device(child);
-	}
-	
-	return rc;
 }
 
 /** Get default handler for client requests */
-remote_handler_t *device_get_default_handler(device_t *dev)
-{
-	if (dev->ops == NULL)
+static remote_handler_t *function_get_default_handler(ddf_fun_t *fun)
+{
+	if (fun->ops == NULL)
 		return NULL;
-	return dev->ops->default_handler;
-}
-
-int add_device_to_class(device_t *dev, const char *class_name)
-{
-	return devman_add_device_to_class(dev->handle, class_name);
-}
-
-int driver_main(driver_t *drv)
+	return fun->ops->default_handler;
+}
+
+/** Add exposed function to class.
+ *
+ * Must only be called when the function is bound.
+ */
+int ddf_fun_add_to_class(ddf_fun_t *fun, const char *class_name)
+{
+	assert(fun->bound == true);
+	assert(fun->ftype == fun_exposed);
+	
+	return devman_add_device_to_class(fun->handle, class_name);
+}
+
+int ddf_driver_main(driver_t *drv)
 {
 	/*
Index: uspace/lib/drv/generic/remote_char_dev.c
===================================================================
--- uspace/lib/drv/generic/remote_char_dev.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/drv/generic/remote_char_dev.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -37,10 +37,10 @@
 
 #include "ops/char_dev.h"
-#include "driver.h"
+#include "ddf/driver.h"
 
 #define MAX_CHAR_RW_COUNT 256
 
-static void remote_char_read(device_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_char_write(device_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_char_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_char_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 
 /** Remote character interface operations. */
@@ -67,9 +67,9 @@
  * local interface to the remote client.
  *
- * @param dev		The device from which the data are read.
+ * @param fun		The function from which the data are read.
  * @param ops		The local ops structure.
  */
 static void
-remote_char_read(device_t *dev, void *ops, ipc_callid_t callid,
+remote_char_read(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
     ipc_call_t *call)
 {
@@ -94,5 +94,5 @@
 	
 	char buf[MAX_CHAR_RW_COUNT];
-	int ret = (*char_dev_ops->read)(dev, buf, len);
+	int ret = (*char_dev_ops->read)(fun, buf, len);
 	
 	if (ret < 0) {
@@ -114,9 +114,9 @@
  * local interface to the remote client.
  *
- * @param dev		The device to which the data are written.
+ * @param fun		The function to which the data are written.
  * @param ops		The local ops structure.
  */
 static void
-remote_char_write(device_t *dev, void *ops, ipc_callid_t callid,
+remote_char_write(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
     ipc_call_t *call)
 {
@@ -144,5 +144,5 @@
 	async_data_write_finalize(cid, buf, len);
 	
-	int ret = (*char_dev_ops->write)(dev, buf, len);
+	int ret = (*char_dev_ops->write)(fun, buf, len);
 	if (ret < 0) {
 		/* Some error occured. */
Index: uspace/lib/drv/generic/remote_hw_res.c
===================================================================
--- uspace/lib/drv/generic/remote_hw_res.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/drv/generic/remote_hw_res.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -37,9 +37,9 @@
 
 #include "ops/hw_res.h"
-#include "driver.h"
+#include "ddf/driver.h"
 
-static void remote_hw_res_get_resource_list(device_t *, void *, ipc_callid_t,
+static void remote_hw_res_get_resource_list(ddf_fun_t *, void *, ipc_callid_t,
     ipc_call_t *);
-static void remote_hw_res_enable_interrupt(device_t *, void *, ipc_callid_t,
+static void remote_hw_res_enable_interrupt(ddf_fun_t *, void *, ipc_callid_t,
     ipc_call_t *);
 
@@ -55,5 +55,5 @@
 };
 
-static void remote_hw_res_enable_interrupt(device_t *dev, void *ops,
+static void remote_hw_res_enable_interrupt(ddf_fun_t *fun, void *ops,
     ipc_callid_t callid, ipc_call_t *call)
 {
@@ -62,5 +62,5 @@
 	if (hw_res_ops->enable_interrupt == NULL)
 		async_answer_0(callid, ENOTSUP);
-	else if (hw_res_ops->enable_interrupt(dev))
+	else if (hw_res_ops->enable_interrupt(fun))
 		async_answer_0(callid, EOK);
 	else
@@ -68,5 +68,5 @@
 }
 
-static void remote_hw_res_get_resource_list(device_t *dev, void *ops,
+static void remote_hw_res_get_resource_list(ddf_fun_t *fun, void *ops,
     ipc_callid_t callid, ipc_call_t *call)
 {
@@ -78,5 +78,5 @@
 	}
 	
-	hw_resource_list_t *hw_resources = hw_res_ops->get_resource_list(dev);
+	hw_resource_list_t *hw_resources = hw_res_ops->get_resource_list(fun);
 	if (hw_resources == NULL){
 		async_answer_0(callid, ENOENT);
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
+++ uspace/lib/drv/include/ddf/driver.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef DDF_DRIVER_H_
+#define DDF_DRIVER_H_
+
+#include <ipc/devman.h>
+#include <ipc/dev_iface.h>
+
+#include "../dev_iface.h"
+
+typedef struct ddf_dev ddf_dev_t;
+typedef struct ddf_fun ddf_fun_t;
+
+/*
+ * Device
+ */
+
+/** Devices operations */
+typedef struct ddf_dev_ops {
+	/**
+	 * Optional callback function called when a client is connecting to the
+	 * device.
+	 */
+	int (*open)(ddf_fun_t *);
+	
+	/**
+	 * Optional callback function called when a client is disconnecting from
+	 * the device.
+	 */
+	void (*close)(ddf_fun_t *);
+	
+	/** The table of standard interfaces implemented by the device. */
+	void *interfaces[DEV_IFACE_COUNT];
+	
+	/**
+	 * The default handler of remote client requests. If the client's remote
+	 * request cannot be handled by any of the standard interfaces, the
+	 * default handler is used.
+	 */
+	remote_handler_t *default_handler;
+} ddf_dev_ops_t;
+
+/** Device structure */
+struct ddf_dev {
+	/**
+	 * Globally unique device identifier (assigned to the device by the
+	 * device manager).
+	 */
+	devman_handle_t handle;
+	
+	/**
+	 * Phone to the parent device driver (if it is different from this
+	 * driver)
+	 */
+	int parent_phone;
+	
+	/** Device name */
+	const char *name;
+	
+	/** Driver-specific data associated with this device */
+	void *driver_data;
+	
+	/** Link in the list of devices handled by the driver */
+	link_t link;
+};
+
+/** Function structure */
+struct ddf_fun {
+	/** True if bound to the device manager */
+	bool bound;
+	/** Function indentifier (asigned by device manager) */
+	devman_handle_t handle;
+	
+	/** Device which this function belogs to */
+	ddf_dev_t *dev;
+	
+	/** Function type */
+	fun_type_t ftype;
+	/** Function name */
+	const char *name;
+	/** List of device ids for driver matching */
+	match_id_list_t match_ids;
+	/** Driver-specific data associated with this function */
+	void *driver_data;
+	/** Implementation of operations provided by this function */
+	ddf_dev_ops_t *ops;
+	
+	/** Link in the list of functions handled by the driver */
+	link_t link;
+};
+
+/*
+ * Driver
+ */
+
+/** Generic device driver operations */
+typedef struct driver_ops {
+	/** Callback method for passing a new device to the device driver */
+	int (*add_device)(ddf_dev_t *dev);
+	/* TODO: add other generic driver operations */
+} driver_ops_t;
+
+/** Driver structure */
+typedef struct driver {
+	/** Name of the device driver */
+	const char *name;
+	/** Generic device driver operations */
+	driver_ops_t *driver_ops;
+} driver_t;
+
+extern int ddf_driver_main(driver_t *);
+
+extern ddf_fun_t *ddf_fun_create(ddf_dev_t *, fun_type_t, const char *);
+extern void ddf_fun_destroy(ddf_fun_t *);
+extern int ddf_fun_bind(ddf_fun_t *);
+extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int);
+
+extern int ddf_fun_add_to_class(ddf_fun_t *, const char *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/ddf/interrupt.h
===================================================================
--- uspace/lib/drv/include/ddf/interrupt.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
+++ uspace/lib/drv/include/ddf/interrupt.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef DDF_INTERRUPT_H_
+#define DDF_INTERRUPT_H_
+
+#include <kernel/ddi/irq.h>
+#include <adt/list.h>
+#include <ddi.h>
+#include <fibril_synch.h>
+
+#include "driver.h"
+#include "../dev_iface.h"
+
+/*
+ * Interrupts
+ */
+
+typedef void interrupt_handler_t(ddf_dev_t *, ipc_callid_t, ipc_call_t *);
+
+typedef struct interrupt_context {
+	int id;
+	ddf_dev_t *dev;
+	int irq;
+	interrupt_handler_t *handler;
+	link_t link;
+} interrupt_context_t;
+
+typedef struct interrupt_context_list {
+	int curr_id;
+	link_t contexts;
+	fibril_mutex_t mutex;
+} 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 int register_interrupt_handler(ddf_dev_t *, int, interrupt_handler_t *,
+    irq_code_t *);
+extern int unregister_interrupt_handler(ddf_dev_t *, int);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/dev_iface.h
===================================================================
--- uspace/lib/drv/include/dev_iface.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/drv/include/dev_iface.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -43,5 +43,5 @@
  */
 
-struct device;
+struct ddf_fun;
 
 /*
@@ -49,8 +49,8 @@
  * devices driver.
  */
-typedef void remote_iface_func_t(struct device *, void *, ipc_callid_t,
+typedef void remote_iface_func_t(struct ddf_fun *, void *, ipc_callid_t,
     ipc_call_t *);
 typedef remote_iface_func_t *remote_iface_func_ptr_t;
-typedef void remote_handler_t(struct device *, ipc_callid_t, ipc_call_t *);
+typedef void remote_handler_t(struct ddf_fun *, ipc_callid_t, ipc_call_t *);
 
 typedef struct {
Index: pace/lib/drv/include/driver.h
===================================================================
--- uspace/lib/drv/include/driver.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,193 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libdrv
- * @{
- */
-/** @file
- */
-
-#ifndef LIBDRV_DRIVER_H_
-#define LIBDRV_DRIVER_H_
-
-#include <kernel/ddi/irq.h>
-#include <adt/list.h>
-#include <devman.h>
-#include <ipc/devman.h>
-#include <ipc/dev_iface.h>
-#include <assert.h>
-#include <ddi.h>
-#include <libarch/ddi.h>
-#include <fibril_synch.h>
-#include <malloc.h>
-
-#include "dev_iface.h"
-
-struct device;
-typedef struct device device_t;
-
-/*
- * Device class
- */
-
-/** Devices operations */
-typedef struct device_ops {
-	/**
-	 * Optional callback function called when a client is connecting to the
-	 * device.
-	 */
-	int (*open)(device_t *);
-	
-	/**
-	 * Optional callback function called when a client is disconnecting from
-	 * the device.
-	 */
-	void (*close)(device_t *);
-	
-	/** The table of standard interfaces implemented by the device. */
-	void *interfaces[DEV_IFACE_COUNT];
-	
-	/**
-	 * The default handler of remote client requests. If the client's remote
-	 * request cannot be handled by any of the standard interfaces, the
-	 * default handler is used.
-	 */
-	remote_handler_t *default_handler;
-} device_ops_t;
-
-
-/*
- * Device
- */
-
-/** Device structure */
-struct device {
-	/**
-	 * Globally unique device identifier (assigned to the device by the
-	 * device manager).
-	 */
-	devman_handle_t handle;
-	
-	/**
-	 * Phone to the parent device driver (if it is different from this
-	 * driver)
-	 */
-	int parent_phone;
-	
-	/** Parent device if handled by this driver, NULL otherwise */
-	device_t *parent;
-	/** Device name */
-	const char *name;
-	/** List of device ids for device-to-driver matching */
-	match_id_list_t match_ids;
-	/** Driver-specific data associated with this device */
-	void *driver_data;
-	/** The implementation of operations provided by this device */
-	device_ops_t *ops;
-	
-	/** Link in the list of devices handled by the driver */
-	link_t link;
-};
-
-/*
- * Driver
- */
-
-/** Generic device driver operations */
-typedef struct driver_ops {
-	/** Callback method for passing a new device to the device driver */
-	int (*add_device)(device_t *dev);
-	/* TODO: add other generic driver operations */
-} driver_ops_t;
-
-/** Driver structure */
-typedef struct driver {
-	/** Name of the device driver */
-	const char *name;
-	/** Generic device driver operations */
-	driver_ops_t *driver_ops;
-} driver_t;
-
-int driver_main(driver_t *);
-
-/** Create new device structure.
- *
- * @return		The device structure.
- */
-extern device_t *create_device(void);
-extern void delete_device(device_t *);
-extern void *device_get_ops(device_t *, dev_inferface_idx_t);
-
-extern int child_device_register(device_t *, device_t *);
-extern int child_device_register_wrapper(device_t *, const char *, const char *,
-    int);
-
-/*
- * Interrupts
- */
-
-typedef void interrupt_handler_t(device_t *, ipc_callid_t, ipc_call_t *);
-
-typedef struct interrupt_context {
-	int id;
-	device_t *dev;
-	int irq;
-	interrupt_handler_t *handler;
-	link_t link;
-} interrupt_context_t;
-
-typedef struct interrupt_context_list {
-	int curr_id;
-	link_t contexts;
-	fibril_mutex_t mutex;
-} 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 *, device_t *, int);
-
-extern int register_interrupt_handler(device_t *, int, interrupt_handler_t *,
-    irq_code_t *);
-extern int unregister_interrupt_handler(device_t *, int);
-
-extern remote_handler_t *device_get_default_handler(device_t *);
-extern int add_device_to_class(device_t *, const char *);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/lib/drv/include/ops/char_dev.h
===================================================================
--- uspace/lib/drv/include/ops/char_dev.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/drv/include/ops/char_dev.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -36,9 +36,9 @@
 #define LIBDRV_OPS_CHAR_DEV_H_
 
-#include "../driver.h"
+#include "../ddf/driver.h"
 
 typedef struct {
-	int (*read)(device_t *, char *, size_t);
-	int (*write)(device_t *, char *, size_t);
+	int (*read)(ddf_fun_t *, char *, size_t);
+	int (*write)(ddf_fun_t *, char *, size_t);
 } char_dev_ops_t;
 
Index: uspace/lib/drv/include/ops/hw_res.h
===================================================================
--- uspace/lib/drv/include/ops/hw_res.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/lib/drv/include/ops/hw_res.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -39,9 +39,9 @@
 #include <sys/types.h>
 
-#include "../driver.h"
+#include "../ddf/driver.h"
 
 typedef struct {
-	 hw_resource_list_t *(*get_resource_list)(device_t *);
-	 bool (*enable_interrupt)(device_t *);
+	 hw_resource_list_t *(*get_resource_list)(ddf_fun_t *);
+	 bool (*enable_interrupt)(ddf_fun_t *);
 } hw_res_ops_t;
 
Index: pace/lib/libpci/Makefile.build
===================================================================
--- uspace/lib/libpci/Makefile.build	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,64 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-## Setup toolchain
-#
-
-include Makefile.common
-include $(LIBC_PREFIX)/Makefile.toolchain
-
-## Sources
-#
-
-SOURCES = \
-	access.c \
-	generic.c \
-	names.c \
-	i386-ports.c
-
-OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
-
-.PHONY: all
-
-all: $(LIBPCI)
-
--include $(DEPEND)
-
-$(LIBPCI): $(OBJECTS)
-	$(AR) rc $@ $(OBJECTS)
-
-%.o: %.c $(DEPEND)
-	$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
-ifeq ($(PRECHECK),y)
-	$(JOBFILE) $(JOB) $< $@ cc core $(DEFS) $(CFLAGS)
-endif
-
-$(DEPEND):
-	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > $@ 2> /dev/null
-	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
Index: pace/lib/libpci/Makefile.common
===================================================================
--- uspace/lib/libpci/Makefile.common	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2005 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.
-#
-
-
-## Common names
-#
-
-LIBC_PREFIX = ../../../../../lib/libc
-DEPEND = Makefile.depend
-DEPEND_PREV = $(DEPEND).prev
-JOB = libpci.job
-LIBPCI = libpci.a
Index: pace/lib/packet/include/net_byteorder.h
===================================================================
--- uspace/lib/packet/include/net_byteorder.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,71 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup net
- *  @{
- */
-
-/** @file
- *  Host - network byte order manipulation functions.
- */
-
-#ifndef __NET_BYTEORDER_H__
-#define __NET_BYTEORDER_H__
-
-#include <byteorder.h>
-#include <sys/types.h>
-
-
-/** Converts the given short number (16 bit) from the host byte order to the network byte order (big endian).
- *  @param[in] number The number in the host byte order to be converted.
- *  @returns The number in the network byte order.
- */
-#define htons(number)		host2uint16_t_be(number)
-
-/** Converts the given long number (32 bit) from the host byte order to the network byte order (big endian).
- *  @param[in] number The number in the host byte order to be converted.
- *  @returns The number in the network byte order.
- */
-#define htonl(number)		host2uint32_t_be(number)
-
-/** Converts the given short number (16 bit) from the network byte order (big endian) to the host byte order.
- *  @param[in] number The number in the network byte order to be converted.
- *  @returns The number in the host byte order.
- */
-#define ntohs(number) 	uint16_t_be2host(number)
-
-/** Converts the given long number (32 bit) from the network byte order (big endian) to the host byte order.
- *  @param[in] number The number in the network byte order to be converted.
- *  @returns The number in the host byte order.
- */
-#define ntohl(number)		uint32_t_be2host(number)
-
-#endif
-
-/** @}
- */
Index: pace/lib/packet/include/net_err.h
===================================================================
--- uspace/lib/packet/include/net_err.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,99 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup net
- * @{
- */
-
-/** @file
- * Common error processing codes and routines.
- */
-
-#ifndef __NET_ERR_H__
-#define __NET_ERR_H__
-
-#include <errno.h>
-
-#ifdef CONFIG_DEBUG
-	#include <stdio.h>
-	#include <str_error.h>
-#endif
-
-/** An actual stored error code.
- *
- */
-#define ERROR_CODE  error_check_return_value
-
-/** An error processing routines declaration.
- *
- * This has to be declared in the block where the error processing
- * is desired.
- *
- */
-#define ERROR_DECLARE  int ERROR_CODE
-
-/** Store the value as an error code and checks if an error occurred.
- *
- * @param[in] value The value to be checked. May be a function call.
- * @return False if the value indicates success (EOK).
- * @return True otherwise.
- *
- */
-#ifdef CONFIG_DEBUG
-
-#define ERROR_OCCURRED(value) \
-	(((ERROR_CODE = (value)) != EOK) \
-	&& ({ \
-		fprintf(stderr, "libsocket error at %s:%d (%s)\n", \
-		__FILE__, __LINE__, str_error(ERROR_CODE)); \
-		1; \
-	}))
-
-#else
-
-#define ERROR_OCCURRED(value)  ((ERROR_CODE = (value)) != EOK)
-
-#endif
-
-/** Error propagation
- *
- * Check if an error occurred and immediately exit the actual
- * function returning the error code.
- *
- * @param[in] value The value to be checked. May be a function call.
- *
- */
-
-#define ERROR_PROPAGATE(value) \
-	if (ERROR_OCCURRED(value)) \
-		return ERROR_CODE
-
-#endif
-
-/** @}
- */
Index: pace/lib/packet/include/socket_errno.h
===================================================================
--- uspace/lib/packet/include/socket_errno.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,136 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup net
- *  @{
- */
-
-/** @file
- *  Socket error codes.
- *  Based on BSD.
- */
-
-#ifndef __NET_SOCKET_ERR_H__
-#define __NET_SOCKET_ERR_H__
-
-#include <errno.h>
-
-/** @name Socket error codes definitions
- */
-/*@{*/
-
-////#define EINTR			(-10004)
-////#define EBADF			(-10009)
-//#define EACCES			(-10013)
-//#define EFAULT			(-10014)
-////#define EINVAL			(-10022)
-////#define EMFILE			(-10024)
-//#define EWOULDBLOCK		(-10035)
-
-/** An API function is called while another blocking function is in progress.
- */
-#define EINPROGRESS		(-10036)
-
-//#define EALREADY		(-10037)
-
-/** The socket identifier is not valid.
- */
-#define ENOTSOCK		(-10038)
-
-/** The destination address required.
- */
-#define EDESTADDRREQ	(-10039)
-
-//#define EMSGSIZE		(-10040)
-//#define EPROTOTYPE		(-10041)
-//#define ENOPROTOOPT		(-10042)
-
-/** Protocol is not supported.
- */
-#define EPROTONOSUPPORT	(-10043)
-
-/** Socket type is not supported.
- */
-#define ESOCKTNOSUPPORT	(-10044)
-
-//#define EOPNOTSUPP		(-10045)
-
-/** Protocol family is not supported.
- */
-#define EPFNOSUPPORT	(-10046)
-
-/** Address family is not supported.
- */
-#define EAFNOSUPPORT	(-10047)
-
-/** Address is already in use.
- */
-#define EADDRINUSE		(-10048)
-
-//#define EADDRNOTAVAIL	(-10049)
-/* May be reported at any time if the implementation detects an underlying failure.
- */
-//#define ENETDOWN		(-10050)
-//#define ENETUNREACH		(-10051)
-//#define ENETRESET		(-10052)
-//#define ECONNABORTED	(-10053)
-//#define ECONNRESET		(-10054)
-//#define ENOBUFS			(-10055)
-//#define EISCONN			(-10056)
-
-/** The socket is not connected or bound.
- */
-#define ENOTCONN		(-10057)
-
-//#define ESHUTDOWN		(-10058)
-//#define ETOOMANYREFS	(-10059)
-//#define ETIMEDOUT		(-10060)
-//#define ECONNREFUSED	(-10061)
-//#define ELOOP			(-10062)
-////#define ENAMETOOLONG	(-10063)
-//#define EHOSTDOWN		(-10064)
-//#define EHOSTUNREACH	(-10065)
-//#define HOST_NOT_FOUND	(-11001)
-
-/** The requested operation was not performed.
- *  Try again later.
- */
-#define TRY_AGAIN		(-11002)
-
-//#define NO_RECOVERY		(-11003)
-
-/** No data.
- */
-#define NO_DATA			(-11004)
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -55,4 +55,5 @@
 #include <as.h>
 #include <fibril_synch.h>
+#include <stdint.h>
 #include <str.h>
 #include <devmap.h>
@@ -61,4 +62,5 @@
 #include <errno.h>
 #include <bool.h>
+#include <byteorder.h>
 #include <task.h>
 #include <macros.h>
@@ -73,6 +75,9 @@
 #define LEGACY_CTLS 4
 
-/** Physical block size. Should be always 512. */
-static const size_t block_size = 512;
+/**
+ * Size of data returned from Identify Device or Identify Packet Device
+ * command.
+ */
+static const size_t identify_data_size = 512;
 
 /** Size of the communication area. */
@@ -105,10 +110,16 @@
 static int ata_bd_write_blocks(int disk_id, uint64_t ba, size_t cnt,
     const void *buf);
-static int ata_bd_read_block(int disk_id, uint64_t ba, size_t cnt,
+static int ata_rcmd_read(int disk_id, uint64_t ba, size_t cnt,
     void *buf);
-static int ata_bd_write_block(int disk_id, uint64_t ba, size_t cnt,
+static int ata_rcmd_write(int disk_id, uint64_t ba, size_t cnt,
     const void *buf);
 static int disk_init(disk_t *d, int disk_id);
 static int drive_identify(int drive_id, void *buf);
+static int identify_pkt_dev(int dev_idx, void *buf);
+static int ata_cmd_packet(int dev_idx, const void *cpkt, size_t cpkt_size,
+    void *obuf, size_t obuf_size);
+static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size);
+static int ata_pcmd_read_12(int dev_idx, uint64_t ba, size_t cnt,
+    void *obuf, size_t obuf_size);
 static void disk_print_summary(disk_t *d);
 static int coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc);
@@ -203,15 +214,20 @@
 	printf("%s: ", d->model);
 
-	switch (d->amode) {
-	case am_chs:
-		printf("CHS %u cylinders, %u heads, %u sectors",
-		    disk->geom.cylinders, disk->geom.heads, disk->geom.sectors);
-		break;
-	case am_lba28:
-		printf("LBA-28");
-		break;
-	case am_lba48:
-		printf("LBA-48");
-		break;
+	if (d->dev_type == ata_reg_dev) {
+		switch (d->amode) {
+		case am_chs:
+			printf("CHS %u cylinders, %u heads, %u sectors",
+			    disk->geom.cylinders, disk->geom.heads,
+			    disk->geom.sectors);
+			break;
+		case am_lba28:
+			printf("LBA-28");
+			break;
+		case am_lba48:
+			printf("LBA-48");
+			break;
+		}
+	} else {
+		printf("PACKET");
 	}
 
@@ -313,5 +329,5 @@
 			    IPC_GET_ARG2(call));
 			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
+			if (cnt * disk[disk_id].block_size > comm_size) {
 				retval = ELIMIT;
 				break;
@@ -323,5 +339,5 @@
 			    IPC_GET_ARG2(call));
 			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
+			if (cnt * disk[disk_id].block_size > comm_size) {
 				retval = ELIMIT;
 				break;
@@ -330,5 +346,5 @@
 			break;
 		case BD_GET_BLOCK_SIZE:
-			async_answer_1(callid, EOK, block_size);
+			async_answer_1(callid, EOK, disk[disk_id].block_size);
 			continue;
 		case BD_GET_NUM_BLOCKS:
@@ -353,4 +369,5 @@
 	identify_data_t idata;
 	uint8_t model[40];
+	ata_inquiry_data_t inq_data;
 	uint16_t w;
 	uint8_t c;
@@ -359,11 +376,42 @@
 	unsigned i;
 
+	d->present = false;
+	fibril_mutex_initialize(&d->lock);
+
+	/* Try identify command. */
 	rc = drive_identify(disk_id, &idata);
-	if (rc != EOK) {
-		d->present = false;
-		return rc;
-	}
-
-	if ((idata.caps & cap_lba) == 0) {
+	if (rc == EOK) {
+		/* Success. It's a register (non-packet) device. */
+		printf("ATA register-only device found.\n");
+		d->dev_type = ata_reg_dev;
+	} else if (rc == EIO) {
+		/*
+		 * There is something, but not a register device.
+		 * It could be a packet device.
+		 */
+		rc = identify_pkt_dev(disk_id, &idata);
+		if (rc == EOK) {
+			/* We have a packet device. */
+			d->dev_type = ata_pkt_dev;
+		} else {
+			/* Nope. Something's there, but not recognized. */
+			return EIO;
+		}
+	} else {
+		/* Operation timed out. That means there is no device there. */
+		return EIO;
+	}
+
+	printf("device caps: 0x%04x\n", idata.caps);
+	if (d->dev_type == ata_pkt_dev) {
+		/* Packet device */
+		d->amode = 0;
+
+		d->geom.cylinders = 0;
+		d->geom.heads = 0;
+		d->geom.sectors = 0;
+
+		d->blocks = 0;
+	} else if ((idata.caps & rd_cap_lba) == 0) {
 		/* Device only supports CHS addressing. */
 		d->amode = am_chs;
@@ -422,7 +470,25 @@
 	d->model[pos] = '\0';
 
+	if (d->dev_type == ata_pkt_dev) {
+		/* Send inquiry. */
+		rc = ata_pcmd_inquiry(0, &inq_data, sizeof(inq_data));
+		if (rc != EOK) {
+			printf("Device inquiry failed.\n");
+			d->present = false;
+			return EIO;
+		}
+
+		/* Check device type. */
+		if (INQUIRY_PDEV_TYPE(inq_data.pdev_type) != PDEV_TYPE_CDROM)
+			printf("Warning: Peripheral device type is not CD-ROM.\n");
+
+		/* Assume 2k block size for now. */
+		d->block_size = 2048;
+	} else {
+		/* Assume register Read always uses 512-byte blocks. */
+		d->block_size = 512;
+	}
+
 	d->present = true;
-	fibril_mutex_initialize(&d->lock);
-
 	return EOK;
 }
@@ -435,5 +501,10 @@
 
 	while (cnt > 0) {
-		rc = ata_bd_read_block(disk_id, ba, 1, buf);
+		if (disk[disk_id].dev_type == ata_reg_dev)
+			rc = ata_rcmd_read(disk_id, ba, 1, buf);
+		else
+			rc = ata_pcmd_read_12(disk_id, ba, 1, buf,
+			    disk[disk_id].block_size);
+
 		if (rc != EOK)
 			return rc;
@@ -441,5 +512,5 @@
 		++ba;
 		--cnt;
-		buf += block_size;
+		buf += disk[disk_id].block_size;
 	}
 
@@ -453,6 +524,9 @@
 	int rc;
 
+	if (disk[disk_id].dev_type != ata_reg_dev)
+		return ENOTSUP;
+
 	while (cnt > 0) {
-		rc = ata_bd_write_block(disk_id, ba, 1, buf);
+		rc = ata_rcmd_write(disk_id, ba, 1, buf);
 		if (rc != EOK)
 			return rc;
@@ -460,5 +534,5 @@
 		++ba;
 		--cnt;
-		buf += block_size;
+		buf += disk[disk_id].block_size;
 	}
 
@@ -473,4 +547,7 @@
  * @param disk_id	Device ID, 0 or 1.
  * @param buf		Pointer to a 512-byte buffer.
+ *
+ * @return		ETIMEOUT on timeout (this can mean the device is
+ *			not present). EIO if device responds with error.
  */
 static int drive_identify(int disk_id, void *buf)
@@ -484,5 +561,5 @@
 
 	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
-		return EIO;
+		return ETIMEOUT;
 
 	pio_write_8(&cmd->drive_head, drv_head);
@@ -493,15 +570,15 @@
 	 */
 	if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
-		return EIO;
+		return ETIMEOUT;
 
 	pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE);
 
 	if (wait_status(0, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
-		return EIO;
+		return ETIMEOUT;
 
 	/* Read data from the disk buffer. */
 
 	if ((status & SR_DRQ) != 0) {
-		for (i = 0; i < block_size / 2; i++) {
+		for (i = 0; i < identify_data_size / 2; i++) {
 			data = pio_read_16(&cmd->data_port);
 			((uint16_t *) buf)[i] = data;
@@ -509,6 +586,204 @@
 	}
 
+	if ((status & SR_ERR) != 0) {
+		return EIO;
+	}
+
+	return EOK;
+}
+
+/** Issue Identify Packet Device command.
+ *
+ * Reads @c identify data into the provided buffer. This is used to detect
+ * whether an ATAPI device is present and if so, to determine its parameters.
+ *
+ * @param dev_idx	Device index, 0 or 1.
+ * @param buf		Pointer to a 512-byte buffer.
+ */
+static int identify_pkt_dev(int dev_idx, void *buf)
+{
+	uint16_t data;
+	uint8_t status;
+	uint8_t drv_head;
+	size_t i;
+
+	drv_head = ((dev_idx != 0) ? DHR_DRV : 0);
+
+	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
+		return EIO;
+
+	pio_write_8(&cmd->drive_head, drv_head);
+
+	/* For ATAPI commands we do not need to wait for DRDY. */
+	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
+		return EIO;
+
+	pio_write_8(&cmd->command, CMD_IDENTIFY_PKT_DEV);
+
+	if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
+		return EIO;
+
+	/* Read data from the device buffer. */
+
+	if ((status & SR_DRQ) != 0) {
+		for (i = 0; i < identify_data_size / 2; i++) {
+			data = pio_read_16(&cmd->data_port);
+			((uint16_t *) buf)[i] = data;
+		}
+	}
+
 	if ((status & SR_ERR) != 0)
 		return EIO;
+
+	return EOK;
+}
+
+/** Issue packet command (i. e. write a command packet to the device).
+ *
+ * Only data-in commands are supported (e.g. inquiry, read).
+ *
+ * @param dev_idx	Device index (0 or 1)
+ * @param obuf		Buffer for storing data read from device
+ * @param obuf_size	Size of obuf in bytes
+ *
+ * @return EOK on success, EIO on error.
+ */
+static int ata_cmd_packet(int dev_idx, const void *cpkt, size_t cpkt_size,
+    void *obuf, size_t obuf_size)
+{
+	size_t i;
+	uint8_t status;
+	uint8_t drv_head;
+	disk_t *d;
+	size_t data_size;
+	uint16_t val;
+
+	d = &disk[dev_idx];
+	fibril_mutex_lock(&d->lock);
+
+	/* New value for Drive/Head register */
+	drv_head =
+	    ((dev_idx != 0) ? DHR_DRV : 0);
+
+	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	pio_write_8(&cmd->drive_head, drv_head);
+
+	if (wait_status(0, ~(SR_BSY|SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	/* Byte count <- max. number of bytes we can read in one transfer. */
+	pio_write_8(&cmd->cylinder_low, 0xfe);
+	pio_write_8(&cmd->cylinder_high, 0xff);
+
+	pio_write_8(&cmd->command, CMD_PACKET);
+
+	if (wait_status(SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	/* Write command packet. */
+	for (i = 0; i < (cpkt_size + 1) / 2; i++)
+		pio_write_16(&cmd->data_port, ((uint16_t *) cpkt)[i]);
+
+	if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	if ((status & SR_DRQ) == 0) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	/* Read byte count. */
+	data_size = (uint16_t) pio_read_8(&cmd->cylinder_low) +
+	    ((uint16_t) pio_read_8(&cmd->cylinder_high) << 8);
+
+	/* Check whether data fits into output buffer. */
+	if (data_size > obuf_size) {
+		/* Output buffer is too small to store data. */
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	/* Read data from the device buffer. */
+	for (i = 0; i < (data_size + 1) / 2; i++) {
+		val = pio_read_16(&cmd->data_port);
+		((uint16_t *) obuf)[i] = val;
+	}
+
+	if (status & SR_ERR) {
+		fibril_mutex_unlock(&d->lock);
+		return EIO;
+	}
+
+	fibril_mutex_unlock(&d->lock);
+
+	return EOK;
+}
+
+/** Issue ATAPI Inquiry.
+ *
+ * @param dev_idx	Device index (0 or 1)
+ * @param obuf		Buffer for storing inquiry data read from device
+ * @param obuf_size	Size of obuf in bytes
+ *
+ * @return EOK on success, EIO on error.
+ */
+static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size)
+{
+	ata_pcmd_inquiry_t cp;
+	int rc;
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.opcode = PCMD_INQUIRY;
+	cp.alloc_len = min(obuf_size, 0xff); /* Allocation length */
+
+	rc = ata_cmd_packet(0, &cp, sizeof(cp), obuf, obuf_size);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+/** Issue ATAPI read(12) command.
+ *
+ * Output buffer must be large enough to hold the data, otherwise the
+ * function will fail.
+ *
+ * @param dev_idx	Device index (0 or 1)
+ * @param ba		Starting block address
+ * @param cnt		Number of blocks to read
+ * @param obuf		Buffer for storing inquiry data read from device
+ * @param obuf_size	Size of obuf in bytes
+ *
+ * @return EOK on success, EIO on error.
+ */
+static int ata_pcmd_read_12(int dev_idx, uint64_t ba, size_t cnt,
+    void *obuf, size_t obuf_size)
+{
+	ata_pcmd_read_12_t cp;
+	int rc;
+
+	if (ba > UINT32_MAX)
+		return EINVAL;
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.opcode = PCMD_READ_12;
+	cp.ba = host2uint32_t_be(ba);
+	cp.nblocks = host2uint32_t_be(cnt);
+
+	rc = ata_cmd_packet(0, &cp, sizeof(cp), obuf, obuf_size);
+	if (rc != EOK)
+		return rc;
 
 	return EOK;
@@ -524,5 +799,5 @@
  * @return EOK on success, EIO on error.
  */
-static int ata_bd_read_block(int disk_id, uint64_t ba, size_t blk_cnt,
+static int ata_rcmd_read(int disk_id, uint64_t ba, size_t blk_cnt,
     void *buf)
 {
@@ -579,5 +854,5 @@
 		/* Read data from the device buffer. */
 
-		for (i = 0; i < block_size / 2; i++) {
+		for (i = 0; i < disk[disk_id].block_size / 2; i++) {
 			data = pio_read_16(&cmd->data_port);
 			((uint16_t *) buf)[i] = data;
@@ -601,5 +876,5 @@
  * @return EOK on success, EIO on error.
  */
-static int ata_bd_write_block(int disk_id, uint64_t ba, size_t cnt,
+static int ata_rcmd_write(int disk_id, uint64_t ba, size_t cnt,
     const void *buf)
 {
@@ -655,5 +930,5 @@
 		/* Write data to the device buffer. */
 
-		for (i = 0; i < block_size / 2; i++) {
+		for (i = 0; i < disk[disk_id].block_size / 2; i++) {
 			pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]);
 		}
Index: uspace/srv/bd/ata_bd/ata_bd.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/bd/ata_bd/ata_bd.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -53,6 +53,11 @@
 };
 
-/** Block addressing mode. */
-enum addr_mode {
+enum ata_dev_type {
+	ata_reg_dev,	/* Register device (no packet feature set support) */
+	ata_pkt_dev	/* Packet device (supports packet feature set). */
+};
+
+/** Register device block addressing mode. */
+enum rd_addr_mode {
 	am_chs,		/**< CHS block addressing */
 	am_lba28,	/**< LBA-28 block addressing */
@@ -62,6 +67,5 @@
 /** Block coordinates */
 typedef struct {
-	/** Addressing mode used */
-	enum addr_mode amode;
+	enum rd_addr_mode amode;
 
 	union {
@@ -90,5 +94,10 @@
 typedef struct {
 	bool present;
-	enum addr_mode amode;
+
+	/** Device type */
+	enum ata_dev_type dev_type;
+
+	/** Addressing mode to use (if register device) */
+	enum rd_addr_mode amode;
 
 	/*
@@ -102,4 +111,5 @@
 
 	uint64_t blocks;
+	size_t block_size;
 
 	char model[STR_BOUNDS(40) + 1];
Index: uspace/srv/bd/ata_bd/ata_hw.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_hw.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/bd/ata_bd/ata_hw.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -134,8 +134,10 @@
 	CMD_WRITE_SECTORS	= 0x30,
 	CMD_WRITE_SECTORS_EXT	= 0x34,
+	CMD_PACKET		= 0xA0,
+	CMD_IDENTIFY_PKT_DEV	= 0xA1,
 	CMD_IDENTIFY_DRIVE	= 0xEC
 };
 
-/** Data returned from @c identify command. */
+/** Data returned from identify device and identify packet device command. */
 typedef struct {
 	uint16_t gen_conf;
@@ -159,5 +161,5 @@
 	uint16_t max_rw_multiple;
 	uint16_t _res48;
-	uint16_t caps;
+	uint16_t caps;		/* Different meaning for packet device */
 	uint16_t _res50;
 	uint16_t pio_timing;
@@ -214,9 +216,22 @@
 } identify_data_t;
 
-enum ata_caps {
-	cap_iordy	= 0x0800,
-	cap_iordy_cbd	= 0x0400,
-	cap_lba		= 0x0200,
-	cap_dma		= 0x0100
+/** Capability bits for register device. */
+enum ata_regdev_caps {
+	rd_cap_iordy		= 0x0800,
+	rd_cap_iordy_cbd	= 0x0400,
+	rd_cap_lba		= 0x0200,
+	rd_cap_dma		= 0x0100
+};
+
+/** Capability bits for packet device. */
+enum ata_pktdev_caps {
+	pd_cap_ildma		= 0x8000,
+	pd_cap_cmdqueue		= 0x4000,
+	pd_cap_overlap		= 0x2000,
+	pd_cap_need_softreset	= 0x1000,	/* Obsolete (ATAPI-6) */
+	pd_cap_iordy		= 0x0800,
+	pd_cap_iordy_dis	= 0x0400,
+	pd_cap_lba		= 0x0200,	/* Must be on */
+	pd_cap_dma		= 0x0100
 };
 
@@ -226,4 +241,56 @@
 };
 
+/** ATA packet command codes. */
+enum ata_pkt_command {
+	PCMD_INQUIRY		= 0x12,
+	PCMD_READ_12		= 0xa8
+};
+
+/** ATAPI Inquiry command */
+typedef struct {
+	uint8_t opcode;		/**< Operation code (PCMD_INQUIRY) */
+	uint8_t _res0;
+	uint8_t _res1;
+	uint8_t _res2;
+	uint8_t alloc_len;	/**< Allocation length */
+	uint8_t _res3;
+	uint8_t _res4;
+	uint8_t _res5;
+	uint32_t _res6;
+} __attribute__ ((packed)) ata_pcmd_inquiry_t;
+
+/** ATAPI Read(12) command */
+typedef struct {
+	uint8_t opcode;		/**< Operation code (PCMD_READ_12) */
+	uint8_t _res0;
+	uint32_t ba;		/**< Starting block address */
+	uint32_t nblocks;	/**< Number of blocks to transfer */
+	uint8_t _res1;
+	uint8_t _res2;
+} __attribute__ ((packed)) ata_pcmd_read_12_t;
+
+/** Data returned from Inquiry command (mandatory part) */
+typedef struct {
+	uint8_t pdev_type;	/** Reserved, Peripheral device type */
+	uint8_t rmb;		/** RMB, Reserved */
+	uint8_t std_version;	/** ISO version, ECMA version, ANSI version */
+	uint8_t atapi_ver_rdf;	/** ATAPI version, Response data format */
+	uint8_t additional_len;	/** Additional length */
+	uint8_t _res0;
+	uint8_t _res1;
+	uint8_t _res2;
+	uint8_t vendor_id[8];	/** Vendor ID */
+	uint8_t product_id[8];	/** Product ID */
+	uint8_t product_rev[4];	/** Product revision level */
+} ata_inquiry_data_t;
+
+/** Extract value of ata_inquiry_data_t.pdev_type */
+#define INQUIRY_PDEV_TYPE(val) ((val) & 0x1f)
+
+/** Values for ata_inquiry_data_t.pdev_type */
+enum ata_pdev_type {
+	PDEV_TYPE_CDROM		= 0x05
+};
+
 #endif
 
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/devman/devman.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -41,4 +41,6 @@
 #include "devman.h"
 
+fun_node_t *find_node_child(fun_node_t *parent, const char *name);
+
 /* hash table operations */
 
@@ -51,13 +53,20 @@
     link_t *item)
 {
-	node_t *dev = hash_table_get_instance(item, node_t, devman_link);
+	dev_node_t *dev = hash_table_get_instance(item, dev_node_t, devman_dev);
 	return (dev->handle == (devman_handle_t) key[0]);
 }
 
-static int devmap_devices_compare(unsigned long key[], hash_count_t keys,
+static int devman_functions_compare(unsigned long key[], hash_count_t keys,
     link_t *item)
 {
-	node_t *dev = hash_table_get_instance(item, node_t, devmap_link);
-	return (dev->devmap_handle == (devmap_handle_t) key[0]);
+	fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devman_fun);
+	return (fun->handle == (devman_handle_t) key[0]);
+}
+
+static int devmap_functions_compare(unsigned long key[], hash_count_t keys,
+    link_t *item)
+{
+	fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devmap_fun);
+	return (fun->devmap_handle == (devmap_handle_t) key[0]);
 }
 
@@ -82,7 +91,13 @@
 };
 
+static hash_table_operations_t devman_functions_ops = {
+	.hash = devices_hash,
+	.compare = devman_functions_compare,
+	.remove_callback = devices_remove_callback
+};
+
 static hash_table_operations_t devmap_devices_ops = {
 	.hash = devices_hash,
-	.compare = devmap_devices_compare,
+	.compare = devmap_functions_compare,
 	.remove_callback = devices_remove_callback
 };
@@ -373,28 +388,52 @@
 }
 
-/** Create root device node in the device tree.
+/** Create root device and function node in the device tree.
  *
  * @param tree	The device tree.
  * @return	True on success, false otherwise.
  */
-bool create_root_node(dev_tree_t *tree)
-{
-	node_t *node;
-
-	printf(NAME ": create_root_node\n");
-
+bool create_root_nodes(dev_tree_t *tree)
+{
+	fun_node_t *fun;
+	dev_node_t *dev;
+	
+	printf(NAME ": create_root_nodes\n");
+	
 	fibril_rwlock_write_lock(&tree->rwlock);
-	node = create_dev_node();
-	if (node != NULL) {
-		insert_dev_node(tree, node, clone_string(""), NULL);
-		match_id_t *id = create_match_id();
-		id->id = clone_string("root");
-		id->score = 100;
-		add_match_id(&node->match_ids, id);
-		tree->root_node = node;
-	}
+	
+	/*
+	 * Create root function. This is a pseudo function to which
+	 * the root device node is attached. It allows us to match
+	 * the root device driver in a standard manner, i.e. against
+	 * the parent function.
+	 */
+	
+	fun = create_fun_node();
+	if (fun == NULL) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		return false;
+	}
+	
+	insert_fun_node(tree, fun, clone_string(""), NULL);
+	match_id_t *id = create_match_id();
+	id->id = clone_string("root");
+	id->score = 100;
+	add_match_id(&fun->match_ids, id);
+	tree->root_node = fun;
+	
+	/*
+	 * Create root device node.
+	 */
+	dev = create_dev_node();
+	if (dev == NULL) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		return false;
+	}
+	
+	insert_dev_node(tree, dev, fun);
+	
 	fibril_rwlock_write_unlock(&tree->rwlock);
-
-	return node != NULL;
+	
+	return dev != NULL;
 }
 
@@ -414,5 +453,5 @@
  *			is found.
  */
-driver_t *find_best_match_driver(driver_list_t *drivers_list, node_t *node)
+driver_t *find_best_match_driver(driver_list_t *drivers_list, dev_node_t *node)
 {
 	driver_t *best_drv = NULL, *drv = NULL;
@@ -442,13 +481,13 @@
  * @param drv		The driver.
  */
-void attach_driver(node_t *node, driver_t *drv)
+void attach_driver(dev_node_t *dev, driver_t *drv)
 {
 	printf(NAME ": attach_driver %s to device %s\n",
-	    drv->name, node->pathname);
+	    drv->name, dev->pfun->pathname);
 	
 	fibril_mutex_lock(&drv->driver_mutex);
 	
-	node->drv = drv;
-	list_append(&node->driver_devices, &drv->devices);
+	dev->drv = drv;
+	list_append(&dev->driver_devices, &drv->devices);
 	
 	fibril_mutex_unlock(&drv->driver_mutex);
@@ -530,5 +569,5 @@
 static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree)
 {
-	node_t *dev;
+	dev_node_t *dev;
 	link_t *link;
 	int phone;
@@ -551,5 +590,5 @@
 	link = driver->devices.next;
 	while (link != &driver->devices) {
-		dev = list_get_instance(link, node_t, driver_devices);
+		dev = list_get_instance(link, dev_node_t, driver_devices);
 		if (dev->passed_to_driver) {
 			link = link->next;
@@ -669,11 +708,11 @@
 }
 
-/** Create devmap path and name for the device. */
-static void devmap_register_tree_device(node_t *node, dev_tree_t *tree)
+/** Create devmap path and name for the function. */
+void devmap_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
 {
 	char *devmap_pathname = NULL;
 	char *devmap_name = NULL;
 	
-	asprintf(&devmap_name, "%s", node->pathname);
+	asprintf(&devmap_name, "%s", fun->pathname);
 	if (devmap_name == NULL)
 		return;
@@ -689,7 +728,7 @@
 	
 	devmap_device_register_with_iface(devmap_pathname,
-	    &node->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
-	
-	tree_add_devmap_device(tree, node);
+	    &fun->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
+	
+	tree_add_devmap_function(tree, fun);
 	
 	free(devmap_name);
@@ -702,5 +741,5 @@
  * @param node		The device's node in the device tree.
  */
-void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)
+void add_device(int phone, driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
 {
 	/*
@@ -709,5 +748,5 @@
 	 */
 	printf(NAME ": add_device (driver `%s', device `%s')\n", drv->name,
-	    node->name);
+	    dev->pfun->name);
 	
 	sysarg_t rc;
@@ -716,16 +755,16 @@
 	/* Send the device to the driver. */
 	devman_handle_t parent_handle;
-	if (node->parent) {
-		parent_handle = node->parent->handle;
+	if (dev->pfun) {
+		parent_handle = dev->pfun->handle;
 	} else {
 		parent_handle = 0;
 	}
 
-	aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, node->handle,
+	aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, dev->handle,
 	    parent_handle, &answer);
 	
 	/* Send the device's name to the driver. */
-	rc = async_data_write_start(phone, node->name,
-	    str_size(node->name) + 1);
+	rc = async_data_write_start(phone, dev->pfun->name,
+	    str_size(dev->pfun->name) + 1);
 	if (rc != EOK) {
 		/* TODO handle error */
@@ -737,15 +776,14 @@
 	switch(rc) {
 	case EOK:
-		node->state = DEVICE_USABLE;
-		devmap_register_tree_device(node, tree);
+		dev->state = DEVICE_USABLE;
 		break;
 	case ENOENT:
-		node->state = DEVICE_NOT_PRESENT;
+		dev->state = DEVICE_NOT_PRESENT;
 		break;
 	default:
-		node->state = DEVICE_INVALID;
-	}
-	
-	node->passed_to_driver = true;
+		dev->state = DEVICE_INVALID;
+	}
+	
+	dev->passed_to_driver = true;
 
 	return;
@@ -759,18 +797,23 @@
  *			successfully assigned to the device, false otherwise.
  */
-bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree)
-{
+bool assign_driver(dev_node_t *dev, driver_list_t *drivers_list,
+    dev_tree_t *tree)
+{
+	assert(dev != NULL);
+	assert(drivers_list != NULL);
+	assert(tree != NULL);
+	
 	/*
 	 * Find the driver which is the most suitable for handling this device.
 	 */
-	driver_t *drv = find_best_match_driver(drivers_list, node);
+	driver_t *drv = find_best_match_driver(drivers_list, dev);
 	if (drv == NULL) {
 		printf(NAME ": no driver found for device '%s'.\n",
-		    node->pathname);
+		    dev->pfun->pathname);
 		return false;
 	}
 	
 	/* Attach the driver to the device. */
-	attach_driver(node, drv);
+	attach_driver(dev, drv);
 	
 	fibril_mutex_lock(&drv->driver_mutex);
@@ -786,5 +829,5 @@
 		int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
 		if (phone >= 0) {
-			add_device(phone, drv, node, tree);
+			add_device(phone, drv, dev, tree);
 			async_hangup(phone);
 		}
@@ -810,15 +853,17 @@
 	hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1,
 	    &devman_devices_ops);
-	hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1,
+	hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1,
+	    &devman_functions_ops);
+	hash_table_create(&tree->devmap_functions, DEVICE_BUCKETS, 1,
 	    &devmap_devices_ops);
 	
 	fibril_rwlock_initialize(&tree->rwlock);
 	
-	/* Create root node and add it to the device tree. */
-	if (!create_root_node(tree))
+	/* Create root function and root device and add them to the device tree. */
+	if (!create_root_nodes(tree))
 		return false;
 
 	/* Find suitable driver and start it. */
-	return assign_driver(tree->root_node, drivers_list, tree);
+	return assign_driver(tree->root_node->child, drivers_list, tree);
 }
 
@@ -829,13 +874,13 @@
  * @return		A device node structure.
  */
-node_t *create_dev_node(void)
-{
-	node_t *res = malloc(sizeof(node_t));
+dev_node_t *create_dev_node(void)
+{
+	dev_node_t *res = malloc(sizeof(dev_node_t));
 	
 	if (res != NULL) {
-		memset(res, 0, sizeof(node_t));
-		list_initialize(&res->children);
-		list_initialize(&res->match_ids.ids);
-		list_initialize(&res->classes);
+		memset(res, 0, sizeof(dev_node_t));
+		list_initialize(&res->functions);
+		link_initialize(&res->driver_devices);
+		link_initialize(&res->devman_dev);
 	}
 	
@@ -847,14 +892,11 @@
  * @param node		The device node structure.
  */
-void delete_dev_node(node_t *node)
-{
-	assert(list_empty(&node->children));
-	assert(node->parent == NULL);
-	assert(node->drv == NULL);
-	
-	clean_match_ids(&node->match_ids);
-	free_not_null(node->name);
-	free_not_null(node->pathname);
-	free(node);
+void delete_dev_node(dev_node_t *dev)
+{
+	assert(list_empty(&dev->functions));
+	assert(dev->pfun == NULL);
+	assert(dev->drv == NULL);
+	
+	free(dev);
 }
 
@@ -865,5 +907,5 @@
  * @return		The device node.
  */
-node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
+dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
 {
 	unsigned long key = handle;
@@ -873,5 +915,5 @@
 	
 	link = hash_table_find(&tree->devman_devices, &key);
-	return hash_table_get_instance(link, node_t, devman_link);
+	return hash_table_get_instance(link, dev_node_t, devman_dev);
 }
 
@@ -882,15 +924,88 @@
  * @return		The device node.
  */
-node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle)
-{
-	node_t *node = NULL;
+dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle)
+{
+	dev_node_t *dev = NULL;
 	
 	fibril_rwlock_read_lock(&tree->rwlock);
-	node = find_dev_node_no_lock(tree, handle);
+	dev = find_dev_node_no_lock(tree, handle);
 	fibril_rwlock_read_unlock(&tree->rwlock);
 	
-	return node;
-}
-
+	return dev;
+}
+
+/* Function nodes */
+
+/** Create a new function node.
+ *
+ * @return		A function node structure.
+ */
+fun_node_t *create_fun_node(void)
+{
+	fun_node_t *res = malloc(sizeof(fun_node_t));
+	
+	if (res != NULL) {
+		memset(res, 0, sizeof(fun_node_t));
+		link_initialize(&res->dev_functions);
+		list_initialize(&res->match_ids.ids);
+		list_initialize(&res->classes);
+		link_initialize(&res->devman_fun);
+		link_initialize(&res->devmap_fun);
+	}
+	
+	return res;
+}
+
+/** Delete a function node.
+ *
+ * @param fun		The device node structure.
+ */
+void delete_fun_node(fun_node_t *fun)
+{
+	assert(fun->dev == NULL);
+	assert(fun->child == NULL);
+	
+	clean_match_ids(&fun->match_ids);
+	free_not_null(fun->name);
+	free_not_null(fun->pathname);
+	free(fun);
+}
+
+/** Find the function node with the specified handle.
+ *
+ * @param tree		The device tree where we look for the device node.
+ * @param handle	The handle of the function.
+ * @return		The function node.
+ */
+fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
+{
+	unsigned long key = handle;
+	link_t *link;
+	
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+	
+	link = hash_table_find(&tree->devman_functions, &key);
+	if (link == NULL)
+		return NULL;
+	
+	return hash_table_get_instance(link, fun_node_t, devman_fun);
+}
+
+/** Find the function node with the specified handle.
+ *
+ * @param tree		The device tree where we look for the device node.
+ * @param handle	The handle of the function.
+ * @return		The function node.
+ */
+fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle)
+{
+	fun_node_t *fun = NULL;
+	
+	fibril_rwlock_read_lock(&tree->rwlock);
+	fun = find_fun_node_no_lock(tree, handle);
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	return fun;
+}
 
 /** Create and set device's full path in device tree.
@@ -901,14 +1016,14 @@
  *			resources etc.).
  */
-static bool set_dev_path(node_t *node, node_t *parent)
-{
-	assert(node->name != NULL);
-	
-	size_t pathsize = (str_size(node->name) + 1);
+static bool set_fun_path(fun_node_t *fun, fun_node_t *parent)
+{
+	assert(fun->name != NULL);
+	
+	size_t pathsize = (str_size(fun->name) + 1);
 	if (parent != NULL)
 		pathsize += str_size(parent->pathname) + 1;
 	
-	node->pathname = (char *) malloc(pathsize);
-	if (node->pathname == NULL) {
+	fun->pathname = (char *) malloc(pathsize);
+	if (fun->pathname == NULL) {
 		printf(NAME ": failed to allocate device path.\n");
 		return false;
@@ -916,9 +1031,9 @@
 	
 	if (parent != NULL) {
-		str_cpy(node->pathname, pathsize, parent->pathname);
-		str_append(node->pathname, pathsize, "/");
-		str_append(node->pathname, pathsize, node->name);
+		str_cpy(fun->pathname, pathsize, parent->pathname);
+		str_append(fun->pathname, pathsize, "/");
+		str_append(fun->pathname, pathsize, fun->name);
 	} else {
-		str_cpy(node->pathname, pathsize, node->name);
+		str_cpy(fun->pathname, pathsize, fun->name);
 	}
 	
@@ -936,44 +1051,81 @@
  *			etc.).
  */
-bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name,
-    node_t *parent)
-{
-	assert(node != NULL);
+bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun)
+{
+	assert(dev != NULL);
 	assert(tree != NULL);
-	assert(dev_name != NULL);
 	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
 	
-	node->name = dev_name;
-	if (!set_dev_path(node, parent)) {
+	/* Add the node to the handle-to-node map. */
+	dev->handle = ++tree->current_handle;
+	unsigned long key = dev->handle;
+	hash_table_insert(&tree->devman_devices, &key, &dev->devman_dev);
+
+	/* Add the node to the list of its parent's children. */
+	printf("insert_dev_node: dev=%p, dev->pfun := %p\n", dev, pfun);
+	dev->pfun = pfun;
+	pfun->child = dev;
+	
+	return true;
+}
+
+/** Insert new function into device tree.
+ *
+ * @param tree		The device tree.
+ * @param node		The newly added function node. 
+ * @param dev_name	The name of the newly added function.
+ * @param parent	Owning device node.
+ *
+ * @return		True on success, false otherwise (insufficient resources
+ *			etc.).
+ */
+bool insert_fun_node(dev_tree_t *tree, fun_node_t *fun, char *fun_name,
+    dev_node_t *dev)
+{
+	fun_node_t *pfun;
+	
+	assert(fun != NULL);
+	assert(tree != NULL);
+	assert(fun_name != NULL);
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
+	
+	/*
+	 * The root function is a special case, it does not belong to any
+	 * device so for the root function dev == NULL.
+	 */
+	pfun = (dev != NULL) ? dev->pfun : NULL;
+	
+	fun->name = fun_name;
+	if (!set_fun_path(fun, pfun)) {
 		return false;
 	}
 	
 	/* Add the node to the handle-to-node map. */
-	node->handle = ++tree->current_handle;
-	unsigned long key = node->handle;
-	hash_table_insert(&tree->devman_devices, &key, &node->devman_link);
+	fun->handle = ++tree->current_handle;
+	unsigned long key = fun->handle;
+	hash_table_insert(&tree->devman_functions, &key, &fun->devman_fun);
 
 	/* Add the node to the list of its parent's children. */
-	node->parent = parent;
-	if (parent != NULL)
-		list_append(&node->sibling, &parent->children);
+	fun->dev = dev;
+	if (dev != NULL)
+		list_append(&fun->dev_functions, &dev->functions);
 	
 	return true;
 }
 
-/** Find device node with a specified path in the device tree.
+/** Find function node with a specified path in the device tree.
  * 
- * @param path		The path of the device node in the device tree.
+ * @param path		The path of the function node in the device tree.
  * @param tree		The device tree.
- * @return		The device node if it is present in the tree, NULL
+ * @return		The function node if it is present in the tree, NULL
  *			otherwise.
  */
-node_t *find_dev_node_by_path(dev_tree_t *tree, char *path)
+fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path)
 {
 	fibril_rwlock_read_lock(&tree->rwlock);
 	
-	node_t *dev = tree->root_node;
+	fun_node_t *fun = tree->root_node;
 	/*
-	 * Relative path to the device from its parent (but with '/' at the
+	 * Relative path to the function from its parent (but with '/' at the
 	 * beginning)
 	 */
@@ -982,5 +1134,5 @@
 	bool cont = (rel_path[0] == '/');
 	
-	while (cont && dev != NULL) {
+	while (cont && fun != NULL) {
 		next_path_elem  = get_path_elem_end(rel_path + 1);
 		if (next_path_elem[0] == '/') {
@@ -991,5 +1143,5 @@
 		}
 		
-		dev = find_node_child(dev, rel_path + 1);
+		fun = find_node_child(fun, rel_path + 1);
 		
 		if (cont) {
@@ -1002,27 +1154,27 @@
 	fibril_rwlock_read_unlock(&tree->rwlock);
 	
-	return dev;
-}
-
-/** Find child device node with a specified name.
+	return fun;
+}
+
+/** Find child function node with a specified name.
  *
  * Device tree rwlock should be held at least for reading.
  *
- * @param parent	The parent device node.
- * @param name		The name of the child device node.
- * @return		The child device node.
- */
-node_t *find_node_child(node_t *parent, const char *name)
-{
-	node_t *dev;
+ * @param parent	The parent function node.
+ * @param name		The name of the child function.
+ * @return		The child function node.
+ */
+fun_node_t *find_node_child(fun_node_t *pfun, const char *name)
+{
+	fun_node_t *fun;
 	link_t *link;
 	
-	link = parent->children.next;
-	
-	while (link != &parent->children) {
-		dev = list_get_instance(link, node_t, sibling);
+	link = pfun->child->functions.next;
+	
+	while (link != &pfun->child->functions) {
+		fun = list_get_instance(link, fun_node_t, dev_functions);
 		
-		if (str_cmp(name, dev->name) == 0)
-			return dev;
+		if (str_cmp(name, fun->name) == 0)
+			return fun;
 		
 		link = link->next;
@@ -1107,5 +1259,5 @@
 }
 
-/** Add the device to the class.
+/** Add the device function to the class.
  *
  * The device may be added to multiple classes and a class may contain multiple
@@ -1120,12 +1272,18 @@
  *			with the class.
  */
-dev_class_info_t *add_device_to_class(node_t *dev, dev_class_t *cl,
+dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl,
     const char *base_dev_name)
 {
-	dev_class_info_t *info = create_dev_class_info();
+	dev_class_info_t *info;
+
+	assert(fun != NULL);
+	assert(cl != NULL);
+
+	info = create_dev_class_info();
+
 	
 	if (info != NULL) {
 		info->dev_class = cl;
-		info->dev = dev;
+		info->fun = fun;
 		
 		/* Add the device to the class. */
@@ -1135,5 +1293,5 @@
 		
 		/* Add the class to the device. */
-		list_append(&info->dev_classes, &dev->classes);
+		list_append(&info->dev_classes, &fun->classes);
 		
 		/* Create unique name for the device within the class. */
@@ -1189,5 +1347,5 @@
 	list_initialize(&class_list->classes);
 	fibril_rwlock_initialize(&class_list->rwlock);
-	hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1,
+	hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1,
 	    &devmap_devices_class_ops);
 }
@@ -1196,23 +1354,23 @@
 /* Devmap devices */
 
-node_t *find_devmap_tree_device(dev_tree_t *tree, devmap_handle_t devmap_handle)
-{
-	node_t *dev = NULL;
+fun_node_t *find_devmap_tree_function(dev_tree_t *tree, devmap_handle_t devmap_handle)
+{
+	fun_node_t *fun = NULL;
 	link_t *link;
 	unsigned long key = (unsigned long) devmap_handle;
 	
 	fibril_rwlock_read_lock(&tree->rwlock);
-	link = hash_table_find(&tree->devmap_devices, &key);
+	link = hash_table_find(&tree->devmap_functions, &key);
 	if (link != NULL)
-		dev = hash_table_get_instance(link, node_t, devmap_link);
+		fun = hash_table_get_instance(link, fun_node_t, devmap_fun);
 	fibril_rwlock_read_unlock(&tree->rwlock);
 	
-	return dev;
-}
-
-node_t *find_devmap_class_device(class_list_t *classes,
+	return fun;
+}
+
+fun_node_t *find_devmap_class_function(class_list_t *classes,
     devmap_handle_t devmap_handle)
 {
-	node_t *dev = NULL;
+	fun_node_t *fun = NULL;
 	dev_class_info_t *cli;
 	link_t *link;
@@ -1220,31 +1378,31 @@
 	
 	fibril_rwlock_read_lock(&classes->rwlock);
-	link = hash_table_find(&classes->devmap_devices, &key);
+	link = hash_table_find(&classes->devmap_functions, &key);
 	if (link != NULL) {
 		cli = hash_table_get_instance(link, dev_class_info_t,
 		    devmap_link);
-		dev = cli->dev;
+		fun = cli->fun;
 	}
 	fibril_rwlock_read_unlock(&classes->rwlock);
 	
-	return dev;
-}
-
-void class_add_devmap_device(class_list_t *class_list, dev_class_info_t *cli)
+	return fun;
+}
+
+void class_add_devmap_function(class_list_t *class_list, dev_class_info_t *cli)
 {
 	unsigned long key = (unsigned long) cli->devmap_handle;
 	
 	fibril_rwlock_write_lock(&class_list->rwlock);
-	hash_table_insert(&class_list->devmap_devices, &key, &cli->devmap_link);
+	hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link);
 	fibril_rwlock_write_unlock(&class_list->rwlock);
 
-	assert(find_devmap_class_device(class_list, cli->devmap_handle) != NULL);
-}
-
-void tree_add_devmap_device(dev_tree_t *tree, node_t *node)
-{
-	unsigned long key = (unsigned long) node->devmap_handle;
+	assert(find_devmap_class_function(class_list, cli->devmap_handle) != NULL);
+}
+
+void tree_add_devmap_function(dev_tree_t *tree, fun_node_t *fun)
+{
+	unsigned long key = (unsigned long) fun->devmap_handle;
 	fibril_rwlock_write_lock(&tree->rwlock);
-	hash_table_insert(&tree->devmap_devices, &key, &node->devmap_link);
+	hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun);
 	fibril_rwlock_write_unlock(&tree->rwlock);
 }
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/devman/devman.h	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -56,6 +56,9 @@
 #define DEVMAP_SEPARATOR '\\'
 
-struct node;
-typedef struct node node_t;
+struct dev_node;
+typedef struct dev_node dev_node_t;
+
+struct fun_node;
+typedef struct fun_node fun_node_t;
 
 typedef enum {
@@ -117,55 +120,26 @@
 } device_state_t;
 
-/** Representation of a node in the device tree. */
-struct node {
+/** Device node in the device tree. */
+struct dev_node {
 	/** The global unique identifier of the device. */
 	devman_handle_t handle;
-	/** The name of the device specified by its parent. */
-	char *name;
-	
-	/**
-	 * Full path and name of the device in device hierarchi (i. e. in full
-	 * path in device tree).
-	 */
-	char *pathname;
-	
-	/** The node of the parent device. */
-	node_t *parent;
-	
-	/**
-	 * Pointers to previous and next child devices in the linked list of
-	 * parent device's node.
-	 */
-	link_t sibling;
-	
-	/** List of child device nodes. */
-	link_t children;
-	/** List of device ids for device-to-driver matching. */
-	match_id_list_t match_ids;
+	
+	/** (Parent) function the device is attached to. */
+	fun_node_t *pfun;
+	
+	/** List of device functions. */
+	link_t functions;
 	/** Driver of this device. */
 	driver_t *drv;
 	/** The state of the device. */
 	device_state_t state;
-	/**
-	 * Pointer to the previous and next device in the list of devices
-	 * owned by one driver.
-	 */
+	/** Link to list of devices owned by driver (driver_t.devices) */
 	link_t driver_devices;
 	
-	/** The list of device classes to which this device belongs. */
-	link_t classes;
-	/** Devmap handle if the device is registered by devmapper. */
-	devmap_handle_t devmap_handle;
-	
 	/**
 	 * Used by the hash table of devices indexed by devman device handles.
 	 */
-	link_t devman_link;
-	
-	/**
-	 * Used by the hash table of devices indexed by devmap device handles.
-	 */
-	link_t devmap_link;
-
+	link_t devman_dev;
+	
 	/**
 	 * Whether this device was already passed to the driver.
@@ -173,9 +147,47 @@
 	bool passed_to_driver;
 };
+
+/** Function node in the device tree. */
+struct fun_node {
+	/** The global unique identifier of the function */
+	devman_handle_t handle;
+	/** Name of the function, assigned by the device driver */
+	char *name;
+	
+	/** Full path and name of the device in device hierarchy */
+	char *pathname;
+	
+	/** Device which this function belongs to */
+	dev_node_t *dev;
+	
+	/** Link to list of functions in the device (ddf_dev_t.functions) */
+	link_t dev_functions;
+	
+	/** Child device node (if any attached). */
+	dev_node_t *child;
+	/** List of device ids for device-to-driver matching. */
+	match_id_list_t match_ids;
+	
+	/** The list of device classes to which this device function belongs. */
+	link_t classes;
+	/** Devmap handle if the device function is registered by devmap. */
+	devmap_handle_t devmap_handle;
+	
+	/**
+	 * Used by the hash table of functions indexed by devman device handles.
+	 */
+	link_t devman_fun;
+	
+	/**
+	 * Used by the hash table of functions indexed by devmap device handles.
+	 */
+	link_t devmap_fun;
+};
+
 
 /** Represents device tree. */
 typedef struct dev_tree {
 	/** Root device node. */
-	node_t *root_node;
+	fun_node_t *root_node;
 	
 	/**
@@ -191,9 +203,12 @@
 	hash_table_t devman_devices;
 	
+	/** Hash table of all devices indexed by devman handles. */
+	hash_table_t devman_functions;
+	
 	/**
 	 * Hash table of devices registered by devmapper, indexed by devmap
 	 * handles.
 	 */
-	hash_table_t devmap_devices;
+	hash_table_t devmap_functions;
 } dev_tree_t;
 
@@ -227,7 +242,7 @@
 
 /**
- * Provides n-to-m mapping between device nodes and classes - each device may
- * be register to the arbitrary number of classes and each class may contain
- * the arbitrary number of devices.
+ * Provides n-to-m mapping between function nodes and classes - each function
+ * can register in an arbitrary number of classes and each class can contain
+ * an arbitrary number of device functions.
  */
 typedef struct dev_class_info {
@@ -235,5 +250,5 @@
 	dev_class_t *dev_class;
 	/** The device. */
-	node_t *dev;
+	fun_node_t *fun;
 	
 	/**
@@ -249,5 +264,5 @@
 	link_t dev_classes;
 	
-	/** The name of the device within the class. */
+	/** The name of the device function within the class. */
 	char *dev_name;
 	/** The handle of the device by device mapper in the class namespace. */
@@ -270,5 +285,5 @@
 	 * indexed by devmap handles.
 	 */
-	hash_table_t devmap_devices;
+	hash_table_t devmap_functions;
 	
 	/** Fibril mutex for list of classes. */
@@ -278,5 +293,5 @@
 /* Match ids and scores */
 
-extern int get_match_score(driver_t *, node_t *);
+extern int get_match_score(driver_t *, dev_node_t *);
 
 extern bool parse_match_ids(char *, match_id_list_t *);
@@ -292,10 +307,10 @@
 extern int lookup_available_drivers(driver_list_t *, const char *);
 
-extern driver_t *find_best_match_driver(driver_list_t *, node_t *);
-extern bool assign_driver(node_t *, driver_list_t *, dev_tree_t *);
+extern driver_t *find_best_match_driver(driver_list_t *, dev_node_t *);
+extern bool assign_driver(dev_node_t *, driver_list_t *, dev_tree_t *);
 
 extern void add_driver(driver_list_t *, driver_t *);
-extern void attach_driver(node_t *, driver_t *);
-extern void add_device(int, driver_t *, node_t *, dev_tree_t *);
+extern void attach_driver(dev_node_t *, driver_t *);
+extern void add_device(int, driver_t *, dev_node_t *, dev_tree_t *);
 extern bool start_driver(driver_t *);
 
@@ -310,17 +325,24 @@
 /* Device nodes */
 
-extern node_t *create_dev_node(void);
-extern void delete_dev_node(node_t *node);
-extern node_t *find_dev_node_no_lock(dev_tree_t *tree,
+extern dev_node_t *create_dev_node(void);
+extern void delete_dev_node(dev_node_t *node);
+extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree,
     devman_handle_t handle);
-extern node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle);
-extern node_t *find_dev_node_by_path(dev_tree_t *, char *);
-extern node_t *find_node_child(node_t *, const char *);
+extern dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle);
+extern dev_node_t *find_dev_function(dev_node_t *, const char *);
+
+extern fun_node_t *create_fun_node(void);
+extern void delete_fun_node(fun_node_t *);
+extern fun_node_t *find_fun_node_no_lock(dev_tree_t *tree,
+    devman_handle_t handle);
+extern fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle);
+extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *);
 
 /* Device tree */
 
 extern bool init_device_tree(dev_tree_t *, driver_list_t *);
-extern bool create_root_node(dev_tree_t *);
-extern bool insert_dev_node(dev_tree_t *, node_t *, char *, node_t *);
+extern bool create_root_nodes(dev_tree_t *);
+extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *);
+extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *);
 
 /* Device classes */
@@ -330,5 +352,5 @@
 extern size_t get_new_class_dev_idx(dev_class_t *);
 extern char *create_dev_name_for_class(dev_class_t *, const char *);
-extern dev_class_info_t *add_device_to_class(node_t *, dev_class_t *,
+extern dev_class_info_t *add_function_to_class(fun_node_t *, dev_class_t *,
     const char *);
 
@@ -341,9 +363,11 @@
 /* Devmap devices */
 
-extern node_t *find_devmap_tree_device(dev_tree_t *, devmap_handle_t);
-extern node_t *find_devmap_class_device(class_list_t *, devmap_handle_t);
-
-extern void class_add_devmap_device(class_list_t *, dev_class_info_t *);
-extern void tree_add_devmap_device(dev_tree_t *, node_t *);
+extern void devmap_register_tree_function(fun_node_t *, dev_tree_t *);
+
+extern fun_node_t *find_devmap_tree_function(dev_tree_t *, devmap_handle_t);
+extern fun_node_t *find_devmap_class_function(class_list_t *, devmap_handle_t);
+
+extern void class_add_devmap_function(class_list_t *, dev_class_info_t *);
+extern void tree_add_devmap_function(dev_tree_t *, fun_node_t *);
 
 #endif
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/devman/main.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -199,23 +199,26 @@
 static int assign_driver_fibril(void *arg)
 {
-	node_t *node = (node_t *) arg;
-	assign_driver(node, &drivers_list, &device_tree);
+	dev_node_t *dev_node = (dev_node_t *) arg;
+	assign_driver(dev_node, &drivers_list, &device_tree);
 	return EOK;
 }
 
-/** Handle child device registration.
+/** Handle function registration.
  *
  * Child devices are registered by their parent's device driver.
  */
-static void devman_add_child(ipc_callid_t callid, ipc_call_t *call)
-{
-	devman_handle_t parent_handle = IPC_GET_ARG1(*call);
-	sysarg_t match_count = IPC_GET_ARG2(*call);
+static void devman_add_function(ipc_callid_t callid, ipc_call_t *call)
+{
+	fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call);
+	devman_handle_t dev_handle = IPC_GET_ARG2(*call);
+	sysarg_t match_count = IPC_GET_ARG3(*call);
 	dev_tree_t *tree = &device_tree;
 	
 	fibril_rwlock_write_lock(&tree->rwlock);
-	node_t *parent = find_dev_node_no_lock(&device_tree, parent_handle);
-	
-	if (parent == NULL) {
+
+	dev_node_t *dev = NULL;
+	dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle);
+	
+	if (pdev == NULL) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
 		async_answer_0(callid, ENOENT);
@@ -223,6 +226,15 @@
 	}
 	
-	char *dev_name = NULL;
-	int rc = async_data_write_accept((void **)&dev_name, true, 0, 0, 0, 0);
+	if (ftype != fun_inner && ftype != fun_exposed) {
+		/* Unknown function type */
+		printf(NAME ": Error, unknown function type provided by driver!\n");
+
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+	
+	char *fun_name = NULL;
+	int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0);
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
@@ -231,38 +243,55 @@
 	}
 	
-	node_t *node = create_dev_node();
-	if (!insert_dev_node(&device_tree, node, dev_name, parent)) {
+	fun_node_t *fun = create_fun_node();
+	if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
-		delete_dev_node(node);
+		delete_fun_node(fun);
 		async_answer_0(callid, ENOMEM);
 		return;
 	}
 
+	if (ftype == fun_inner) {
+		dev = create_dev_node();
+		if (dev == NULL) {
+			fibril_rwlock_write_unlock(&tree->rwlock);
+			delete_fun_node(fun);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+
+		insert_dev_node(tree, dev, fun);
+	}
+
 	fibril_rwlock_write_unlock(&tree->rwlock);
 	
-	printf(NAME ": devman_add_child %s\n", node->pathname);
-	
-	devman_receive_match_ids(match_count, &node->match_ids);
-
-	/*
-	 * Try to find a suitable driver and assign it to the device.  We do
-	 * not want to block the current fibril that is used for processing
-	 * incoming calls: we will launch a separate fibril to handle the
-	 * driver assigning. That is because assign_driver can actually include
-	 * task spawning which could take some time.
-	 */
-	fid_t assign_fibril = fibril_create(assign_driver_fibril, node);
-	if (assign_fibril == 0) {
+	printf(NAME ": devman_add_function %s\n", fun->pathname);
+	
+	devman_receive_match_ids(match_count, &fun->match_ids);
+
+	if (ftype == fun_inner) {
+		assert(dev != NULL);
 		/*
-		 * Fallback in case we are out of memory.
-		 * Probably not needed as we will die soon anyway ;-).
+		 * Try to find a suitable driver and assign it to the device.  We do
+		 * not want to block the current fibril that is used for processing
+		 * incoming calls: we will launch a separate fibril to handle the
+		 * driver assigning. That is because assign_driver can actually include
+		 * task spawning which could take some time.
 		 */
-		(void) assign_driver_fibril(node);
+		fid_t assign_fibril = fibril_create(assign_driver_fibril, dev);
+		if (assign_fibril == 0) {
+			/*
+			 * Fallback in case we are out of memory.
+			 * Probably not needed as we will die soon anyway ;-).
+			 */
+			(void) assign_driver_fibril(fun);
+		} else {
+			fibril_add_ready(assign_fibril);
+		}
 	} else {
-		fibril_add_ready(assign_fibril);
-	}
-
+		devmap_register_tree_function(fun, tree);
+	}
+	
 	/* Return device handle to parent's driver. */
-	async_answer_1(callid, EOK, node->handle);
+	async_answer_1(callid, EOK, fun->handle);
 }
 
@@ -288,10 +317,10 @@
 	 * mapper.
 	 */
-	class_add_devmap_device(&class_list, cli);
+	class_add_devmap_function(&class_list, cli);
 	
 	free(devmap_pathname);
 }
 
-static void devman_add_device_to_class(ipc_callid_t callid, ipc_call_t *call)
+static void devman_add_function_to_class(ipc_callid_t callid, ipc_call_t *call)
 {
 	devman_handle_t handle = IPC_GET_ARG1(*call);
@@ -306,6 +335,6 @@
 	}	
 	
-	node_t *dev = find_dev_node(&device_tree, handle);
-	if (dev == NULL) {
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
 		async_answer_0(callid, ENOENT);
 		return;
@@ -313,11 +342,11 @@
 	
 	dev_class_t *cl = get_dev_class(&class_list, class_name);
-	dev_class_info_t *class_info = add_device_to_class(dev, cl, NULL);
+	dev_class_info_t *class_info = add_function_to_class(fun, cl, NULL);
 	
 	/* Register the device's class alias by devmapper. */
 	devmap_register_class_dev(class_info);
 	
-	printf(NAME ": device '%s' added to class '%s', class name '%s' was "
-	    "asigned to it\n", dev->pathname, class_name, class_info->dev_name);
+	printf(NAME ": function'%s' added to class '%s', class name '%s' was "
+	    "asigned to it\n", fun->pathname, class_name, class_info->dev_name);
 
 	async_answer_0(callid, EOK);
@@ -372,9 +401,9 @@
 			cont = false;
 			continue;
-		case DEVMAN_ADD_CHILD_DEVICE:
-			devman_add_child(callid, &call);
+		case DEVMAN_ADD_FUNCTION:
+			devman_add_function(callid, &call);
 			break;
 		case DEVMAN_ADD_DEVICE_TO_CLASS:
-			devman_add_device_to_class(callid, &call);
+			devman_add_function_to_class(callid, &call);
 			break;
 		default:
@@ -387,5 +416,5 @@
 /** Find handle for the device instance identified by the device's path in the
  * device tree. */
-static void devman_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
+static void devman_function_get_handle(ipc_callid_t iid, ipc_call_t *icall)
 {
 	char *pathname;
@@ -397,14 +426,14 @@
 	}
 	
-	node_t * dev = find_dev_node_by_path(&device_tree, pathname);
+	fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname);
 	
 	free(pathname);
 
-	if (dev == NULL) {
+	if (fun == NULL) {
 		async_answer_0(iid, ENOENT);
 		return;
 	}
-	
-	async_answer_1(iid, EOK, dev->handle);
+
+	async_answer_1(iid, EOK, fun->handle);
 }
 
@@ -426,5 +455,5 @@
 			continue;
 		case DEVMAN_DEVICE_GET_HANDLE:
-			devman_device_get_handle(callid, &call);
+			devman_function_get_handle(callid, &call);
 			break;
 		default:
@@ -438,21 +467,41 @@
 {
 	devman_handle_t handle = IPC_GET_ARG2(*icall);
-	
-	node_t *dev = find_dev_node(&device_tree, handle);
-	if (dev == NULL) {
-		printf(NAME ": devman_forward error - no device with handle %" PRIun
-		    " was found.\n", handle);
+	devman_handle_t fwd_h;
+	fun_node_t *fun = NULL;
+	dev_node_t *dev = NULL;
+	
+	fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL)
+		dev = find_dev_node(&device_tree, handle);
+	else
+		dev = fun->dev;
+
+	if (fun == NULL && dev == NULL) {
+		printf(NAME ": devman_forward error - no device or function with "
+		    "handle %" PRIun " was found.\n", handle);
 		async_answer_0(iid, ENOENT);
 		return;
 	}
+
+	if (fun == NULL && !drv_to_parent) {
+		printf(NAME ": devman_forward error - cannot connect to "
+		    "handle %" PRIun ", refers to a device.\n", handle);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
 	
 	driver_t *driver = NULL;
 	
 	if (drv_to_parent) {
-		if (dev->parent != NULL)
-			driver = dev->parent->drv;
+		/* Connect to parent function of a device (or device function). */
+		if (dev->pfun->dev != NULL)
+			driver = dev->pfun->dev->drv;
+		fwd_h = dev->pfun->handle;
 	} else if (dev->state == DEVICE_USABLE) {
+		/* Connect to the specified function */
 		driver = dev->drv;
 		assert(driver != NULL);
+
+		fwd_h = handle;
 	}
 	
@@ -478,7 +527,13 @@
 	}
 
-	printf(NAME ": devman_forward: forward connection to device %s to "
-	    "driver %s.\n", dev->pathname, driver->name);
-	async_forward_fast(iid, driver->phone, method, dev->handle, 0, IPC_FF_NONE);
+	if (fun != NULL) {
+		printf(NAME ": devman_forward: forward connection to function %s to "
+		    "driver %s.\n", fun->pathname, driver->name);
+	} else {
+		printf(NAME ": devman_forward: forward connection to device %s to "
+		    "driver %s.\n", dev->pfun->pathname, driver->name);
+	}
+
+	async_forward_fast(iid, driver->phone, method, fwd_h, 0, IPC_FF_NONE);
 }
 
@@ -488,14 +543,17 @@
 {
 	devmap_handle_t devmap_handle = IPC_GET_ARG2(*icall);
-	node_t *dev;
-
-	dev = find_devmap_tree_device(&device_tree, devmap_handle);
-	if (dev == NULL)
-		dev = find_devmap_class_device(&class_list, devmap_handle);
-	
-	if (dev == NULL || dev->drv == NULL) {
+	fun_node_t *fun;
+	dev_node_t *dev;
+
+	fun = find_devmap_tree_function(&device_tree, devmap_handle);
+	if (fun == NULL)
+		fun = find_devmap_class_function(&class_list, devmap_handle);
+	
+	if (fun == NULL || fun->dev->drv == NULL) {
 		async_answer_0(iid, ENOENT);
 		return;
 	}
+	
+	dev = fun->dev;
 	
 	if (dev->state != DEVICE_USABLE || dev->drv->phone <= 0) {
@@ -504,8 +562,8 @@
 	}
 	
-	async_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, dev->handle, 0,
+	async_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, fun->handle, 0,
 	    IPC_FF_NONE);
 	printf(NAME ": devman_connection_devmapper: forwarded connection to "
-	    "device %s to driver %s.\n", dev->pathname, dev->drv->name);
+	    "device %s to driver %s.\n", fun->pathname, dev->drv->name);
 }
 
Index: uspace/srv/devman/match.c
===================================================================
--- uspace/srv/devman/match.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/devman/match.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -57,8 +57,8 @@
 }
 
-int get_match_score(driver_t *drv, node_t *dev)
+int get_match_score(driver_t *drv, dev_node_t *dev)
 {
 	link_t *drv_head = &drv->match_ids.ids;
-	link_t *dev_head = &dev->match_ids.ids;
+	link_t *dev_head = &dev->pfun->match_ids.ids;
 	
 	if (list_empty(drv_head) || list_empty(dev_head))
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/devmap/devmap.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -123,4 +123,10 @@
 static devmap_handle_t last_handle = 0;
 static devmap_device_t *null_devices[NULL_DEVICES];
+
+/*
+ * Dummy list for null devices. This is necessary so that null devices can
+ * be used just as any other devices, e.g. in devmap_device_unregister_core().
+ */
+static LIST_INITIALIZE(dummy_null_driver_devices);
 
 static devmap_handle_t devmap_create_handle(void)
@@ -953,7 +959,11 @@
 	device->name = dev_name;
 	
-	/* Insert device into list of all devices
-	   and into null devices array */
+	/*
+	 * Insert device into list of all devices and into null devices array.
+	 * Insert device into a dummy list of null driver's devices so that it
+	 * can be safely removed later.
+	 */
 	list_append(&device->devices, &devices_list);
+	list_append(&device->driver_devices, &dummy_null_driver_devices);
 	null_devices[i] = device;
 	
Index: pace/srv/hid/kbd/port/i8042.h
===================================================================
--- uspace/srv/hid/kbd/port/i8042.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 i8042 port driver.
- */
-
-#ifndef KBD_PORT_i8042_H_
-#define KBD_PORT_i8042_H_
-
-#include <libarch/ddi.h>
-#include <libarch/types.h>
-
-struct i8042 {
-	ioport8_t data;
-	uint8_t pad[3];
-	ioport8_t status;
-} __attribute__ ((packed));
-typedef struct i8042 i8042_t;
-
-#endif
-
-/**
- * @}
- */ 
Index: pace/srv/hw/netif/ne2000/dp8390_drv.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390_drv.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,84 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface driver interface.
- */
-
-#ifndef __NET_NETIF_DP8390_DRIVER_H__
-#define __NET_NETIF_DP8390_DRIVER_H__
-
-#include "dp8390.h"
-
-/** Initializes and/or starts the network interface.
- *  @param[in,out] dep The network interface structure.
- *  @param[in] mode The state mode.
- *  @returns EOK on success.
- *  @returns EXDEV if the network interface is disabled.
- */
-int do_init(dpeth_t *dep, int mode);
-
-/** Stops the network interface.
- *  @param[in,out] dep The network interface structure.
- */
-void do_stop(dpeth_t *dep);
-
-/** Processes the interrupt.
- *  @param[in,out] dep The network interface structure.
- *  @param[in] isr The interrupt status register.
- */
-void dp_check_ints(dpeth_t *dep, int isr);
-
-/** Probes and initializes the network interface.
- *  @param[in,out] dep The network interface structure.
- *  @returns EOK on success.
- *  @returns EXDEV if the network interface was not recognized.
- */
-int do_probe(dpeth_t * dep);
-
-/** Sends a packet.
- *  @param[in,out] dep The network interface structure.
- *  @param[in] packet The packet t be sent.
- *  @param[in] from_int The value indicating whether the sending is initialized from the interrupt handler.
- *  @returns 
- */
-int do_pwrite(dpeth_t * dep, packet_t *packet, int from_int);
-
-/** Prints out network interface information.
- *  @param[in] dep The network interface structure.
- */
-void dp8390_dump(dpeth_t * dep);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hw/netif/ne2000/dp8390_port.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390_port.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,274 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface types and structures ports.
- */
-
-#ifndef __NET_NETIF_DP8390_PORT_H__
-#define __NET_NETIF_DP8390_PORT_H__
-
-#include <errno.h>
-#include <mem.h>
-#include <stdio.h>
-#include <libarch/ddi.h>
-#include <sys/types.h>
-
-/** Macro for difining functions.
- *  @param[in] function The function type and name definition.
- *  @param[in] params The function parameters definition.
- */
-#define _PROTOTYPE(function, params) function params
-
-/** Success error code.
- */
-#define OK	EOK
-
-/** Type definition of the unsigned byte.
- */
-typedef uint8_t u8_t;
-
-/** Type definition of the unsigned short.
- */
-typedef uint16_t u16_t;
-
-/** Compares two memory blocks.
- *  @param[in] first The first memory block.
- *  @param[in] second The second memory block.
- *  @param[in] size The blocks size in bytes.
- *  @returns 0 if equeal.
- *  @returns -1 if the first is greater than the second.
- *  @returns 1 if the second is greater than the first.
- */
-#define memcmp(first, second, size)	bcmp((char *) (first), (char *) (second), (size))
-
-/** Reads 1 byte.
- *  @param[in] port The address to be read.
- *  @returns The read value.
- */
-#define inb(port)	pio_read_8((ioport8_t *) (port))
-
-/** Reads 1 word (2 bytes).
- *  @param[in] port The address to be read.
- *  @returns The read value.
- */
-#define inw(port)	pio_read_16((ioport16_t *) (port))
-
-/** Writes 1 byte.
- *  @param[in] port The address to be written.
- *  @param[in] value The value to be written.
- */
-#define outb(port, value)	pio_write_8((ioport8_t *) (port), (value))
-
-/** Writes 1 word (2 bytes).
- *  @param[in] port The address to be written.
- *  @param[in] value The value to be written.
- */
-#define outw(port, value)	pio_write_16((ioport16_t *) (port), (value))
-
-/** Prints out the driver critical error.
- *  Does not call the system panic().
- */
-#define panic(...)	printf("%s%s%d", __VA_ARGS__)
-
-/** Copies a memory block.
- *  @param proc The source process. Ignored parameter.
- *  @param src_s Ignored parameter.
- *  @param[in] src The source address.
- *  @param me The current proces. Ignored parameter.
- *  @param dst_s Ignored parameter.
- *  @param[in] dst The destination address.
- *  @param[in] bytes The block size in bytes.
- *  @returns EOK.
- */
-#define sys_vircopy(proc, src_s, src, me, dst_s, dst, bytes)	({memcpy((void *)(dst), (void *)(src), (bytes)); EOK;})
-
-/** Reads a memory block byte by byte.
- *  @param[in] port The address to be written.
- *  @param proc The source process. Ignored parameter.
- *  @param[in] dst The destination address.
- *  @param[in] bytes The block size in bytes.
- */
-#define do_vir_insb(port, proc, dst, bytes)	insb((port), (void *)(dst), (bytes))
-
-/** Reads a memory block word by word (2 bytes).
- *  @param[in] port The address to be written.
- *  @param proc The source process. Ignored parameter.
- *  @param[in] dst The destination address.
- *  @param[in] bytes The block size in bytes.
- */
-#define do_vir_insw(port, proc, dst, bytes)	insw((port), (void *)(dst), (bytes))
-
-/** Writes a memory block byte by byte.
- *  @param[in] port The address to be written.
- *  @param proc The source process. Ignored parameter.
- *  @param[in] src The source address.
- *  @param[in] bytes The block size in bytes.
- */
-#define do_vir_outsb(port, proc, src, bytes)	outsb((port), (void *)(src), (bytes))
-
-/** Writes a memory block word by word (2 bytes).
- *  @param[in] port The address to be written.
- *  @param proc The source process. Ignored parameter.
- *  @param[in] src The source address.
- *  @param[in] bytes The block size in bytes.
- */
-#define do_vir_outsw(port, proc, src, bytes)	outsw((port), (void *)(src), (bytes))
-
-/* com.h */
-/* Bits in 'DL_MODE' field of DL requests. */
-#  define DL_NOMODE		0x0
-#  define DL_PROMISC_REQ	0x2
-#  define DL_MULTI_REQ		0x4
-#  define DL_BROAD_REQ		0x8
-
-/* const.h */
-/** True value.
- */
-#define TRUE               1	/* used for turning integers into Booleans */
-
-/** False value.
- */
-#define FALSE              0	/* used for turning integers into Booleans */
-
-/** No number value.
- */
-#define NO_NUM        0x8000	/* used as numerical argument to panic() */
-
-/* devio.h */
-//typedef u16_t port_t;
-/** Type definition of a port.
- */
-typedef long port_t;
-
-/* dl_eth.h */
-/** Ethernet statistics.
- */
-typedef struct eth_stat
-{
-	/** Number of receive errors.
-	 */
-	unsigned long ets_recvErr;
-	/** Number of send error.
-	 */
-	unsigned long ets_sendErr;
-	/** Number of buffer overwrite warnings.
-	 */
-	unsigned long ets_OVW;
-	/** Number of crc errors of read.
-	 */
-	unsigned long ets_CRCerr;
-	/** Number of frames not alligned (number of bits % 8 != 0).
-	 */
-	unsigned long ets_frameAll;
-	/** Number of packets missed due to slow processing.
-	 */
-	unsigned long ets_missedP;
-	/** Number of packets received.
-	 */
-	unsigned long ets_packetR;
-	/** Number of packets transmitted.
-	 */
-	unsigned long ets_packetT;
-	/** Number of transmission defered (Tx was busy).
-	 */
-	unsigned long ets_transDef;
-	/** Number of collissions.
-	 */
-	unsigned long ets_collision;
-	/** Number of Tx aborted due to excess collisions.
-	 */
-	unsigned long ets_transAb;
-	/** Number of carrier sense lost.
-	 */
-	unsigned long ets_carrSense;
-	/** Number of FIFO underruns (processor too busy).
-	 */
-	unsigned long ets_fifoUnder;
-	/** Number of FIFO overruns (processor too busy).
-	 */
-	unsigned long ets_fifoOver;
-	/** Number of times unable to transmit collision sig.
-	 */
-	unsigned long ets_CDheartbeat;
-	/** Number of times out of window collision.
-	 */
-	unsigned long ets_OWC;
-} eth_stat_t;
-
-/* errno.h */
-/** Generic error.
- */
-#define EGENERIC     EINVAL
-
-/* ether.h */
-/** Minimum Ethernet packet size in bytes.
- */
-#define ETH_MIN_PACK_SIZE		  60
-
-/** Maximum Ethernet packet size in bytes.
- */
-#define ETH_MAX_PACK_SIZE_TAGGED	1518
-
-/** Ethernet address type definition.
- */
-typedef struct ether_addr
-{
-	/** Address data.
-	 */
-	u8_t ea_addr[6];
-} ether_addr_t;
-
-/* type.h */
-/** Type definition of the physical addresses and lengths in bytes.
- */
-typedef unsigned long phys_bytes;
-
-/** Type definition of the virtual addresses and lengths in bytes.
- */
-typedef unsigned long vir_bytes;
-
-/** Type definition of the input/output vector.
- */
-typedef struct {
-	/** Address of an I/O buffer.
-	 */
-	vir_bytes iov_addr;
-	/** Sizeof an I/O buffer.
-	 */
-	vir_bytes iov_size;
-} iovec_t;
-
-#endif
-
-/** @}
- */
Index: pace/srv/hw/netif/ne2000/local.h
===================================================================
--- uspace/srv/hw/netif/ne2000/local.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,99 +1,0 @@
-/*
- * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
- * * Any deviations from these conditions require written permission from the copyright holder in advance
- *
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Changes:
- *  2009 ported to HelenOS, Lukas Mejdrech
- */
-
-/** @addtogroup dp8390
- *  @{
- */
-
-/** @file
- *  Network interface probe functions.
- */
-
-#ifndef __NET_NETIF_DP8390_CONFIG_H__
-#define __NET_NETIF_DP8390_CONFIG_H__
-
-#include "dp8390_port.h"
-
-/*
-local.h
-*/
-
-/** WDETH switch.
- */
-#define ENABLE_WDETH 0
-
-/** NE2000 switch.
- */
-#define ENABLE_NE2000 1
-
-/** 3C503 switch.
- */
-#define ENABLE_3C503 0
-
-/** PCI support switch.
- */
-#define ENABLE_PCI 0
-
-struct dpeth;
-
-/* 3c503.c */
-/* * Probes a 3C503 network interface.
- *  @param[in] dep The network interface structure.
- *  @returns 1 if the NE2000 network interface is present.
- *  @returns 0 otherwise.
- */
-//_PROTOTYPE(int el2_probe, (struct dpeth*dep)				);
-
-/* ne2000.c */
-/** Probes a NE2000 or NE1000 network interface.
- *  @param[in] dep The network interface structure.
- *  @returns 1 if the NE2000 network interface is present.
- *  @returns 0 otherwise.
- */
-int ne_probe(struct dpeth * dep);
-//_PROTOTYPE(int ne_probe, (struct dpeth *dep)				);
-//_PROTOTYPE(void ne_init, (struct dpeth *dep)				);
-
-/* rtl8029.c */
-/* * Probes a RTL8029 network interface.
- *  @param[in] dep The network interface structure.
- *  @returns 1 if the NE2000 network interface is present.
- *  @returns 0 otherwise.
- */
-//_PROTOTYPE(int rtl_probe, (struct dpeth *dep)				);
-
-/* wdeth.c */
-/* * Probes a WDETH network interface.
- *  @param[in] dep The network interface structure.
- *  @returns 1 if the NE2000 network interface is present.
- *  @returns 0 otherwise.
- */
-//_PROTOTYPE(int wdeth_probe, (struct dpeth*dep)				);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hw/netif/ne2000/ne2000.h
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.h	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ 	(revision )
@@ -1,111 +1,0 @@
-/*
- * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
- * * Any deviations from these conditions require written permission from the copyright holder in advance
- *
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Changes:
- *  2009 ported to HelenOS, Lukas Mejdrech
- */
-
-/*
-ne2000.h
-
-Created:	March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
-*/
-
-/** @addtogroup ne2k
- *  @{
- */
-
-/** @file
- *  NE1000 and NE2000 network interface definitions.
- */
-
-#ifndef __NET_NETIF_NE2000_H__
-#define __NET_NETIF_NE2000_H__
-
-#include <libarch/ddi.h>
-
-#include "dp8390_port.h"
-
-/** DP8390 register offset.
- */
-#define NE_DP8390	0x00
-
-/** Data register.
- */
-#define NE_DATA		0x10
-
-/** Reset register.
- */
-#define NE_RESET	0x1F
-
-/** NE1000 data start.
- */
-#define NE1000_START	0x2000
-
-/** NE1000 data size.
- */
-#define NE1000_SIZE	0x2000
-
-/** NE2000 data start.
- */
-#define NE2000_START	0x4000
-
-/** NE2000 data size.
- */
-#define NE2000_SIZE	0x4000
-
-/** Reads 1 byte register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inb_ne(dep, reg)	(inb(dep->de_base_port+reg))
-
-/** Writes 1 byte register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outb_ne(dep, reg, data)	(outb(dep->de_base_port+reg, data))
-
-/** Reads 1 word (2 bytes) register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inw_ne(dep, reg)	(inw(dep->de_base_port+reg))
-
-/** Writes 1 word (2 bytes) register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outw_ne(dep, reg, data)	(outw(dep->de_base_port+reg, data))
-
-#endif /* __NET_NETIF_NE2000_H__ */
-
-/*
- * $PchId: ne2000.h,v 1.4 2004/08/03 12:03:20 philip Exp $
- */
-
-/** @}
- */
Index: uspace/srv/loader/arch/abs32le/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/abs32le/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/loader/arch/abs32le/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -3,4 +3,5 @@
  * is the base address and the special interp section.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -54,8 +55,4 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	
-	_heap = .;
-	
 	/DISCARD/ : {
 		*(*);
Index: uspace/srv/loader/arch/amd64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/amd64/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/loader/arch/amd64/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -1,2 +1,7 @@
+/*
+ * The difference from _link.ld.in for regular statically-linked apps
+ * is the base address and the special interp section.
+ */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -6,4 +11,5 @@
 	text PT_LOAD FLAGS(5);
 	data PT_LOAD FLAGS(6);
+	debug PT_NOTE;
 }
 
@@ -11,7 +17,7 @@
 	.interp : {
 		*(.interp);
-	} : interp
-
-	/* . = 0x0000700000001000;*/
+	} :interp
+	
+	/* . = 0x0000700000001000; */
 	. = 0x70001000;
 	
@@ -19,4 +25,5 @@
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
@@ -27,4 +34,5 @@
 		*(.data);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -32,4 +40,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -37,16 +46,27 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(COMMON);
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x1000);
-	_heap = .;
+	
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); } :debug
+	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
+	.debug_aranges 0 : { *(.debug_aranges); } :debug
+	.debug_info 0 : { *(.debug_info); } :debug
+	.debug_line 0 : { *(.debug_line); } :debug
+	.debug_loc 0 : { *(.debug_loc); } :debug
+	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
+	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
+	.debug_ranges 0 : { *(.debug_ranges); } :debug
+	.debug_str 0 : { *(.debug_str); } :debug
+#endif
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/arch/arm32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/arm32/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/loader/arch/arm32/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -3,4 +3,5 @@
  * is the base address.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -16,13 +17,14 @@
 		*(.interp);
 	} : interp
-
+	
 	. = 0x70001000;
-
+	
 	.init ALIGN(0x1000): SUBALIGN(0x1000) {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
-        *(.rodata*);
+		*(.rodata*);
 	} :text
 	
@@ -32,4 +34,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -37,4 +40,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -42,18 +46,16 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
 		*(.scommon);
-        *(COMMON);
-        *(.bss);
+		*(COMMON);
+		*(.bss);
 	} :data
-	
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/arch/ia32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia32/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/loader/arch/ia32/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -3,4 +3,5 @@
  * is the base address and the special interp section.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -10,4 +11,5 @@
 	text PT_LOAD FILEHDR PHDRS FLAGS(5);
 	data PT_LOAD FLAGS(6);
+	debug PT_NOTE;
 }
 
@@ -52,7 +54,16 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	
-	_heap = .;
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); } :debug
+	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
+	.debug_aranges 0 : { *(.debug_aranges); } :debug
+	.debug_info 0 : { *(.debug_info); } :debug
+	.debug_line 0 : { *(.debug_line); } :debug
+	.debug_loc 0 : { *(.debug_loc); } :debug
+	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
+	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
+	.debug_ranges 0 : { *(.debug_ranges); } :debug
+	.debug_str 0 : { *(.debug_str); } :debug
+#endif
 	
 	/DISCARD/ : {
Index: uspace/srv/loader/arch/ia64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia64/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/loader/arch/ia64/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -12,22 +12,24 @@
 		*(.interp);
 	} :interp
-
+	
 	/* On Itanium code sections must be aligned to 16 bytes. */
 	. = ALIGN(0x800000000 + SIZEOF_HEADERS, 16);
-
+	
 	.init : {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		_gp = .;
 		*(.got*);
-	} :data	
+	} :data
+	
 	.data : {
 		*(.opd);
@@ -35,4 +37,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -40,4 +43,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -45,5 +49,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
@@ -52,10 +58,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
- 
+	
 	/DISCARD/ : {
 		*(*);
-        }
+	}
 }
Index: uspace/srv/loader/arch/mips32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/mips32/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/loader/arch/mips32/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -3,4 +3,5 @@
  * is the base address.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -16,5 +17,5 @@
 		*(.interp);
 	} :interp
-
+	
 	. = 0x70004000;
 	
@@ -22,19 +23,22 @@
 		*(.init);
 	} :text
+	
 	.text : {
-	        *(.text);
+		*(.text);
 		*(.rodata*);
 	} :text
-
+	
+	. = . + 0x4000;
+	
 	.data : {
 		*(.data);
 		*(.data.rel*);
 	} :data
-
+	
 	.got : {
 		_gp = .;
 		*(.got);
 	} :data
-
+	
 	.tdata : {
 		_tdata_start = .;
@@ -42,4 +46,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -47,18 +52,17 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-
+	
 	.sbss : {
 		*(.scommon);
 		*(.sbss);
-	}	
+	}
+	
 	.bss : {
 		*(.bss);
 		*(COMMON);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
-
+	
 	/DISCARD/ : {
 		*(*);
Index: uspace/srv/loader/arch/ppc32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ppc32/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/loader/arch/ppc32/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -3,4 +3,5 @@
  * is the base address.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -16,10 +17,11 @@
 		*(.interp);
 	} :interp
-
+	
 	. = 0x70001000;
-
+	
 	.init ALIGN(0x1000) : SUBALIGN(0x1000) {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
@@ -31,4 +33,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -36,4 +39,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -41,5 +45,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
@@ -47,11 +53,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/arch/sparc64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/sparc64/_link.ld.in	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/loader/arch/sparc64/_link.ld.in	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -12,25 +12,28 @@
 		*(.interp);
 	} :interp
-
+	
 	. = 0x70004000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		 _gp = .;
 		 *(.got*);
 	} :data
+	
 	.data : {
 		*(.data);
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -38,4 +41,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -43,5 +47,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
@@ -49,11 +55,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/elf_load.c
===================================================================
--- uspace/srv/loader/elf_load.c	(revision 5ca5eaa780223488e3f882cc226da0c2c5d9ced6)
+++ uspace/srv/loader/elf_load.c	(revision 05155a175fff63bbff7f621a99cceb6db7ed5976)
@@ -109,5 +109,5 @@
 	int fd;
 	int rc;
-
+	
 	fd = open(file_name, O_RDONLY);
 	if (fd < 0) {
@@ -300,4 +300,5 @@
 	case PT_NULL:
 	case PT_PHDR:
+	case PT_NOTE:
 		break;
 	case PT_LOAD:
@@ -310,5 +311,4 @@
 	case PT_DYNAMIC:
 	case PT_SHLIB:
-	case PT_NOTE:
 	case PT_LOPROC:
 	case PT_HIPROC:
@@ -344,5 +344,5 @@
 	seg_ptr = (void *) seg_addr;
 
-	DPRINTF("Load segment at addr %p, size 0x%x\n", seg_addr,
+	DPRINTF("Load segment at addr %p, size 0x%x\n", (void *) seg_addr,
 		entry->p_memsz);
 
@@ -372,6 +372,7 @@
 	mem_sz = entry->p_memsz + (entry->p_vaddr - base);
 
-	DPRINTF("Map to seg_addr=%p-%p.\n", seg_addr,
-	entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
+	DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
+	    (void *) (entry->p_vaddr + bias +
+	    ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
 
 	/*
@@ -386,6 +387,6 @@
 	}
 
-	DPRINTF("as_area_create(%p, 0x%x, %d) -> 0x%lx\n",
-		base + bias, mem_sz, flags, (uintptr_t)a);
+	DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
+	    (void *) (base + bias), mem_sz, flags, (void *) a);
 
 	/*
@@ -464,5 +465,5 @@
 		    (void *)((uint8_t *)entry->sh_addr + elf->bias);
 		DPRINTF("Dynamic section found at %p.\n",
-			(uintptr_t)elf->info->dynamic);
+		    (void *) elf->info->dynamic);
 		break;
 	default:
