Index: .bzrignore
===================================================================
--- .bzrignore	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ .bzrignore	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,265 @@
+*.disasm
+*.map
+*.prev
+Makefile.depend
+Makefile.common
+Makefile.config
+autotool/
+common.h
+config.h
+hdisk.img
+image.iso
+boot/distroot/
+boot/initrd.img
+kernel/kernel.bin
+kernel/kernel.dump
+kernel/kernel.raw
+kernel/arch/amd64/_link.ld
+kernel/arch/amd64/include/arch/common.h
+kernel/generic/src/debug/real_map.bin
+uspace/app/bdsh/bdsh
+uspace/app/bithenge/bithenge
+uspace/app/blkdump/blkdump
+uspace/app/bnchmark/bnchmark
+uspace/app/date/date
+uspace/app/devctl/devctl
+uspace/app/dnscfg/dnscfg
+uspace/app/dnsres/dnsres
+uspace/app/edit/edit
+uspace/app/getterm/getterm
+uspace/app/inet/inet
+uspace/app/init/init
+uspace/app/kill/kill
+uspace/app/killall/killall
+uspace/app/klog/klog
+uspace/app/loc/loc
+uspace/app/logset/logset
+uspace/app/mixerctl/mixerctl
+uspace/app/mkbd/mkbd
+uspace/app/mkexfat/mkexfat
+uspace/app/mkfat/mkfat
+uspace/app/mkmfs/mkmfs
+uspace/app/netecho/netecho
+uspace/app/nettest1/nettest1
+uspace/app/nettest2/nettest2
+uspace/app/nettest3/nettest3
+uspace/app/nterm/nterm
+uspace/app/ping/ping
+uspace/app/ping6/ping6
+uspace/app/redir/redir
+uspace/app/sbi/sbi
+uspace/app/sportdmp/sportdmp
+uspace/app/stats/stats
+uspace/app/sysinfo/sysinfo
+uspace/app/taskdump/taskdump
+uspace/app/tester/tester
+uspace/app/testread/testread
+uspace/app/testwrit/testwrit
+uspace/app/tetris/tetris
+uspace/app/top/top
+uspace/app/trace/trace
+uspace/app/usbinfo/usbinfo
+uspace/app/vdemo/vdemo
+uspace/app/vlaunch/images.c
+uspace/app/vlaunch/images.h
+uspace/app/vlaunch/vlaunch
+uspace/app/vterm/vterm
+uspace/app/vuhid/vuh
+uspace/app/wavplay/wavplay
+uspace/app/websrv/websrv
+uspace/dist/app/bdsh
+uspace/dist/app/bithenge
+uspace/dist/app/blkdump
+uspace/dist/app/bnchmark
+uspace/dist/app/date
+uspace/dist/app/devctl
+uspace/dist/app/dnscfg
+uspace/dist/app/dnsres
+uspace/dist/app/edit
+uspace/dist/app/getterm
+uspace/dist/app/inet
+uspace/dist/app/kill
+uspace/dist/app/killall
+uspace/dist/app/klog
+uspace/dist/app/loc
+uspace/dist/app/logset
+uspace/dist/app/mixerctl
+uspace/dist/app/mkbd
+uspace/dist/app/mkexfat
+uspace/dist/app/mkfat
+uspace/dist/app/mkmfs
+uspace/dist/app/netecho
+uspace/dist/app/nettest1
+uspace/dist/app/nettest2
+uspace/dist/app/nettest3
+uspace/dist/app/nterm
+uspace/dist/app/ping
+uspace/dist/app/ping6
+uspace/dist/app/redir
+uspace/dist/app/sbi
+uspace/dist/app/sportdmp
+uspace/dist/app/stats
+uspace/dist/app/sysinfo
+uspace/dist/app/taskdump
+uspace/dist/app/tester
+uspace/dist/app/testread
+uspace/dist/app/testwrit
+uspace/dist/app/tetris
+uspace/dist/app/top
+uspace/dist/app/trace
+uspace/dist/app/usbinfo
+uspace/dist/app/vdemo
+uspace/dist/app/vlaunch
+uspace/dist/app/vterm
+uspace/dist/app/vuh
+uspace/dist/app/wavplay
+uspace/dist/app/websrv
+uspace/dist/drv/ahci/
+uspace/dist/drv/ata_bd/
+uspace/dist/drv/cmos-rtc/
+uspace/dist/drv/e1k/
+uspace/dist/drv/ehci/
+uspace/dist/drv/i8042/
+uspace/dist/drv/isa/
+uspace/dist/drv/kfb/
+uspace/dist/drv/ne2k/
+uspace/dist/drv/ns8250/
+uspace/dist/drv/ohci/
+uspace/dist/drv/pciintel/
+uspace/dist/drv/ps2mouse/
+uspace/dist/drv/root/
+uspace/dist/drv/rootpc/
+uspace/dist/drv/rootvirt/
+uspace/dist/drv/rtl8139/
+uspace/dist/drv/sb16/
+uspace/dist/drv/test1/
+uspace/dist/drv/test2/
+uspace/dist/drv/test3/
+uspace/dist/drv/uhci/
+uspace/dist/drv/uhcirh/
+uspace/dist/drv/usbflbk/
+uspace/dist/drv/usbhid/
+uspace/dist/drv/usbhub/
+uspace/dist/drv/usbmast/
+uspace/dist/drv/usbmid/
+uspace/dist/drv/vhc/
+uspace/dist/drv/xtkbd/
+uspace/dist/srv/apic
+uspace/dist/srv/cdfs
+uspace/dist/srv/clipboard
+uspace/dist/srv/compositor
+uspace/dist/srv/console
+uspace/dist/srv/devman
+uspace/dist/srv/dnsrsrv
+uspace/dist/srv/ethip
+uspace/dist/srv/exfat
+uspace/dist/srv/ext4fs
+uspace/dist/srv/fat
+uspace/dist/srv/file_bd
+uspace/dist/srv/g_part
+uspace/dist/srv/hound
+uspace/dist/srv/i8259
+uspace/dist/srv/inetsrv
+uspace/dist/srv/input
+uspace/dist/srv/isdv4_tablet
+uspace/dist/srv/locfs
+uspace/dist/srv/loopip
+uspace/dist/srv/mbr_part
+uspace/dist/srv/mfs
+uspace/dist/srv/output
+uspace/dist/srv/remcons
+uspace/dist/srv/sata_bd
+uspace/dist/srv/slip
+uspace/dist/srv/taskmon
+uspace/dist/srv/tcp
+uspace/dist/srv/tmpfs
+uspace/dist/srv/udf
+uspace/dist/srv/udp
+uspace/drv/audio/sb16/sb16
+uspace/drv/block/ahci/ahci
+uspace/drv/block/ata_bd/ata_bd
+uspace/drv/bus/isa/isa
+uspace/drv/bus/pci/pciintel/pciintel
+uspace/drv/bus/usb/ehci/ehci
+uspace/drv/bus/usb/ohci/ohci
+uspace/drv/bus/usb/uhci/uhci
+uspace/drv/bus/usb/uhcirh/uhcirh
+uspace/drv/bus/usb/usbflbk/usbflbk
+uspace/drv/bus/usb/usbhid/usbhid
+uspace/drv/bus/usb/usbhub/usbhub
+uspace/drv/bus/usb/usbmast/usbmast
+uspace/drv/bus/usb/usbmid/usbmid
+uspace/drv/bus/usb/vhc/vhc
+uspace/drv/char/i8042/i8042
+uspace/drv/char/ns8250/ns8250
+uspace/drv/char/ps2mouse/ps2mouse
+uspace/drv/char/xtkbd/xtkbd
+uspace/drv/fb/kfb/kfb
+uspace/drv/infrastructure/root/root
+uspace/drv/infrastructure/rootpc/rootpc
+uspace/drv/infrastructure/rootvirt/rootvirt
+uspace/drv/nic/e1k/e1k
+uspace/drv/nic/ne2k/ne2k
+uspace/drv/nic/rtl8139/rtl8139
+uspace/drv/test/test1/test1
+uspace/drv/test/test2/test2
+uspace/drv/test/test3/test3
+uspace/drv/time/cmos-rtc/cmos-rtc
+uspace/lib/c/arch/amd64/_link-dlexe.ld
+uspace/lib/c/arch/amd64/_link-loader.ld
+uspace/lib/c/arch/amd64/_link-shlib.ld
+uspace/lib/c/arch/amd64/_link.ld
+uspace/lib/c/arch/amd64/include/libarch/common.h
+uspace/lib/posix/collisions.list
+uspace/lib/posix/redefs-hide-libc.xargs
+uspace/lib/posix/redefs-show-posix.xargs
+uspace/lib/posix/include/libc
+uspace/srv/audio/hound/hound
+uspace/srv/bd/file_bd/file_bd
+uspace/srv/bd/part/guid_part/g_part
+uspace/srv/bd/part/mbr_part/mbr_part
+uspace/srv/bd/rd/rd
+uspace/srv/bd/sata_bd/sata_bd
+uspace/srv/clipboard/clipboard
+uspace/srv/devman/devman
+uspace/srv/fs/cdfs/cdfs
+uspace/srv/fs/exfat/exfat
+uspace/srv/fs/ext4fs/ext4fs
+uspace/srv/fs/fat/fat
+uspace/srv/fs/locfs/locfs
+uspace/srv/fs/mfs/mfs
+uspace/srv/fs/tmpfs/tmpfs
+uspace/srv/fs/udf/udf
+uspace/srv/hid/compositor/compositor
+uspace/srv/hid/compositor/images.c
+uspace/srv/hid/compositor/images.h
+uspace/srv/hid/console/console
+uspace/srv/hid/input/input
+uspace/srv/hid/isdv4_tablet/isdv4_tablet
+uspace/srv/hid/output/output
+uspace/srv/hid/remcons/remcons
+uspace/srv/hid/s3c24xx_ts/s3c24xx_ts
+uspace/srv/hw/char/s3c24xx_uart/s3c24ser
+uspace/srv/hw/irc/apic/apic
+uspace/srv/hw/irc/i8259/i8259
+uspace/srv/loader/loader
+uspace/srv/locsrv/locsrv
+uspace/srv/logger/logger
+uspace/srv/net/dnsrsrv/dnsrsrv
+uspace/srv/net/ethip/ethip
+uspace/srv/net/inetsrv/inetsrv
+uspace/srv/net/loopip/loopip
+uspace/srv/net/slip/slip
+uspace/srv/net/tcp/tcp
+uspace/srv/net/udp/udp
+uspace/srv/ns/ns
+uspace/srv/taskmon/taskmon
+uspace/srv/vfs/vfs
+kernel/arch/ia32/_link.ld
+uspace/lib/c/arch/ia32/_link-dlexe.ld
+uspace/lib/c/arch/ia32/_link-loader.ld
+uspace/lib/c/arch/ia32/_link-shlib.ld
+uspace/lib/c/arch/ia32/_link.ld
+kernel/arch/arm32/_link.ld
+uspace/app/corecfg/corecfg
+uspace/dist/app/corecfg
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ boot/Makefile.common	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -165,4 +165,5 @@
 	$(USPACE_PATH)/app/blkdump/blkdump \
 	$(USPACE_PATH)/app/bnchmark/bnchmark \
+	$(USPACE_PATH)/app/corecfg/corecfg \
 	$(USPACE_PATH)/app/devctl/devctl \
 	$(USPACE_PATH)/app/dltest/dltest \
Index: boot/arch/arm32/Makefile.inc
===================================================================
--- boot/arch/arm32/Makefile.inc	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ boot/arch/arm32/Makefile.inc	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -57,5 +57,5 @@
 endif
 
-RD_DRVS += \
+RD_DRVS_ESSENTIAL += \
 	infrastructure/rootamdm37x \
 	fb/amdm37x_dispc \
Index: boot/arch/mips32/Makefile.inc
===================================================================
--- boot/arch/mips32/Makefile.inc	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ boot/arch/mips32/Makefile.inc	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -50,4 +50,17 @@
 endif
 
+ifeq ($(MACHINE), $(filter $(MACHINE),bmalta lmalta))
+	RD_DRVS_ESSENTIAL += \
+		infrastructure/rootmalta \
+		block/ata_bd \
+		bus/pci/pciintel \
+		bus/isa \
+		char/i8042 \
+		char/ps2mouse \
+		char/xtkbd
+
+	RD_DRV_CFG += \
+		bus/isa
+endif
 
 SOURCES = \
Index: boot/arch/ppc32/Makefile.inc
===================================================================
--- boot/arch/ppc32/Makefile.inc	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ boot/arch/ppc32/Makefile.inc	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -42,5 +42,5 @@
 	$(USPACE_PATH)/srv/hw/bus/cuda_adb/cuda_adb
 
-RD_DRVS += \
+RD_DRVS_ESSENTIAL += \
 	infrastructure/rootmac \
 	bus/pci/pciintel \
Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/Makefile	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -220,5 +220,4 @@
 	generic/src/mm/km.c \
 	generic/src/mm/reserve.c \
-	generic/src/mm/buddy.c \
 	generic/src/mm/frame.c \
 	generic/src/mm/page.c \
Index: kernel/arch/abs32le/include/arch/mm/page.h
===================================================================
--- kernel/arch/abs32le/include/arch/mm/page.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/abs32le/include/arch/mm/page.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -57,8 +57,8 @@
 
 /* Page table sizes for each level. */
-#define PTL0_SIZE_ARCH  ONE_FRAME
-#define PTL1_SIZE_ARCH  0
-#define PTL2_SIZE_ARCH  0
-#define PTL3_SIZE_ARCH  ONE_FRAME
+#define PTL0_FRAMES_ARCH  1
+#define PTL1_FRAMES_ARCH  1
+#define PTL2_FRAMES_ARCH  1
+#define PTL3_FRAMES_ARCH  1
 
 /* Macros calculating indices for each level. */
Index: kernel/arch/amd64/include/arch/mm/page.h
===================================================================
--- kernel/arch/amd64/include/arch/mm/page.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/amd64/include/arch/mm/page.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -61,8 +61,8 @@
 
 /* Page table sizes for each level. */
-#define PTL0_SIZE_ARCH  ONE_FRAME
-#define PTL1_SIZE_ARCH  ONE_FRAME
-#define PTL2_SIZE_ARCH  ONE_FRAME
-#define PTL3_SIZE_ARCH  ONE_FRAME
+#define PTL0_FRAMES_ARCH  1
+#define PTL1_FRAMES_ARCH  1
+#define PTL2_FRAMES_ARCH  1
+#define PTL3_FRAMES_ARCH  1
 
 /* Macros calculating indices into page tables in each level. */
Index: kernel/arch/amd64/src/ddi/ddi.c
===================================================================
--- kernel/arch/amd64/src/ddi/ddi.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/amd64/src/ddi/ddi.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -42,4 +42,5 @@
 #include <errno.h>
 #include <arch/cpu.h>
+#include <cpu.h>
 #include <arch.h>
 #include <align.h>
@@ -58,27 +59,28 @@
 int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
 {
-	size_t bits = ioaddr + size;
-	if (bits > IO_PORTS)
+	size_t elements = ioaddr + size;
+	if (elements > IO_PORTS)
 		return ENOENT;
 	
-	if (task->arch.iomap.bits < bits) {
+	if (task->arch.iomap.elements < elements) {
 		/*
 		 * The I/O permission bitmap is too small and needs to be grown.
 		 */
 		
-		uint8_t *newmap = (uint8_t *) malloc(BITS2BYTES(bits), FRAME_ATOMIC);
-		if (!newmap)
+		void *store = malloc(bitmap_size(elements, 0), FRAME_ATOMIC);
+		if (!store)
 			return ENOMEM;
 		
 		bitmap_t oldiomap;
-		bitmap_initialize(&oldiomap, task->arch.iomap.map,
+		bitmap_initialize(&oldiomap, task->arch.iomap.elements, 0,
 		    task->arch.iomap.bits);
-		bitmap_initialize(&task->arch.iomap, newmap, bits);
+		
+		bitmap_initialize(&task->arch.iomap, elements, 0, store);
 		
 		/*
 		 * Mark the new range inaccessible.
 		 */
-		bitmap_set_range(&task->arch.iomap, oldiomap.bits,
-		    bits - oldiomap.bits);
+		bitmap_set_range(&task->arch.iomap, oldiomap.elements,
+		    elements - oldiomap.elements);
 		
 		/*
@@ -88,6 +90,7 @@
 		if (oldiomap.bits) {
 			bitmap_copy(&task->arch.iomap, &oldiomap,
-			    oldiomap.bits);
-			free(oldiomap.map);
+			    oldiomap.elements);
+			
+			free(oldiomap.bits);
 		}
 	}
@@ -96,5 +99,5 @@
 	 * Enable the range and we are done.
 	 */
-	bitmap_clear_range(&task->arch.iomap, (size_t) ioaddr, (size_t) size);
+	bitmap_clear_range(&task->arch.iomap, (size_t) ioaddr, size);
 	
 	/*
@@ -118,13 +121,15 @@
 	/* First, copy the I/O Permission Bitmap. */
 	irq_spinlock_lock(&TASK->lock, false);
+	
 	size_t ver = TASK->arch.iomapver;
-	size_t bits = TASK->arch.iomap.bits;
-	if (bits) {
-		ASSERT(TASK->arch.iomap.map);
+	size_t elements = TASK->arch.iomap.elements;
+	
+	if (elements > 0) {
+		ASSERT(TASK->arch.iomap.bits);
 		
 		bitmap_t iomap;
-		bitmap_initialize(&iomap, CPU->arch.tss->iomap,
-		    TSS_IOMAP_SIZE * 8);
-		bitmap_copy(&iomap, &TASK->arch.iomap, bits);
+		bitmap_initialize(&iomap, TSS_IOMAP_SIZE * 8, 0,
+		    CPU->arch.tss->iomap);
+		bitmap_copy(&iomap, &TASK->arch.iomap, elements);
 		
 		/*
@@ -132,16 +137,19 @@
 		 * I/O access.
 		 */
-		bitmap_set_range(&iomap, bits, ALIGN_UP(bits, 8) - bits);
+		bitmap_set_range(&iomap, elements,
+		    ALIGN_UP(elements, 8) - elements);
+		
 		/*
 		 * It is safe to set the trailing eight bits because of the
 		 * extra convenience byte in TSS_IOMAP_SIZE.
 		 */
-		bitmap_set_range(&iomap, ALIGN_UP(bits, 8), 8);
+		bitmap_set_range(&iomap, ALIGN_UP(elements, 8), 8);
 	}
+	
 	irq_spinlock_unlock(&TASK->lock, false);
 	
 	/*
 	 * Second, adjust TSS segment limit.
-	 * Take the extra ending byte will all bits set into account. 
+	 * Take the extra ending byte with all bits set into account.
 	 */
 	ptr_16_64_t cpugdtr;
@@ -149,5 +157,6 @@
 	
 	descriptor_t *gdt_p = (descriptor_t *) cpugdtr.base;
-	gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits));
+	size_t size = bitmap_size(elements, 0);
+	gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + size);
 	gdtr_load(&cpugdtr);
 	
Index: kernel/arch/amd64/src/proc/task.c
===================================================================
--- kernel/arch/amd64/src/proc/task.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/amd64/src/proc/task.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -34,6 +34,7 @@
 
 #include <proc/task.h>
+#include <typedefs.h>
+#include <adt/bitmap.h>
 #include <mm/slab.h>
-#include <typedefs.h>
 
 /** Perform amd64 specific task initialization.
@@ -45,5 +46,5 @@
 {
 	task->arch.iomapver = 0;
-	bitmap_initialize(&task->arch.iomap, NULL, 0);
+	bitmap_initialize(&task->arch.iomap, 0, 0, NULL);
 }
 
@@ -55,6 +56,6 @@
 void task_destroy_arch(task_t *task)
 {
-	if (task->arch.iomap.map)
-		free(task->arch.iomap.map);
+	if (task->arch.iomap.bits != NULL)
+		free(task->arch.iomap.bits);
 }
 
Index: kernel/arch/arm32/include/arch/mm/page.h
===================================================================
--- kernel/arch/arm32/include/arch/mm/page.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/arm32/include/arch/mm/page.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -73,8 +73,8 @@
 
 /* Page table sizes for each level. */
-#define PTL0_SIZE_ARCH          FOUR_FRAMES
-#define PTL1_SIZE_ARCH          0
-#define PTL2_SIZE_ARCH          0
-#define PTL3_SIZE_ARCH          ONE_FRAME
+#define PTL0_FRAMES_ARCH  4
+#define PTL1_FRAMES_ARCH  1
+#define PTL2_FRAMES_ARCH  1
+#define PTL3_FRAMES_ARCH  1
 
 /* Macros calculating indices into page tables for each level. */
Index: kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c
===================================================================
--- kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -60,5 +60,5 @@
 
 static struct beagleboard {
-	amdm37x_irc_regs_t *irc_addr;
+	omap_irc_regs_t *irc_addr;
 	omap_uart_t uart;
 	amdm37x_gpt_t timer;
@@ -103,5 +103,5 @@
 	    PAGE_NOT_CACHEABLE);
 	ASSERT(beagleboard.irc_addr);
-	amdm37x_irc_init(beagleboard.irc_addr);
+	omap_irc_init(beagleboard.irc_addr);
 
 	/* Initialize timer. Use timer1, because it is in WKUP power domain
@@ -123,5 +123,5 @@
 
 	/* Enable timer interrupt */
-	amdm37x_irc_enable(beagleboard.irc_addr, AMDM37x_GPT1_IRQ);
+	omap_irc_enable(beagleboard.irc_addr, AMDM37x_GPT1_IRQ);
 
 	/* Start timer here */
@@ -147,5 +147,5 @@
 static void bbxm_irq_exception(unsigned int exc_no, istate_t *istate)
 {
-	const unsigned inum = amdm37x_irc_inum_get(beagleboard.irc_addr);
+	const unsigned inum = omap_irc_inum_get(beagleboard.irc_addr);
 
 	irq_t *irq = irq_dispatch_and_lock(inum);
@@ -161,5 +161,5 @@
 	/** amdm37x manual ch. 12.5.2 (p. 2428) places irc ack at the end
 	 * of ISR. DO this to avoid strange behavior. */
-	amdm37x_irc_irq_ack(beagleboard.irc_addr);
+	omap_irc_irq_ack(beagleboard.irc_addr);
 }
 
@@ -188,5 +188,5 @@
 		indev_t *srln = srln_wire(srln_instance, sink);
 		omap_uart_input_wire(&beagleboard.uart, srln);
-		amdm37x_irc_enable(beagleboard.irc_addr, AMDM37x_UART3_IRQ);
+		omap_irc_enable(beagleboard.irc_addr, AMDM37x_UART3_IRQ);
 	}
 #endif
Index: kernel/arch/arm32/src/mach/beaglebone/beaglebone.c
===================================================================
--- kernel/arch/arm32/src/mach/beaglebone/beaglebone.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/arm32/src/mach/beaglebone/beaglebone.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -63,5 +63,5 @@
 
 static struct beaglebone {
-	am335x_irc_regs_t *irc_addr;
+	omap_irc_regs_t *irc_addr;
 	am335x_cm_per_regs_t *cm_per_addr;
 	am335x_cm_dpll_regs_t *cm_dpll_addr;
@@ -104,5 +104,5 @@
 
 	/* Initialize the interrupt controller */
-	am335x_irc_init(bbone.irc_addr);
+	omap_irc_init(bbone.irc_addr);
 }
 
@@ -153,5 +153,5 @@
 	}
 	/* Enable the interrupt */
-	am335x_irc_enable(bbone.irc_addr, AM335x_DMTIMER2_IRQ);
+	omap_irc_enable(bbone.irc_addr, AM335x_DMTIMER2_IRQ);
 	/* Start the timer */
 	am335x_timer_start(&bbone.timer);
@@ -176,5 +176,5 @@
 static void bbone_irq_exception(unsigned int exc_no, istate_t *istate)
 {
-	const unsigned inum = am335x_irc_inum_get(bbone.irc_addr);
+	const unsigned inum = omap_irc_inum_get(bbone.irc_addr);
 
 	irq_t *irq = irq_dispatch_and_lock(inum);
@@ -187,5 +187,5 @@
 	}
 
-	am335x_irc_irq_ack(bbone.irc_addr);
+	omap_irc_irq_ack(bbone.irc_addr);
 }
 
@@ -214,5 +214,5 @@
 		indev_t *srln = srln_wire(srln_instance, sink);
 		omap_uart_input_wire(&bbone.uart, srln);
-		am335x_irc_enable(bbone.irc_addr, AM335x_UART0_IRQ);
+		omap_irc_enable(bbone.irc_addr, AM335x_UART0_IRQ);
 	}
 #endif
Index: kernel/arch/arm32/src/mm/frame.c
===================================================================
--- kernel/arch/arm32/src/mm/frame.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/arm32/src/mm/frame.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -88,7 +88,6 @@
 void boot_page_table_free(void)
 {
-	unsigned int i;
-	for (i = 0; i < BOOT_PAGE_TABLE_SIZE_IN_FRAMES; i++)
-		frame_free(i * FRAME_SIZE + BOOT_PAGE_TABLE_ADDRESS);
+	frame_free(BOOT_PAGE_TABLE_ADDRESS,
+	    BOOT_PAGE_TABLE_SIZE_IN_FRAMES);
 }
 
Index: kernel/arch/arm32/src/mm/page.c
===================================================================
--- kernel/arch/arm32/src/mm/page.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/arm32/src/mm/page.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -69,5 +69,5 @@
 #ifdef HIGH_EXCEPTION_VECTORS
 	/* Create mapping for exception table at high offset */
-	uintptr_t ev_frame = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_NONE);
+	uintptr_t ev_frame = frame_alloc(1, FRAME_NONE, 0);
 	page_mapping_insert(AS_KERNEL, EXC_BASE_ADDRESS, ev_frame, flags);
 #else
Index: kernel/arch/arm32/src/ras.c
===================================================================
--- kernel/arch/arm32/src/ras.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/arm32/src/ras.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -51,13 +51,12 @@
 void ras_init(void)
 {
-	uintptr_t frame;
-
-	frame = (uintptr_t) frame_alloc(ONE_FRAME,
-	    FRAME_ATOMIC | FRAME_HIGHMEM);
+	uintptr_t frame =
+	    frame_alloc(1, FRAME_ATOMIC | FRAME_HIGHMEM, 0);
 	if (!frame)
-		frame = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_LOWMEM);
+		frame = frame_alloc(1, FRAME_LOWMEM, 0);
+	
 	ras_page = (uintptr_t *) km_map(frame,
 	    PAGE_SIZE, PAGE_READ | PAGE_WRITE | PAGE_USER | PAGE_CACHEABLE);
-
+	
 	memsetb(ras_page, PAGE_SIZE, 0); 
 	ras_page[RAS_START] = 0;
Index: kernel/arch/ia32/include/arch/mm/page.h
===================================================================
--- kernel/arch/ia32/include/arch/mm/page.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/ia32/include/arch/mm/page.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -66,8 +66,8 @@
 
 /* Page table sizes for each level. */
-#define PTL0_SIZE_ARCH  ONE_FRAME
-#define PTL1_SIZE_ARCH  0
-#define PTL2_SIZE_ARCH  0
-#define PTL3_SIZE_ARCH  ONE_FRAME
+#define PTL0_FRAMES_ARCH  1
+#define PTL1_FRAMES_ARCH  1
+#define PTL2_FRAMES_ARCH  1
+#define PTL3_FRAMES_ARCH  1
 
 /* Macros calculating indices for each level. */
Index: kernel/arch/ia32/src/ddi/ddi.c
===================================================================
--- kernel/arch/ia32/src/ddi/ddi.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/ia32/src/ddi/ddi.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -59,27 +59,28 @@
 int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
 {
-	size_t bits = ioaddr + size;
-	if (bits > IO_PORTS)
+	size_t elements = ioaddr + size;
+	if (elements > IO_PORTS)
 		return ENOENT;
 	
-	if (task->arch.iomap.bits < bits) {
+	if (task->arch.iomap.elements < elements) {
 		/*
 		 * The I/O permission bitmap is too small and needs to be grown.
 		 */
 		
-		uint8_t *newmap = (uint8_t *) malloc(BITS2BYTES(bits), FRAME_ATOMIC);
-		if (!newmap)
+		void *store = malloc(bitmap_size(elements, 0), FRAME_ATOMIC);
+		if (!store)
 			return ENOMEM;
 		
 		bitmap_t oldiomap;
-		bitmap_initialize(&oldiomap, task->arch.iomap.map,
+		bitmap_initialize(&oldiomap, task->arch.iomap.elements, 0,
 		    task->arch.iomap.bits);
-		bitmap_initialize(&task->arch.iomap, newmap, bits);
+		
+		bitmap_initialize(&task->arch.iomap, elements, 0, store);
 		
 		/*
 		 * Mark the new range inaccessible.
 		 */
-		bitmap_set_range(&task->arch.iomap, oldiomap.bits,
-		    bits - oldiomap.bits);
+		bitmap_set_range(&task->arch.iomap, oldiomap.elements,
+		    elements - oldiomap.elements);
 		
 		/*
@@ -89,6 +90,7 @@
 		if (oldiomap.bits) {
 			bitmap_copy(&task->arch.iomap, &oldiomap,
-			    oldiomap.bits);
-			free(oldiomap.map);
+			    oldiomap.elements);
+			
+			free(oldiomap.bits);
 		}
 	}
@@ -97,5 +99,5 @@
 	 * Enable the range and we are done.
 	 */
-	bitmap_clear_range(&task->arch.iomap, (size_t) ioaddr, (size_t) size);
+	bitmap_clear_range(&task->arch.iomap, (size_t) ioaddr, size);
 	
 	/*
@@ -119,13 +121,15 @@
 	/* First, copy the I/O Permission Bitmap. */
 	irq_spinlock_lock(&TASK->lock, false);
+	
 	size_t ver = TASK->arch.iomapver;
-	size_t bits = TASK->arch.iomap.bits;
-	if (bits) {
-		ASSERT(TASK->arch.iomap.map);
+	size_t elements = TASK->arch.iomap.elements;
+	
+	if (elements > 0) {
+		ASSERT(TASK->arch.iomap.bits);
 		
 		bitmap_t iomap;
-		bitmap_initialize(&iomap, CPU->arch.tss->iomap,
-		    TSS_IOMAP_SIZE * 8);
-		bitmap_copy(&iomap, &TASK->arch.iomap, bits);
+		bitmap_initialize(&iomap, TSS_IOMAP_SIZE * 8, 0,
+		    CPU->arch.tss->iomap);
+		bitmap_copy(&iomap, &TASK->arch.iomap, elements);
 		
 		/*
@@ -133,11 +137,14 @@
 		 * I/O access.
 		 */
-		bitmap_set_range(&iomap, bits, ALIGN_UP(bits, 8) - bits);
+		bitmap_set_range(&iomap, elements,
+		    ALIGN_UP(elements, 8) - elements);
+		
 		/*
 		 * It is safe to set the trailing eight bits because of the
 		 * extra convenience byte in TSS_IOMAP_SIZE.
 		 */
-		bitmap_set_range(&iomap, ALIGN_UP(bits, 8), 8);
+		bitmap_set_range(&iomap, ALIGN_UP(elements, 8), 8);
 	}
+	
 	irq_spinlock_unlock(&TASK->lock, false);
 	
@@ -150,5 +157,6 @@
 	
 	descriptor_t *gdt_p = (descriptor_t *) cpugdtr.base;
-	gdt_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits));
+	size_t size = bitmap_size(elements, 0);
+	gdt_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + size);
 	gdtr_load(&cpugdtr);
 	
Index: kernel/arch/ia32/src/mm/frame.c
===================================================================
--- kernel/arch/ia32/src/mm/frame.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/ia32/src/mm/frame.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -47,5 +47,4 @@
 
 #define PHYSMEM_LIMIT32  UINT64_C(0x100000000)
-#define PHYSMEM_LIMIT_DMA   UINT64_C(0x1000000)
 
 size_t hardcoded_unmapped_ktext_size = 0;
@@ -92,26 +91,11 @@
 				else
 					conf = minconf;
-
-				if ((pfn * PAGE_SIZE) < PHYSMEM_LIMIT_DMA) {
-					size_t dma_count = min(
-					    PHYSMEM_LIMIT_DMA / PAGE_SIZE - pfn,
-					    count);
-					zone_create(pfn, dma_count, conf,
-					    ZONE_AVAILABLE | ZONE_DMA);
-					count -= dma_count;
-					pfn += dma_count;
-				}
-
-				conf = pfn;
-				if (count) {
-					zone_create(pfn, count, conf,
-					    ZONE_AVAILABLE | ZONE_LOWMEM);
-				}
+				zone_create(pfn, count, conf,
+				    ZONE_AVAILABLE | ZONE_LOWMEM);
 			} else {
 				conf = zone_external_conf_alloc(count);
-				if (conf != 0) {
+				if (conf != 0)
 					zone_create(pfn, count, conf,
 					    ZONE_AVAILABLE | ZONE_HIGHMEM);
-				}
 			}
 		} else if ((e820table[i].type == MEMMAP_MEMORY_ACPI) ||
Index: kernel/arch/ia32/src/proc/task.c
===================================================================
--- kernel/arch/ia32/src/proc/task.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/ia32/src/proc/task.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -40,20 +40,22 @@
 /** Perform ia32 specific task initialization.
  *
- * @param t Task to be initialized.
+ * @param task Task to be initialized.
+ *
  */
-void task_create_arch(task_t *t)
+void task_create_arch(task_t *task)
 {
-	t->arch.iomapver = 0;
-	bitmap_initialize(&t->arch.iomap, NULL, 0);
+	task->arch.iomapver = 0;
+	bitmap_initialize(&task->arch.iomap, 0, 0, NULL);
 }
 
 /** Perform ia32 specific task destruction.
  *
- * @param t Task to be initialized.
+ * @param task Task to be initialized.
+ *
  */
-void task_destroy_arch(task_t *t)
+void task_destroy_arch(task_t *task)
 {
-	if (t->arch.iomap.map)
-		free(t->arch.iomap.map);
+	if (task->arch.iomap.bits != NULL)
+		free(task->arch.iomap.bits);
 }
 
Index: kernel/arch/ia64/src/ddi/ddi.c
===================================================================
--- kernel/arch/ia64/src/ddi/ddi.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/ia64/src/ddi/ddi.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -56,11 +56,13 @@
 {
 	if (!task->arch.iomap) {
-		uint8_t *map;
-
 		task->arch.iomap = malloc(sizeof(bitmap_t), 0);
-		map = malloc(BITS2BYTES(IO_MEMMAP_PAGES), 0);
-		if(!map)
+		if (task->arch.iomap == NULL)
 			return ENOMEM;
-		bitmap_initialize(task->arch.iomap, map, IO_MEMMAP_PAGES);
+		
+		void *store = malloc(bitmap_size(IO_MEMMAP_PAGES, 0), 0);
+		if (store == NULL)
+			return ENOMEM;
+		
+		bitmap_initialize(task->arch.iomap, IO_MEMMAP_PAGES, 0, store);
 		bitmap_clear_range(task->arch.iomap, 0, IO_MEMMAP_PAGES);
 	}
@@ -69,5 +71,5 @@
 	size = ALIGN_UP(size + ioaddr - 4 * iopage, PORTS_PER_PAGE);
 	bitmap_set_range(task->arch.iomap, iopage, size / 4);
-
+	
 	return 0;
 }
Index: kernel/arch/ia64/src/mm/vhpt.c
===================================================================
--- kernel/arch/ia64/src/mm/vhpt.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/ia64/src/mm/vhpt.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -42,8 +42,10 @@
 uintptr_t vhpt_set_up(void)
 {
-	vhpt_base = frame_alloc(VHPT_WIDTH - FRAME_WIDTH,
-	    FRAME_KA | FRAME_ATOMIC);
-	if (!vhpt_base)
+	uintptr_t vhpt_frame =
+	    frame_alloc(SIZE2FRAMES(VHPT_SIZE), FRAME_ATOMIC, 0);
+	if (!vhpt_frame)
 		panic("Kernel configured with VHPT but no memory for table.");
+	
+	vhpt_base = (vhpt_entry_t *) PA2KA(vhpt_frame);
 	vhpt_invalidate_all();
 	return (uintptr_t) vhpt_base;
@@ -82,5 +84,5 @@
 void vhpt_invalidate_all()
 {
-	memsetb(vhpt_base, 1 << VHPT_WIDTH, 0);
+	memsetb(vhpt_base, VHPT_SIZE, 0);
 }
 
Index: kernel/arch/mips32/include/arch/mm/page.h
===================================================================
--- kernel/arch/mips32/include/arch/mm/page.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/mips32/include/arch/mm/page.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup mips32mm	
+/** @addtogroup mips32mm
  * @{
  */
@@ -70,27 +70,27 @@
  * - PTL3 has 4096 entries (12 bits)
  */
- 
+
 /* Macros describing number of entries in each level. */
-#define PTL0_ENTRIES_ARCH	64
-#define PTL1_ENTRIES_ARCH	0
-#define PTL2_ENTRIES_ARCH	0
-#define PTL3_ENTRIES_ARCH	4096
+#define PTL0_ENTRIES_ARCH  64
+#define PTL1_ENTRIES_ARCH  0
+#define PTL2_ENTRIES_ARCH  0
+#define PTL3_ENTRIES_ARCH  4096
 
 /* Macros describing size of page tables in each level. */
-#define PTL0_SIZE_ARCH		ONE_FRAME
-#define PTL1_SIZE_ARCH		0
-#define PTL2_SIZE_ARCH		0
-#define PTL3_SIZE_ARCH		ONE_FRAME
+#define PTL0_FRAMES_ARCH  1
+#define PTL1_FRAMES_ARCH  1
+#define PTL2_FRAMES_ARCH  1
+#define PTL3_FRAMES_ARCH  1
 
 /* Macros calculating entry indices for each level. */
-#define PTL0_INDEX_ARCH(vaddr)	((vaddr) >> 26) 
-#define PTL1_INDEX_ARCH(vaddr)	0
-#define PTL2_INDEX_ARCH(vaddr)	0
-#define PTL3_INDEX_ARCH(vaddr)	(((vaddr) >> 14) & 0xfff)
+#define PTL0_INDEX_ARCH(vaddr)  ((vaddr) >> 26)
+#define PTL1_INDEX_ARCH(vaddr)  0
+#define PTL2_INDEX_ARCH(vaddr)  0
+#define PTL3_INDEX_ARCH(vaddr)  (((vaddr) >> 14) & 0xfff)
 
 /* Set accessor for PTL0 address. */
 #define SET_PTL0_ADDRESS_ARCH(ptl0)
 
-/* Get PTE address accessors for each level. */ 
+/* Get PTE address accessors for each level. */
 #define GET_PTL1_ADDRESS_ARCH(ptl0, i) \
 	(((pte_t *) (ptl0))[(i)].pfn << 12)
@@ -196,5 +196,4 @@
 	p->p = 1;
 }
-	
 
 extern void page_arch_init(void);
Index: kernel/arch/mips32/src/mm/tlb.c
===================================================================
--- kernel/arch/mips32/src/mm/tlb.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/mips32/src/mm/tlb.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -48,14 +48,16 @@
 #include <symtab.h>
 
-#define PFN_SHIFT	12
-#define VPN_SHIFT	12
-#define ADDR2VPN(a)	((a) >> VPN_SHIFT)
-#define ADDR2VPN2(a)	(ADDR2VPN((a)) >> 1)
-#define VPN2ADDR(vpn)	((vpn) << VPN_SHIFT)
-#define VPN22ADDR(vpn2)	(VPN2ADDR(vpn2) << 1)
-#define PFN2ADDR(pfn)	((pfn) << PFN_SHIFT)
-
-#define BANK_SELECT_BIT(a)	(((a) >> PAGE_WIDTH) & 1) 
-	
+#define PFN_SHIFT  12
+#define VPN_SHIFT  12
+
+#define ADDR2HI_VPN(a)   ((a) >> VPN_SHIFT)
+#define ADDR2HI_VPN2(a)  (ADDR2HI_VPN((a)) >> 1)
+
+#define HI_VPN2ADDR(vpn)    ((vpn) << VPN_SHIFT)
+#define HI_VPN22ADDR(vpn2)  (HI_VPN2ADDR(vpn2) << 1)
+
+#define LO_PFN2ADDR(pfn)  ((pfn) << PFN_SHIFT)
+
+#define BANK_SELECT_BIT(a)  (((a) >> PAGE_WIDTH) & 1)
 
 /** Initialize TLB.
@@ -266,5 +268,5 @@
 {
 	hi->value = 0;
-	hi->vpn2 = ADDR2VPN2(ALIGN_DOWN(addr, PAGE_SIZE));
+	hi->vpn2 = ADDR2HI_VPN2(ALIGN_DOWN(addr, PAGE_SIZE));
 	hi->asid = asid;
 }
@@ -295,8 +297,8 @@
 		
 		printf("%-4u %-6u %0#10x %-#6x  %1u%1u%1u%1u  %0#10x\n",
-		    i, hi.asid, VPN22ADDR(hi.vpn2), mask.mask,
-		    lo0.g, lo0.v, lo0.d, lo0.c, PFN2ADDR(lo0.pfn));
+		    i, hi.asid, HI_VPN22ADDR(hi.vpn2), mask.mask,
+		    lo0.g, lo0.v, lo0.d, lo0.c, LO_PFN2ADDR(lo0.pfn));
 		printf("                               %1u%1u%1u%1u  %0#10x\n",
-		    lo1.g, lo1.v, lo1.d, lo1.c, PFN2ADDR(lo1.pfn));
+		    lo1.g, lo1.v, lo1.d, lo1.c, LO_PFN2ADDR(lo1.pfn));
 	}
 	
Index: kernel/arch/ppc32/include/arch/mm/page.h
===================================================================
--- kernel/arch/ppc32/include/arch/mm/page.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/ppc32/include/arch/mm/page.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -70,8 +70,8 @@
 
 /* Page table sizes for each level. */
-#define PTL0_SIZE_ARCH  ONE_FRAME
-#define PTL1_SIZE_ARCH  0
-#define PTL2_SIZE_ARCH  0
-#define PTL3_SIZE_ARCH  ONE_FRAME
+#define PTL0_FRAMES_ARCH  1
+#define PTL1_FRAMES_ARCH  1
+#define PTL2_FRAMES_ARCH  1
+#define PTL3_FRAMES_ARCH  1
 
 /* Macros calculating indices into page tables on each level. */
Index: kernel/arch/sparc64/src/mm/sun4u/as.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4u/as.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/sparc64/src/mm/sun4u/as.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -63,40 +63,30 @@
 {
 #ifdef CONFIG_TSB
-	/*
-	 * The order must be calculated with respect to the emulated
-	 * 16K page size.
-	 *
-	 */
-	uint8_t order = fnzb32(((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
-	    sizeof(tsb_entry_t)) >> FRAME_WIDTH);
-	
-	uintptr_t tsb = (uintptr_t) frame_alloc(order, flags | FRAME_KA);
-	
-	if (!tsb)
+	uintptr_t tsb_phys =
+	    frame_alloc(SIZE2FRAMES((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
+	    sizeof(tsb_entry_t)), flags, 0);
+	if (!tsb_phys)
 		return -1;
 	
-	as->arch.itsb = (tsb_entry_t *) tsb;
-	as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT *
+	tsb_entry_t *tsb = (tsb_entry_t *) PA2KA(tsb_phys);
+	
+	as->arch.itsb = tsb;
+	as->arch.dtsb = tsb + ITSB_ENTRY_COUNT;
+	
+	memsetb(as->arch.itsb, (ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
+	    sizeof(tsb_entry_t), 0);
+#endif
+	
+	return 0;
+}
+
+int as_destructor_arch(as_t *as)
+{
+#ifdef CONFIG_TSB
+	size_t frames = SIZE2FRAMES((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
 	    sizeof(tsb_entry_t));
-	
-	memsetb(as->arch.itsb,
-	    (ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0);
-#endif
-	
-	return 0;
-}
-
-int as_destructor_arch(as_t *as)
-{
-#ifdef CONFIG_TSB
-	/*
-	 * The count must be calculated with respect to the emualted 16K page
-	 * size.
-	 */
-	size_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
-	    sizeof(tsb_entry_t)) >> FRAME_WIDTH;
-	frame_free(KA2PA((uintptr_t) as->arch.itsb));
-	
-	return cnt;
+	frame_free(KA2PA((uintptr_t) as->arch.itsb), frames);
+	
+	return frames;
 #else
 	return 0;
Index: kernel/arch/sparc64/src/mm/sun4v/as.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4v/as.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/arch/sparc64/src/mm/sun4v/as.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -66,9 +66,7 @@
 {
 #ifdef CONFIG_TSB
-	uint8_t order = fnzb32(
-		(TSB_ENTRY_COUNT * sizeof(tsb_entry_t)) >> FRAME_WIDTH);
-	
-	uintptr_t tsb = (uintptr_t) frame_alloc(order, flags);
-	
+	uintptr_t tsb =
+	    frame_alloc(SIZE2FRAMES(TSB_ENTRY_COUNT * sizeof(tsb_entry_t)),
+	    flags, 0);
 	if (!tsb)
 		return -1;
@@ -92,8 +90,8 @@
 {
 #ifdef CONFIG_TSB
-	size_t cnt = (TSB_ENTRY_COUNT * sizeof(tsb_entry_t)) >> FRAME_WIDTH;
-	frame_free((uintptr_t) as->arch.tsb_description.tsb_base);
+	size_t frames = SIZE2FRAMES(TSB_ENTRY_COUNT * sizeof(tsb_entry_t));
+	frame_free(as->arch.tsb_description.tsb_base, frames);
 	
-	return cnt;
+	return frames;
 #else
 	return 0;
Index: kernel/doc/mm
===================================================================
--- kernel/doc/mm	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/doc/mm	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -71,5 +71,5 @@
 
 'malloc' function accepts flags as a second argument. The flags are directly
-passed to the underlying frame_alloc function. 
+passed to the underlying frame_alloc function.
 
 1) If the flags parameter contains FRAME_ATOMIC, the allocator will not sleep.
Index: kernel/genarch/include/genarch/drivers/am335x/irc.h
===================================================================
--- kernel/genarch/include/genarch/drivers/am335x/irc.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/genarch/include/genarch/drivers/am335x/irc.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -38,214 +38,14 @@
 #define KERN_AM335x_IRQC_H_
 
-#define AM335x_IRC_BASE_ADDRESS 0x48200000
-#define AM335x_IRC_SIZE         4096
+#define AM335x_IRC_BASE_ADDRESS     0x48200000
+#define AM335x_IRC_SIZE             4096
 
-#define AM335x_IRC_IRQ_COUNT    128
+#define AM335x_IRC_IRQ_COUNT        128
+#define AM335x_IRC_IRQ_GROUPS_COUNT 4
 
-#include <typedefs.h>
+#define OMAP_IRC_IRQ_COUNT        AM335x_IRC_IRQ_COUNT
+#define OMAP_IRC_IRQ_GROUPS_COUNT AM335x_IRC_IRQ_GROUPS_COUNT
 
-typedef struct {
-	const ioport32_t revision;
-#define AM335x_IRC_REV_MASK 0xFF
-
-	const uint8_t padd0[12];
-
-	/* This register controls the various parameters
-	 * of the OCP interface.
-	 */
-	ioport32_t sysconfig;
-#define AM335x_IRC_SYSCONFIG_AUTOIDLE_FLAG   (1 << 0)
-#define AM335x_IRC_SYSCONFIG_SOFTRESET_FLAG  (1 << 1)
-
-	/* This register provides status information about the module */
-	const ioport32_t sysstatus;
-#define AM335x_IRC_SYSSTATUS_RESET_DONE_FLAG (1 << 0)
-
-	const uint8_t padd1[40];
-
-	/* This register supplies the currently active IRQ interrupt number */
-	ioport32_t sir_irq;
-#define AM335x_IRC_SIR_IRQ_ACTIVEIRQ_MASK       0x7F
-#define AM335x_IRC_SIR_IRQ_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
-
-	/* This register supplies the currently active FIQ interrupt number */
-	const ioport32_t sir_fiq;
-#define AM335x_IRC_FIQ_IRQ_ACTIVEFIQ_MASK       0x7F
-#define AM335x_IRC_FIQ_IRQ_SPURIOUSFIQFLAG_MASK 0xFFFFFFF8
-
-	/* This register contains the new interrupt agreement bits */
-	ioport32_t control;
-#define AM335x_IRC_CONTROL_NEWIRQAGR_FLAG       (1 << 0)
-#define AM335x_IRC_CONTROL_NEWFIQAGR_FLAG       (1 << 1)
-
-	/* This register controls protection of the other registers.
-	 * This register can only be accessed in priviledged mode, regardless
-	 * of the current value of the protection bit.
-	 */
-	ioport32_t protection;
-#define AM335x_IRC_PROTECTION_FLAG              (1 << 0)
-
-	/* This register controls the clock auto-idle for the functional
-	 * clock and the input synchronizers.
-	 */
-	ioport32_t idle;
-#define AM335x_IRC_IDLE_FUNCIDLE_FLAG           (1 << 0)
-#define AM335x_IRC_IDLE_TURBO_FLAG              (1 << 1)
-
-	const uint8_t padd2[12];
-
-	/* This register supplies the currently active IRQ priority level */
-	const ioport32_t irq_priority;
-#define AM335x_IRC_IRQ_PRIORITY_IRQPRIORITY_MASK     0x7F
-#define AM335x_IRC_IRQ_PRIORITY_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
-
-	/* This register supplies the currently active FIQ priority level */
-	const ioport32_t fiq_priority;
-#define AM335x_IRC_FIQ_PRIORITY_FIQPRIORITY_MASK     0x7F
-#define AM335x_IRC_FIQ_PRIORITY_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
-
-	/* This register sets the priority threshold */
-	ioport32_t threshold;
-#define AM335x_IRC_THRESHOLD_PRIORITYTHRESHOLD_MASK     0xFF
-#define AM335x_IRC_THRESHOLD_PRIORITYTHRESHOLD_ENABLED  0x00
-#define AM335x_IRC_THRESHOLD_PRIORITYTHRESHOLD_DISABLED 0xFF
-
-	const uint8_t padd[20];
-
-	struct {
-		/* Raw interrupt input status before masking */
-		const ioport32_t itr;
-
-		/* Interrupt mask */
-		ioport32_t mir;
-
-		/* This register is used to clear the interrupt mask bits,
-		 * Write 1 clears the mask bit to 0.
-		 */
-		ioport32_t mir_clear;
-
-		/* This register is used to set the interrupt mask bits,
-		 * Write 1 sets the mask bit to 1.
-		 */
-		ioport32_t mir_set;
-
-		/* This register is used to set the software interrupt bits,
-		 * it is also used to read the current active software
-		 * interrupts.
-		 * Write 1 sets the software interrups bits to 1.
-		 */
-		ioport32_t isr_set;
-
-		/* This register is used to clear the software interrups bits.
-		 * Write 1 clears the software interrupt bits to 0.
-		 */
-		ioport32_t isr_clear;
-
-		/* This register contains the IRQ status after masking. */
-		const ioport32_t pending_irq;
-
-		/* This register contains the FIQ status after masking. */
-		const ioport32_t pending_fiq;
-	} interrupts[4];
-
-	/* These registers contain the priority for the interrups and
-	 * the FIQ/IRQ steering.
-	 */
-	ioport32_t ilr[AM335x_IRC_IRQ_COUNT];
-/* 0 = Interrupt routed to IRQ, 1 = interrupt routed to FIQ */
-#define AM335x_IRC_ILR_FIQNIRQ_FLAG    (1 << 0)
-#define AM335x_IRC_ILR_PRIORITY_MASK   0x3F
-#define AM335x_IRC_ILR_PRIORITY_SHIFT  2
-
-} am335x_irc_regs_t;
-
-static inline void am335x_irc_init(am335x_irc_regs_t *regs)
-{
-	int i;
-
-	/* Initialization sequence */
-
-	/* 1 - Program the SYSCONFIG register: if necessary, enable the
-	 *     autogating by setting the AUTOIDLE bit.
-	 */
-	regs->sysconfig &= ~AM335x_IRC_SYSCONFIG_AUTOIDLE_FLAG;
-
-	/* 2 - Program the IDLE register: if necessary, disable functional
-	 *     clock autogating or enable synchronizer autogating by setting
-	 *     the FUNCIDLE bit or the TURBO bit accordingly.
-	 */
-	regs->idle &= ~AM335x_IRC_IDLE_FUNCIDLE_FLAG;
-	regs->idle &= ~AM335x_IRC_IDLE_TURBO_FLAG;
-
-	/* 3 - Program ILRm register for each interrupt line: Assign a
-	 *     priority level and set the FIQNIRQ bit for an FIQ interrupt
-	 *     (by default, interrupts are mapped to IRQ and
-	 *     priority is 0 (highest).
-	 */
-
-	for (i = 0; i < AM335x_IRC_IRQ_COUNT; ++i)
-		regs->ilr[i] = 0;
-
-	/* 4 - Program the MIRn register: Enable interrupts (by default,
-	 *     all interrupt lines are masked).
-	 */
-	for (i = 0; i < 4; ++i)
-		regs->interrupts[i].mir_set = 0xFFFFFFFF;
-}
-
-/** Get the currently active IRQ interrupt number
- *
- * @param regs     Pointer to the irc memory mapped registers
- *
- * @return         The active IRQ interrupt number
- */
-static inline unsigned am335x_irc_inum_get(am335x_irc_regs_t *regs)
-{
-	return regs->sir_irq & AM335x_IRC_SIR_IRQ_ACTIVEIRQ_MASK;
-}
-
-/** Reset IRQ output and enable new IRQ generation
- *
- * @param regs    Pointer to the irc memory mapped registers
- */
-static inline void am335x_irc_irq_ack(am335x_irc_regs_t *regs)
-{
-	regs->control = AM335x_IRC_CONTROL_NEWIRQAGR_FLAG;
-}
-
-/** Reset FIQ output and enable new FIQ generation
- *
- * @param regs    Pointer to the irc memory mapped registers
- */
-static inline void am335x_irc_fiq_ack(am335x_irc_regs_t *regs)
-{
-	regs->control = AM335x_IRC_CONTROL_NEWFIQAGR_FLAG;
-}
-
-/** Clear an interrupt mask bit
- *
- * @param regs    Pointer to the irc memory mapped registers
- * @param inum    The interrupt to be enabled
- */
-static inline void am335x_irc_enable(am335x_irc_regs_t *regs, unsigned inum)
-{
-	ASSERT(inum < AM335x_IRC_IRQ_COUNT);
-	const unsigned set = inum / 32;
-	const unsigned pos = inum % 32;
-	regs->interrupts[set].mir_clear = (1 << pos);
-}
-
-/** Set an interrupt mask bit
- *
- * @param regs    Pointer to the irc memory mapped registers
- * @param inum    The interrupt to be disabled
- */
-static inline void am335x_irc_disable(am335x_irc_regs_t *regs, unsigned inum)
-{
-	ASSERT(inum < AM335x_IRC_IRQ_COUNT);
-	const unsigned set = inum / 32;
-	const unsigned pos = inum % 32;
-	regs->interrupts[set].mir_set = (1 << pos);
-}
+#include <genarch/drivers/omap/irc.h>
 
 #endif
Index: kernel/genarch/include/genarch/drivers/amdm37x/irc.h
===================================================================
--- kernel/genarch/include/genarch/drivers/amdm37x/irc.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/genarch/include/genarch/drivers/amdm37x/irc.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -38,165 +38,14 @@
 
 /* AMDM37x TRM p. 1079 */
-#define AMDM37x_IRC_BASE_ADDRESS 0x48200000
-#define AMDM37x_IRC_SIZE 4096
+#define AMDM37x_IRC_BASE_ADDRESS     0x48200000
+#define AMDM37x_IRC_SIZE             4096
 
-#define AMDM37x_IRC_IRQ_COUNT 96
+#define AMDM37x_IRC_IRQ_COUNT        96
+#define AMDM37x_IRC_IRQ_GROUPS_COUNT 3
 
-#include <typedefs.h>
+#define OMAP_IRC_IRQ_COUNT        AMDM37x_IRC_IRQ_COUNT
+#define OMAP_IRC_IRQ_GROUPS_COUNT AMDM37x_IRC_IRQ_GROUPS_COUNT
 
-typedef struct {
-	const ioport32_t revision; /**< Revision */
-#define AMDM37x_IRC_REV_MASK (0xff)
-
-	uint8_t padd0_[12];
-
-	ioport32_t sysconfig; /**< SYS config */
-#define AMDM37x_IRC_SYSCONFIG_AUTOIDLE_FLAG (1 << 0)
-#define AMDM37x_IRC_SYSCONFIG_SOFTRESET_FLAG (1 << 1)
-
-	const ioport32_t sysstatus; /**< SYS status */
-#define AMDM37x_IRC_SYSSTATUS_RESET_DONE_FLAG (1 << 0)
-
-	uint8_t padd1_[40];
-
-	const ioport32_t sir_irq;   /**< Currently active irq number */
-#define AMDM37x_IRC_SIR_IRQ_ACTIVEIRQ_MASK (0x7f)
-#define AMDM37x_IRC_SIR_IRQ_SPURIOUSIRQFLAG_MASK (0xfffffff8)
-
-	const ioport32_t sir_fiq;
-#define AMDM37x_IRC_SIR_FIQ_ACTIVEIRQ_MASK (0x7f)
-#define AMDM37x_IRC_SIR_FIQ_SPURIOUSIRQFLAG_MASK (0xfffffff8)
-
-	ioport32_t control;   /**< New interrupt agreement. */
-#define AMDM37x_IRC_CONTROL_NEWIRQAGR_FLAG (1 << 0)
-#define AMDM37x_IRC_CONTROL_NEWFIQAGR_FLAG (1 << 1)
-
-	ioport32_t protection;  /**< Protect other registers. */
-#define AMDM37x_IRC_PROTECTION_PROETCTION_FLAG (1 << 0)
-
-	ioport32_t idle;   /**< Idle and autogating */
-#define AMDM37x_IRC_IDLE_FUNCIDLE_FLAG (1 << 0)
-#define AMDM37x_IRC_IDLE_TURBO_FLAG (1 << 1)
-
-	uint8_t padd2_[12];
-
-	ioport32_t irq_priority; /**< Active IRQ priority */
-#define AMDM37x_IRC_IRQ_PRIORITY_IRQPRIORITY_MASK (0x7f)
-#define AMDM37x_IRC_IRQ_PRIORITY_SPURIOUSIRQFLAG_MASK (0xfffffff8)
-
-	ioport32_t fiq_priority; /**< Active FIQ priority */
-#define AMDM37x_IRC_FIQ_PRIORITY_FIQPRIORITY_MASK (0x7f)
-#define AMDM37x_IRC_FIQ_PRIORITY_SPURIOUSFIQFLAG_MASK (0xfffffff8)
-
-	ioport32_t threshold; /**< Priority threshold */
-#define AMDM37x_IRC_THRESHOLD_PRIORITYTHRESHOLD_MASK (0xff)
-#define AMDM37x_IRC_THRESHOLD_PRIORITYTHRESHOLD_ENABLED (0x00)
-#define AMDM37x_IRC_THRESHOLD_PRIORITYTHRESHOLD_DISABLED (0xff)
-
-	uint8_t padd3__[20];
-
-	struct {
-		const ioport32_t itr;   /**< Interrupt input status before masking */
-		ioport32_t mir;   /**< Interrupt mask */
-		ioport32_t mir_clear; /**< Clear mir mask bits */
-		ioport32_t mir_set;   /**< Set mir mask bits */
-		ioport32_t isr_set;   /**< Set software interrupt bits */
-		ioport32_t isr_clear; /**< Clear software interrupt bits */
-		const ioport32_t pending_irq; /**< IRQ status after masking */
-		const ioport32_t pending_fiq; /**< FIQ status after masking */
-	} interrupts[3];
-
-	uint8_t padd4_[32];
-
-	ioport32_t ilr[96];   /**< FIQ/IRQ steering */
-#define AMDM37x_IRC_ILR_FIQNIRQ (1 << 0)
-#define AMDM37x_IRC_ILR_PRIORITY_MASK (0x3f)
-#define AMDM37x_IRC_ILR_PRIORITY_SHIFT (2)
-
-} amdm37x_irc_regs_t;
-
-static inline void amdm37x_irc_dump(amdm37x_irc_regs_t *regs)
-{
-#define DUMP_REG(name) \
-	printf("%s %p(%x).\n", #name, &regs->name, regs->name);
-
-	DUMP_REG(revision);
-	DUMP_REG(sysconfig);
-	DUMP_REG(sysstatus);
-	DUMP_REG(sir_irq);
-	DUMP_REG(sir_fiq);
-	DUMP_REG(control);
-	DUMP_REG(protection);
-	DUMP_REG(idle);
-	DUMP_REG(irq_priority);
-	DUMP_REG(fiq_priority);
-	DUMP_REG(threshold);
-
-	for (int i = 0; i < 3; ++i) {
-		DUMP_REG(interrupts[i].itr);
-		DUMP_REG(interrupts[i].mir);
-		DUMP_REG(interrupts[i].isr_set);
-		DUMP_REG(interrupts[i].pending_irq);
-		DUMP_REG(interrupts[i].pending_fiq);
-	}
-	for (int i = 0; i < AMDM37x_IRC_IRQ_COUNT; ++i) {
-		DUMP_REG(ilr[i]);
-	}
-
-#undef DUMP_REG
-}
-
-static inline void amdm37x_irc_init(amdm37x_irc_regs_t *regs)
-{
-	/* AMDM37x TRM sec 12.5.1 p. 2425 */
-	/* Program system config register */
-	//TODO enable this when you know the meaning
-	//regs->sysconfig |= AMDM37x_IRC_SYSCONFIG_AUTOIDLE_FLAG;
-
-	/* Program idle register */
-	//TODO enable this when you know the meaning
-	//regs->sysconfig |= AMDM37x_IRC_IDLE_TURBO_FLAG;
-
-	/* Program ilr[m] assign priority, decide fiq */
-	for (unsigned i = 0; i < AMDM37x_IRC_IRQ_COUNT; ++i) {
-		regs->ilr[i] = 0; /* highest prio(default) route to irq */
-	}
-
-	/* Disable all interrupts */
-	regs->interrupts[0].mir_set = 0xffffffff;
-	regs->interrupts[1].mir_set = 0xffffffff;
-	regs->interrupts[2].mir_set = 0xffffffff;
-}
-
-static inline unsigned amdm37x_irc_inum_get(amdm37x_irc_regs_t *regs)
-{
-	return regs->sir_irq & AMDM37x_IRC_SIR_IRQ_ACTIVEIRQ_MASK;
-}
-
-static inline void amdm37x_irc_irq_ack(amdm37x_irc_regs_t *regs)
-{
-	regs->control = AMDM37x_IRC_CONTROL_NEWIRQAGR_FLAG;
-}
-
-static inline void amdm37x_irc_fiq_ack(amdm37x_irc_regs_t *regs)
-{
-	regs->control = AMDM37x_IRC_CONTROL_NEWFIQAGR_FLAG;
-}
-
-static inline void amdm37x_irc_enable(amdm37x_irc_regs_t *regs, unsigned inum)
-{
-	ASSERT(inum < AMDM37x_IRC_IRQ_COUNT);
-	const unsigned set = inum / 32;
-	const unsigned pos = inum % 32;
-	regs->interrupts[set].mir_clear = (1 << pos);
-}
-
-static inline void amdm37x_irc_disable(amdm37x_irc_regs_t *regs, unsigned inum)
-{
-	ASSERT(inum < AMDM37x_IRC_IRQ_COUNT);
-	const unsigned set = inum / 32;
-	const unsigned pos = inum % 32;
-	regs->interrupts[set].mir_set = (1 << pos);
-}
+#include <genarch/drivers/omap/irc.h>
 
 #endif
Index: kernel/genarch/include/genarch/drivers/omap/irc.h
===================================================================
--- kernel/genarch/include/genarch/drivers/omap/irc.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ kernel/genarch/include/genarch/drivers/omap/irc.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ *
+ * 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 genarch
+ * @{
+ */
+
+/**
+ * @file
+ * @brief Texas Instruments OMAP on-chip interrupt controller driver.
+ */
+
+#ifndef KERN_OMAP_IRQC_H_
+#define KERN_OMAP_IRQC_H_
+
+#include <typedefs.h>
+
+#define OMAP_IRC_IRQ_GROUPS_PAD (4 - OMAP_IRC_IRQ_GROUPS_COUNT)
+
+typedef struct {
+	const ioport32_t revision;
+#define OMAP_IRC_REV_MASK 0xFF
+
+	const uint8_t padd0[12];
+
+	/* This register controls the various parameters
+	 * of the OCP interface.
+	 */
+	ioport32_t sysconfig;
+#define OMAP_IRC_SYSCONFIG_AUTOIDLE_FLAG   (1 << 0)
+#define OMAP_IRC_SYSCONFIG_SOFTRESET_FLAG  (1 << 1)
+
+	/* This register provides status information about the module */
+	const ioport32_t sysstatus;
+#define OMAP_IRC_SYSSTATUS_RESET_DONE_FLAG (1 << 0)
+
+	const uint8_t padd1[40];
+
+	/* This register supplies the currently active IRQ interrupt number */
+	ioport32_t sir_irq;
+#define OMAP_IRC_SIR_IRQ_ACTIVEIRQ_MASK       0x7F
+#define OMAP_IRC_SIR_IRQ_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
+
+	/* This register supplies the currently active FIQ interrupt number */
+	const ioport32_t sir_fiq;
+#define OMAP_IRC_FIQ_IRQ_ACTIVEFIQ_MASK       0x7F
+#define OMAP_IRC_FIQ_IRQ_SPURIOUSFIQFLAG_MASK 0xFFFFFFF8
+
+	/* This register contains the new interrupt agreement bits */
+	ioport32_t control;
+#define OMAP_IRC_CONTROL_NEWIRQAGR_FLAG       (1 << 0)
+#define OMAP_IRC_CONTROL_NEWFIQAGR_FLAG       (1 << 1)
+
+	/* This register controls protection of the other registers.
+	 * This register can only be accessed in priviledged mode, regardless
+	 * of the current value of the protection bit.
+	 */
+	ioport32_t protection;
+#define OMAP_IRC_PROTECTION_FLAG              (1 << 0)
+
+	/* This register controls the clock auto-idle for the functional
+	 * clock and the input synchronizers.
+	 */
+	ioport32_t idle;
+#define OMAP_IRC_IDLE_FUNCIDLE_FLAG           (1 << 0)
+#define OMAP_IRC_IDLE_TURBO_FLAG              (1 << 1)
+
+	const uint8_t padd2[12];
+
+	/* This register supplies the currently active IRQ priority level */
+	const ioport32_t irq_priority;
+#define OMAP_IRC_IRQ_PRIORITY_IRQPRIORITY_MASK     0x7F
+#define OMAP_IRC_IRQ_PRIORITY_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
+
+	/* This register supplies the currently active FIQ priority level */
+	const ioport32_t fiq_priority;
+#define OMAP_IRC_FIQ_PRIORITY_FIQPRIORITY_MASK     0x7F
+#define OMAP_IRC_FIQ_PRIORITY_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
+
+	/* This register sets the priority threshold */
+	ioport32_t threshold;
+#define OMAP_IRC_THRESHOLD_PRIORITYTHRESHOLD_MASK     0xFF
+#define OMAP_IRC_THRESHOLD_PRIORITYTHRESHOLD_ENABLED  0x00
+#define OMAP_IRC_THRESHOLD_PRIORITYTHRESHOLD_DISABLED 0xFF
+
+	const uint8_t padd3[20];
+
+	struct {
+		/* Raw interrupt input status before masking */
+		const ioport32_t itr;
+
+		/* Interrupt mask */
+		ioport32_t mir;
+
+		/* This register is used to clear the interrupt mask bits,
+		 * Write 1 clears the mask bit to 0.
+		 */
+		ioport32_t mir_clear;
+
+		/* This register is used to set the interrupt mask bits,
+		 * Write 1 sets the mask bit to 1.
+		 */
+		ioport32_t mir_set;
+
+		/* This register is used to set the software interrupt bits,
+		 * it is also used to read the current active software
+		 * interrupts.
+		 * Write 1 sets the software interrups bits to 1.
+		 */
+		ioport32_t isr_set;
+
+		/* This register is used to clear the software interrups bits.
+		 * Write 1 clears the software interrupt bits to 0.
+		 */
+		ioport32_t isr_clear;
+
+		/* This register contains the IRQ status after masking. */
+		const ioport32_t pending_irq;
+
+		/* This register contains the FIQ status after masking. */
+		const ioport32_t pending_fiq;
+	} interrupts[OMAP_IRC_IRQ_GROUPS_COUNT];
+
+	const uint32_t padd4[8 * OMAP_IRC_IRQ_GROUPS_PAD];
+
+	/* These registers contain the priority for the interrups and
+	 * the FIQ/IRQ steering.
+	 */
+	ioport32_t ilr[OMAP_IRC_IRQ_COUNT];
+/* 0 = Interrupt routed to IRQ, 1 = interrupt routed to FIQ */
+#define OMAP_IRC_ILR_FIQNIRQ_FLAG    (1 << 0)
+#define OMAP_IRC_ILR_PRIORITY_MASK   0x3F
+#define OMAP_IRC_ILR_PRIORITY_SHIFT  2
+
+} omap_irc_regs_t;
+
+static inline void omap_irc_init(omap_irc_regs_t *regs)
+{
+	int i;
+
+	/* Initialization sequence */
+
+	/* 1 - Program the SYSCONFIG register: if necessary, enable the
+	 *     autogating by setting the AUTOIDLE bit.
+	 */
+	regs->sysconfig &= ~OMAP_IRC_SYSCONFIG_AUTOIDLE_FLAG;
+
+	/* 2 - Program the IDLE register: if necessary, disable functional
+	 *     clock autogating or enable synchronizer autogating by setting
+	 *     the FUNCIDLE bit or the TURBO bit accordingly.
+	 */
+	regs->idle &= ~OMAP_IRC_IDLE_FUNCIDLE_FLAG;
+	regs->idle &= ~OMAP_IRC_IDLE_TURBO_FLAG;
+
+	/* 3 - Program ILRm register for each interrupt line: Assign a
+	 *     priority level and set the FIQNIRQ bit for an FIQ interrupt
+	 *     (by default, interrupts are mapped to IRQ and
+	 *     priority is 0 (highest).
+	 */
+
+	for (i = 0; i < OMAP_IRC_IRQ_COUNT; ++i)
+		regs->ilr[i] = 0;
+
+	/* 4 - Program the MIRn register: Enable interrupts (by default,
+	 *     all interrupt lines are masked).
+	 */
+	for (i = 0; i < OMAP_IRC_IRQ_GROUPS_COUNT; ++i)
+		regs->interrupts[i].mir_set = 0xFFFFFFFF;
+}
+
+/** Get the currently active IRQ interrupt number
+ *
+ * @param regs     Pointer to the irc memory mapped registers
+ *
+ * @return         The active IRQ interrupt number
+ */
+static inline unsigned omap_irc_inum_get(omap_irc_regs_t *regs)
+{
+	return regs->sir_irq & OMAP_IRC_SIR_IRQ_ACTIVEIRQ_MASK;
+}
+
+/** Reset IRQ output and enable new IRQ generation
+ *
+ * @param regs    Pointer to the irc memory mapped registers
+ */
+static inline void omap_irc_irq_ack(omap_irc_regs_t *regs)
+{
+	regs->control = OMAP_IRC_CONTROL_NEWIRQAGR_FLAG;
+}
+
+/** Reset FIQ output and enable new FIQ generation
+ *
+ * @param regs    Pointer to the irc memory mapped registers
+ */
+static inline void omap_irc_fiq_ack(omap_irc_regs_t *regs)
+{
+	regs->control = OMAP_IRC_CONTROL_NEWFIQAGR_FLAG;
+}
+
+/** Clear an interrupt mask bit
+ *
+ * @param regs    Pointer to the irc memory mapped registers
+ * @param inum    The interrupt to be enabled
+ */
+static inline void omap_irc_enable(omap_irc_regs_t *regs, unsigned inum)
+{
+	ASSERT(inum < OMAP_IRC_IRQ_COUNT);
+	const unsigned set = inum / 32;
+	const unsigned pos = inum % 32;
+	regs->interrupts[set].mir_clear = (1 << pos);
+}
+
+/** Set an interrupt mask bit
+ *
+ * @param regs    Pointer to the irc memory mapped registers
+ * @param inum    The interrupt to be disabled
+ */
+static inline void omap_irc_disable(omap_irc_regs_t *regs, unsigned inum)
+{
+	ASSERT(inum < OMAP_IRC_IRQ_COUNT);
+	const unsigned set = inum / 32;
+	const unsigned pos = inum % 32;
+	regs->interrupts[set].mir_set = (1 << pos);
+}
+
+static inline void omap_irc_dump(omap_irc_regs_t *regs)
+{
+#define DUMP_REG(name) \
+	printf("%s %p(%x).\n", #name, &regs->name, regs->name);
+
+	DUMP_REG(revision);
+	DUMP_REG(sysconfig);
+	DUMP_REG(sysstatus);
+	DUMP_REG(sir_irq);
+	DUMP_REG(sir_fiq);
+	DUMP_REG(control);
+	DUMP_REG(protection);
+	DUMP_REG(idle);
+	DUMP_REG(irq_priority);
+	DUMP_REG(fiq_priority);
+	DUMP_REG(threshold);
+
+	for (int i = 0; i < OMAP_IRC_IRQ_GROUPS_COUNT; ++i) {
+		DUMP_REG(interrupts[i].itr);
+		DUMP_REG(interrupts[i].mir);
+		DUMP_REG(interrupts[i].isr_set);
+		DUMP_REG(interrupts[i].pending_irq);
+		DUMP_REG(interrupts[i].pending_fiq);
+	}
+	for (int i = 0; i < OMAP_IRC_IRQ_COUNT; ++i) {
+		DUMP_REG(ilr[i]);
+	}
+
+#undef DUMP_REG
+}
+
+#endif
+
+/**
+ * @}
+ */
Index: kernel/genarch/include/genarch/mm/page_pt.h
===================================================================
--- kernel/genarch/include/genarch/mm/page_pt.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/genarch/include/genarch/mm/page_pt.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -58,9 +58,15 @@
 #define PTL3_ENTRIES  PTL3_ENTRIES_ARCH
 
-/* Table sizes in each level */
-#define PTL0_SIZE  PTL0_SIZE_ARCH
-#define PTL1_SIZE  PTL1_SIZE_ARCH
-#define PTL2_SIZE  PTL2_SIZE_ARCH
-#define PTL3_SIZE  PTL3_SIZE_ARCH
+/* Table sizes in each level (in frames) */
+#define PTL0_FRAMES  PTL0_FRAMES_ARCH
+#define PTL1_FRAMES  PTL1_FRAMES_ARCH
+#define PTL2_FRAMES  PTL2_FRAMES_ARCH
+#define PTL3_FRAMES  PTL3_FRAMES_ARCH
+
+/* Table sizes in each level (in bytes) */
+#define PTL0_SIZE  FRAMES2SIZE(PTL0_FRAMES)
+#define PTL1_SIZE  FRAMES2SIZE(PTL1_FRAMES)
+#define PTL2_SIZE  FRAMES2SIZE(PTL2_FRAMES)
+#define PTL3_SIZE  FRAMES2SIZE(PTL3_FRAMES)
 
 /*
Index: kernel/genarch/src/mm/as_pt.c
===================================================================
--- kernel/genarch/src/mm/as_pt.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/genarch/src/mm/as_pt.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -73,14 +73,12 @@
 pte_t *ptl0_create(unsigned int flags)
 {
-	pte_t *dst_ptl0 = (pte_t *) frame_alloc(PTL0_SIZE,
-	    FRAME_LOWMEM | FRAME_KA);
-	size_t table_size = FRAME_SIZE << PTL0_SIZE;
+	pte_t *dst_ptl0 = (pte_t *)
+	    PA2KA(frame_alloc(PTL0_FRAMES, FRAME_LOWMEM, PTL0_SIZE - 1));
 	
 	if (flags & FLAG_AS_KERNEL)
-		memsetb(dst_ptl0, table_size, 0);
+		memsetb(dst_ptl0, PTL0_SIZE, 0);
 	else {
 		/*
 		 * Copy the kernel address space portion to new PTL0.
-		 *
 		 */
 		
@@ -95,7 +93,7 @@
 		    &dst_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)];
 		
-		memsetb(dst_ptl0, table_size, 0);
+		memsetb(dst_ptl0, PTL0_SIZE, 0);
 		memcpy((void *) dst, (void *) src,
-		    table_size - (src - (uintptr_t) src_ptl0));
+		    PTL0_SIZE - (src - (uintptr_t) src_ptl0));
 		
 		mutex_unlock(&AS_KERNEL->lock);
@@ -114,5 +112,5 @@
 void ptl0_destroy(pte_t *page_table)
 {
-	frame_free((uintptr_t) page_table);
+	frame_free((uintptr_t) page_table, PTL0_FRAMES);
 }
 
Index: kernel/genarch/src/mm/page_pt.c
===================================================================
--- kernel/genarch/src/mm/page_pt.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/genarch/src/mm/page_pt.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -82,7 +82,7 @@
 	
 	if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
-		pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE,
-		    FRAME_LOWMEM | FRAME_KA);
-		memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0);
+		pte_t *newpt = (pte_t *)
+		    PA2KA(frame_alloc(PTL1_FRAMES, FRAME_LOWMEM, PTL1_SIZE - 1));
+		memsetb(newpt, PTL1_SIZE, 0);
 		SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
 		SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page),
@@ -101,7 +101,7 @@
 	
 	if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
-		pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE,
-		    FRAME_LOWMEM | FRAME_KA);
-		memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0);
+		pte_t *newpt = (pte_t *)
+		    PA2KA(frame_alloc(PTL2_FRAMES, FRAME_LOWMEM, PTL2_SIZE - 1));
+		memsetb(newpt, PTL2_SIZE, 0);
 		SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
 		SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page),
@@ -118,7 +118,7 @@
 	
 	if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
-		pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE,
-		    FRAME_LOWMEM | FRAME_KA);
-		memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0);
+		pte_t *newpt = (pte_t *)
+		    PA2KA(frame_alloc(PTL3_FRAMES, FRAME_LOWMEM, PTL2_SIZE - 1));
+		memsetb(newpt, PTL2_SIZE, 0);
 		SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
 		SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page),
@@ -219,5 +219,5 @@
 		memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
 #endif
-		frame_free(KA2PA((uintptr_t) ptl3));
+		frame_free(KA2PA((uintptr_t) ptl3), PTL3_FRAMES);
 	} else {
 		/*
@@ -253,5 +253,5 @@
 		memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
 #endif
-		frame_free(KA2PA((uintptr_t) ptl2));
+		frame_free(KA2PA((uintptr_t) ptl2), PTL2_FRAMES);
 	} else {
 		/*
@@ -284,5 +284,5 @@
 
 		memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
-		frame_free(KA2PA((uintptr_t) ptl1));
+		frame_free(KA2PA((uintptr_t) ptl1), PTL1_FRAMES);
 	}
 #endif /* PTL1_ENTRIES != 0 */
@@ -363,28 +363,27 @@
  * @param size Size in bytes defining the range of PTL0 entries that will be
  *             altered by this function.
+ *
  */
 void pt_mapping_make_global(uintptr_t base, size_t size)
 {
+	ASSERT(size > 0);
+	
 	uintptr_t ptl0 = PA2KA((uintptr_t) AS_KERNEL->genarch.page_table);
 	uintptr_t ptl0_step = ptl0_step_get();
-	size_t order;
-	uintptr_t addr;
-
+	size_t frames;
+	
 #if (PTL1_ENTRIES != 0)
-	order = PTL1_SIZE;
+	frames = PTL1_FRAMES;
 #elif (PTL2_ENTRIES != 0)
-	order = PTL2_SIZE;
+	frames = PTL2_FRAMES;
 #else
-	order = PTL3_SIZE;
-#endif
-
-	ASSERT(size > 0);
-
-	for (addr = ALIGN_DOWN(base, ptl0_step); addr - 1 < base + size - 1;
+	frames = PTL3_FRAMES;
+#endif
+	
+	for (uintptr_t addr = ALIGN_DOWN(base, ptl0_step);
+	    addr - 1 < base + size - 1;
 	    addr += ptl0_step) {
-		uintptr_t l1;
-
-		l1 = (uintptr_t) frame_alloc(order, FRAME_KA | FRAME_LOWMEM);
-		memsetb((void *) l1, FRAME_SIZE << order, 0);
+		uintptr_t l1 = PA2KA(frame_alloc(frames, FRAME_LOWMEM, 0));
+		memsetb((void *) l1, FRAMES2SIZE(frames), 0);
 		SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(addr), KA2PA(l1));
 		SET_PTL1_FLAGS(ptl0, PTL0_INDEX(addr),
Index: kernel/generic/include/adt/bitmap.h
===================================================================
--- kernel/generic/include/adt/bitmap.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/include/adt/bitmap.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -38,24 +38,59 @@
 #include <typedefs.h>
 
-#define BITS2BYTES(bits)	(bits ? ((((bits)-1)>>3)+1) : 0)
+#define BITMAP_ELEMENT   8
+#define BITMAP_REMAINER  7
 
 typedef struct {
-	uint8_t *map;
-	size_t bits;
+	size_t elements;
+	uint8_t *bits;
+	
+	size_t block_size;
+	uint8_t *blocks;
 } bitmap_t;
 
-extern void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, size_t bits);
-extern void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t bits);
-extern void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t bits);
-extern void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t bits);
+static inline void bitmap_set(bitmap_t *bitmap, size_t element,
+    unsigned int value)
+{
+	if (element < bitmap->elements) {
+		/*
+		 * The 2nd level bitmap is conservative.
+		 * Make sure we update it properly.
+		 */
+		
+		if (value) {
+			bitmap->bits[element / BITMAP_ELEMENT] |=
+			    (1 << (element & BITMAP_REMAINER));
+		} else {
+			bitmap->bits[element / BITMAP_ELEMENT] &=
+			    ~(1 << (element & BITMAP_REMAINER));
+			
+			if (bitmap->block_size > 0) {
+				size_t block = element / bitmap->block_size;
+				
+				bitmap->blocks[block / BITMAP_ELEMENT] &=
+				    ~(1 << (block & BITMAP_REMAINER));
+			}
+		}
+	}
+}
 
-static inline int bitmap_get(bitmap_t *bitmap, size_t bit)
+static inline unsigned int bitmap_get(bitmap_t *bitmap, size_t element)
 {
-	if(bit >= bitmap->bits)
+	if (element >= bitmap->elements)
 		return 0;
 	
-	return !! ((bitmap->map)[bit/8] & (1 << (bit & 7)));
+	return !!((bitmap->bits)[element / BITMAP_ELEMENT] &
+	    (1 << (element & BITMAP_REMAINER)));
 }
 
+extern size_t bitmap_size(size_t, size_t);
+extern void bitmap_initialize(bitmap_t *, size_t, size_t, void *);
+
+extern void bitmap_set_range(bitmap_t *, size_t, size_t);
+extern void bitmap_clear_range(bitmap_t *, size_t, size_t);
+
+extern int bitmap_allocate_range(bitmap_t *, size_t, size_t, size_t, size_t *);
+extern void bitmap_free_range(bitmap_t *, size_t, size_t);
+extern void bitmap_copy(bitmap_t *, bitmap_t *, size_t);
 
 #endif
Index: kernel/generic/include/adt/list.h
===================================================================
--- kernel/generic/include/adt/list.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/include/adt/list.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2001-2004 Jakub Jermar
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2013 Jiri Svoboda
  * All rights reserved.
  *
@@ -65,9 +65,11 @@
 
 #define list_get_instance(link, type, member) \
-	((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member))))
-
-#define list_foreach(list, iterator) \
-	for (link_t *iterator = (list).head.next; \
-	    iterator != &(list).head; iterator = iterator->next)
+	((type *) (((void *)(link)) - list_link_to_void(&(((type *) NULL)->member))))
+
+#define list_foreach(list, member, itype, iterator) \
+	for (itype *iterator = NULL; iterator == NULL; iterator = (itype *) 1) \
+	    for (link_t *_link = (list).head.next; \
+	    iterator = list_get_instance(_link, itype, member), \
+	    _link != &(list).head; _link = _link->next)
 
 #define assert_link_not_used(link) \
@@ -204,4 +206,28 @@
 }
 
+/** Get next item in list.
+ *
+ * @param link Current item link
+ * @param list List containing @a link
+ *
+ * @return Next item or NULL if @a link is the last item.
+ */
+static inline link_t *list_next(link_t *link, const list_t *list)
+{
+	return (link->next == &list->head) ? NULL : link->next;
+}
+
+/** Get previous item in list.
+ *
+ * @param link Current item link
+ * @param list List containing @a link
+ *
+ * @return Previous item or NULL if @a link is the first item.
+ */
+static inline link_t *list_prev(link_t *link, const list_t *list)
+{
+	return (link->prev == &list->head) ? NULL : link->prev;
+}
+
 /** Split or concatenate headless doubly-linked circular list
  *
@@ -270,13 +296,25 @@
 {
 	unsigned int cnt = 0;
-	
-	list_foreach(*list, link) {
+	link_t *link;
+	
+	link = list_first(list);
+	while (link != NULL) {
 		if (cnt == n)
 			return link;
 		
 		cnt++;
+		link = list_next(link, list);
 	}
 	
 	return NULL;
+}
+
+/** Verify that argument type is a pointer to link_t (at compile time).
+ *
+ * This can be used to check argument type in a macro.
+ */
+static inline const void *list_link_to_void(const link_t *link)
+{
+	return link;
 }
 
Index: kernel/generic/include/config.h
===================================================================
--- kernel/generic/include/config.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/include/config.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -37,13 +37,10 @@
 
 #include <arch/mm/page.h>
+#include <macros.h>
 
-#define ONE_FRAME    0
-#define TWO_FRAMES   1
-#define FOUR_FRAMES  2
+#define STACK_FRAMES  2
+#define STACK_SIZE    FRAMES2SIZE(STACK_FRAMES)
 
-#define STACK_FRAMES  TWO_FRAMES
-#define STACK_SIZE    ((1 << STACK_FRAMES) << PAGE_WIDTH)
-
-#define STACK_SIZE_USER	(1 * 1024 * 1024)
+#define STACK_SIZE_USER  (1 * 1024 * 1024)
 
 #define CONFIG_INIT_TASKS        32
@@ -97,5 +94,5 @@
 	/** Size of initial stack. */
 	size_t stack_size;
-
+	
 	bool identity_configured;
 	/** Base address of the kernel identity mapped memory. */
@@ -103,7 +100,7 @@
 	/** Size of the kernel identity mapped memory. */
 	size_t identity_size;
-
-	bool non_identity_configured;   
-
+	
+	bool non_identity_configured;
+	
 	/** End of physical memory. */
 	uint64_t physmem_end;
Index: kernel/generic/include/macros.h
===================================================================
--- kernel/generic/include/macros.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/include/macros.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -117,4 +117,11 @@
 	overlaps(KA2PA((x)), (szx), KA2PA((y)), (szy))
 
+#define PFN2ADDR(frame)  ((frame) << FRAME_WIDTH)
+#define ADDR2PFN(addr)   ((addr) >> FRAME_WIDTH)
+
+#define FRAMES2SIZE(frames)  ((frames) << FRAME_WIDTH)
+#define SIZE2FRAMES(size) \
+	(((size) == 0) ? 0 : ((((size) - 1) >> FRAME_WIDTH) + 1))
+
 #define KiB2SIZE(kb)  ((kb) << 10)
 #define MiB2SIZE(mb)  ((mb) << 20)
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/include/mm/as.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -250,7 +250,4 @@
 extern int as_area_change_flags(as_t *, unsigned int, uintptr_t);
 
-//TODO REMOVE!
-extern as_area_t * find_locked_area(as_t *as, uintptr_t va);
-
 extern unsigned int as_area_get_flags(as_area_t *);
 extern bool as_area_check_access(as_area_t *, pf_access_t);
Index: rnel/generic/include/mm/buddy.h
===================================================================
--- kernel/generic/include/mm/buddy.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ 	(revision )
@@ -1,91 +1,0 @@
-/*
- * Copyright (c) 2005 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.
- */
-
-/** @addtogroup genericmm
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_BUDDY_H_
-#define KERN_BUDDY_H_
-
-#include <typedefs.h>
-#include <adt/list.h>
-
-#define BUDDY_SYSTEM_INNER_BLOCK	0xff
-
-struct buddy_system;
-
-/** Buddy system operations to be implemented by each implementation. */
-typedef struct {
-	/**
-	 * Return pointer to left-side or right-side buddy for block passed as
-	 * argument.
-	 */
-	link_t *(* find_buddy)(struct buddy_system *, link_t *);
-	/**
-	 * Bisect the block passed as argument and return pointer to the new
-	 * right-side buddy.
-	 */
-	link_t *(* bisect)(struct buddy_system *, link_t *);
-	/** Coalesce two buddies into a bigger block. */
-	link_t *(* coalesce)(struct buddy_system *, link_t *, link_t *);
-	/** Set order of block passed as argument. */
-	void (*set_order)(struct buddy_system *, link_t *, uint8_t);
-	/** Return order of block passed as argument. */
-	uint8_t (*get_order)(struct buddy_system *, link_t *);
-	/** Mark block as busy. */
-	void (*mark_busy)(struct buddy_system *, link_t *);
-	/** Mark block as available. */
-	void (*mark_available)(struct buddy_system *, link_t *);
-	/** Find parent of block that has given order  */
-	link_t *(* find_block)(struct buddy_system *, link_t *, uint8_t);
-} buddy_system_operations_t;
-
-typedef struct buddy_system {
-	/** Maximal order of block which can be stored by buddy system. */
-	uint8_t max_order;
-	list_t *order;
-	buddy_system_operations_t *op;
-	/** Pointer to be used by the implementation. */
-	void *data;
-} buddy_system_t;
-
-extern void buddy_system_create(buddy_system_t *, uint8_t,
-    buddy_system_operations_t *, void *);
-extern link_t *buddy_system_alloc(buddy_system_t *, uint8_t);
-extern bool buddy_system_can_alloc(buddy_system_t *, uint8_t);
-extern void buddy_system_free(buddy_system_t *, link_t *);
-extern size_t buddy_conf_size(size_t);
-extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *);
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/mm/frame.h
===================================================================
--- kernel/generic/include/mm/frame.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/include/mm/frame.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -39,6 +39,6 @@
 #include <typedefs.h>
 #include <trace.h>
+#include <adt/bitmap.h>
 #include <adt/list.h>
-#include <mm/buddy.h>
 #include <synch/spinlock.h>
 #include <arch/mm/page.h>
@@ -50,44 +50,37 @@
 typedef uint8_t frame_flags_t;
 
-#define FRAME_NONE        0x0
-/** Convert the frame address to kernel VA. */
-#define FRAME_KA          0x1
+#define FRAME_NONE        0x00
 /** Do not panic and do not sleep on failure. */
-#define FRAME_ATOMIC      0x2
+#define FRAME_ATOMIC      0x01
 /** Do not start reclaiming when no free memory. */
-#define FRAME_NO_RECLAIM  0x4
+#define FRAME_NO_RECLAIM  0x02
 /** Do not reserve / unreserve memory. */
-#define FRAME_NO_RESERVE  0x8
+#define FRAME_NO_RESERVE  0x04
 /** Allocate a frame which can be identity-mapped. */
-#define FRAME_LOWMEM	  0x10
+#define FRAME_LOWMEM      0x08
 /** Allocate a frame which cannot be identity-mapped. */
-#define FRAME_HIGHMEM	  0x20
-/** Allocate a frame which needs to be from DMA zone. */
-#define FRAME_DMA         0x40
+#define FRAME_HIGHMEM     0x10
 
 typedef uint8_t zone_flags_t;
 
-#define ZONE_NONE	0x0
+#define ZONE_NONE       0x00
 /** Available zone (free for allocation) */
-#define ZONE_AVAILABLE  0x1
+#define ZONE_AVAILABLE  0x01
 /** Zone is reserved (not available for allocation) */
-#define ZONE_RESERVED   0x2
+#define ZONE_RESERVED   0x02
 /** Zone is used by firmware (not available for allocation) */
-#define ZONE_FIRMWARE   0x4
+#define ZONE_FIRMWARE   0x04
 /** Zone contains memory that can be identity-mapped */
-#define ZONE_LOWMEM	0x8
+#define ZONE_LOWMEM     0x08
 /** Zone contains memory that cannot be identity-mapped */
-#define ZONE_HIGHMEM	0x10
-/** Zone contains memory suitable for old ISA DMA */
-#define ZONE_DMA        0x20
+#define ZONE_HIGHMEM    0x10
 
 /** Mask of zone bits that must be matched exactly. */
-#define ZONE_EF_MASK	0x7
+#define ZONE_EF_MASK  0x07
 
-#define FRAME_TO_ZONE_FLAGS(ff)	\
-	((((ff) & FRAME_DMA) ? ZONE_DMA : \
-	    (((ff) & FRAME_LOWMEM) ? ZONE_LOWMEM : \
+#define FRAME_TO_ZONE_FLAGS(ff) \
+	((((ff) & FRAME_LOWMEM) ? ZONE_LOWMEM : \
 	    (((ff) & FRAME_HIGHMEM) ? ZONE_HIGHMEM : \
-	    ZONE_LOWMEM /* | ZONE_HIGHMEM */))) | \
+	    ZONE_LOWMEM /* | ZONE_HIGHMEM */)) | \
 	    ZONE_AVAILABLE)
 
@@ -97,24 +90,29 @@
 
 typedef struct {
-	size_t refcount;      /**< Tracking of shared frames */
-	link_t buddy_link;    /**< Link to the next free block inside
-                                   one order */
-	void *parent;         /**< If allocated by slab, this points there */
-	uint8_t buddy_order;  /**< Buddy system block order */
+	size_t refcount;  /**< Tracking of shared frames */
+	void *parent;     /**< If allocated by slab, this points there */
 } frame_t;
 
 typedef struct {
-	pfn_t base;                    /**< Frame_no of the first frame
-                                            in the frames array */
-	size_t count;                  /**< Size of zone */
-	size_t free_count;             /**< Number of free frame_t
-                                            structures */
-	size_t busy_count;             /**< Number of busy frame_t
-                                            structures */
-	zone_flags_t flags;            /**< Type of the zone */
+	/** Frame_no of the first frame in the frames array */
+	pfn_t base;
 	
-	frame_t *frames;               /**< Array of frame_t structures
-                                            in this zone */
-	buddy_system_t *buddy_system;  /**< Buddy system for the zone */
+	/** Size of zone */
+	size_t count;
+	
+	/** Number of free frame_t structures */
+	size_t free_count;
+	
+	/** Number of busy frame_t structures */
+	size_t busy_count;
+	
+	/** Type of the zone */
+	zone_flags_t flags;
+	
+	/** Frame bitmap */
+	bitmap_t bitmap;
+	
+	/** Array of frame_t structures in this zone */
+	frame_t *frames;
 } zone_t;
 
@@ -131,45 +129,12 @@
 extern zones_t zones;
 
-NO_TRACE static inline uintptr_t PFN2ADDR(pfn_t frame)
-{
-	return (uintptr_t) (frame << FRAME_WIDTH);
-}
-
-NO_TRACE static inline pfn_t ADDR2PFN(uintptr_t addr)
-{
-	return (pfn_t) (addr >> FRAME_WIDTH);
-}
-
-NO_TRACE static inline size_t SIZE2FRAMES(size_t size)
-{
-	if (!size)
-		return 0;
-	return (size_t) ((size - 1) >> FRAME_WIDTH) + 1;
-}
-
-NO_TRACE static inline size_t FRAMES2SIZE(size_t frames)
-{
-	return (size_t) (frames << FRAME_WIDTH);
-}
-
-#define IS_BUDDY_ORDER_OK(index, order) \
-    ((~(((sysarg_t) -1) << (order)) & (index)) == 0)
-#define IS_BUDDY_LEFT_BLOCK(zone, frame) \
-    (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
-#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \
-    (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
-#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \
-    (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
-#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \
-    (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
-
 extern void frame_init(void);
 extern bool frame_adjust_zone_bounds(bool, uintptr_t *, size_t *);
-extern void *frame_alloc_generic(uint8_t, frame_flags_t, size_t *);
-extern void *frame_alloc(uint8_t, frame_flags_t);
-extern void *frame_alloc_noreserve(uint8_t, frame_flags_t);
-extern void frame_free_generic(uintptr_t, frame_flags_t);
-extern void frame_free(uintptr_t);
-extern void frame_free_noreserve(uintptr_t);
+extern uintptr_t frame_alloc_generic(size_t, frame_flags_t, uintptr_t, size_t *);
+extern uintptr_t frame_alloc(size_t, frame_flags_t, uintptr_t);
+extern uintptr_t frame_alloc_noreserve(size_t, frame_flags_t, uintptr_t);
+extern void frame_free_generic(uintptr_t, size_t, frame_flags_t);
+extern void frame_free(uintptr_t, size_t);
+extern void frame_free_noreserve(uintptr_t, size_t);
 extern void frame_reference_add(pfn_t);
 extern size_t frame_total_free_get(void);
Index: kernel/generic/include/mm/page.h
===================================================================
--- kernel/generic/include/mm/page.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/include/mm/page.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -65,6 +65,6 @@
 extern void page_table_destroy(pte_t *);
 
-extern int page_find_mapping(uintptr_t, void **);
-extern sysarg_t sys_page_find_mapping(uintptr_t, void *);
+extern int page_find_mapping(uintptr_t, uintptr_t *);
+extern sysarg_t sys_page_find_mapping(uintptr_t, uintptr_t *);
 
 #endif
Index: kernel/generic/include/mm/slab.h
===================================================================
--- kernel/generic/include/mm/slab.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/include/mm/slab.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -55,5 +55,5 @@
 /** Maximum wasted space we allow for cache */
 #define SLAB_MAX_BADNESS(cache) \
-	(((unsigned int) PAGE_SIZE << (cache)->order) >> 2)
+	(FRAMES2SIZE((cache)->frames) >> 2)
 
 /* slab_reclaim constants */
@@ -90,4 +90,5 @@
 	
 	/* Configuration */
+	
 	/** Size of slab position - align_up(sizeof(obj)) */
 	size_t size;
@@ -100,5 +101,5 @@
 	
 	/* Computed values */
-	uint8_t order;   /**< Order of frames to be allocated */
+	size_t frames;   /**< Number of frames to be allocated */
 	size_t objects;  /**< Number of objects that fit in */
 	
Index: kernel/generic/src/adt/bitmap.c
===================================================================
--- kernel/generic/src/adt/bitmap.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/adt/bitmap.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -35,5 +35,14 @@
  *
  * This file implements bitmap ADT and provides functions for
- * setting and clearing ranges of bits.
+ * setting and clearing ranges of bits and for finding ranges
+ * of unset bits.
+ *
+ * The bitmap ADT can optionally implement a two-level hierarchy
+ * for faster range searches. The second level bitmap (of blocks)
+ * is not precise, but conservative. This means that if the block
+ * bit is set, it guarantees that all bits in the block are set.
+ * But if the block bit is unset, nothing can be said about the
+ * bits in the block.
+ *
  */
 
@@ -44,6 +53,34 @@
 #include <macros.h>
 
-#define ALL_ONES 	0xff
-#define ALL_ZEROES	0x00
+#define ALL_ONES    0xff
+#define ALL_ZEROES  0x00
+
+/** Get bitmap size
+ *
+ * Return the size (in bytes) required for the bitmap.
+ *
+ * @param elements   Number bits stored in bitmap.
+ * @param block_size Block size of the 2nd level bitmap.
+ *                   If set to zero, no 2nd level is used.
+ *
+ * @return Size (in bytes) required for the bitmap.
+ *
+ */
+size_t bitmap_size(size_t elements, size_t block_size)
+{
+	size_t size = elements / BITMAP_ELEMENT;
+	
+	if ((elements % BITMAP_ELEMENT) != 0)
+		size++;
+	
+	if (block_size > 0) {
+		size += elements / block_size;
+		
+		if ((elements % block_size) != 0)
+			size++;
+	}
+	
+	return size;
+}
 
 /** Initialize bitmap.
@@ -51,41 +88,49 @@
  * No portion of the bitmap is set or cleared by this function.
  *
- * @param bitmap	Bitmap structure.
- * @param map		Address of the memory used to hold the map.
- * @param bits		Number of bits stored in bitmap.
- */
-void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, size_t bits)
-{
-	bitmap->map = map;
-	bitmap->bits = bits;
-}
-
-/** Set range of bits.
- *
- * @param bitmap	Bitmap structure.
- * @param start		Starting bit.
- * @param bits		Number of bits to set.
- */
-void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t bits)
-{
-	size_t i = 0;
-	size_t aligned_start;
-	size_t lub;	/* leading unaligned bits */
-	size_t amb;	/* aligned middle bits */
-	size_t tab;	/* trailing aligned bits */
-	
-	ASSERT(start + bits <= bitmap->bits);
-	
-	aligned_start = ALIGN_UP(start, 8);
-	lub = min(aligned_start - start, bits);
-	amb = bits > lub ? bits - lub : 0;
-	tab = amb % 8;
-	
-	if (!bits)
+ * @param bitmap     Bitmap structure.
+ * @param elements   Number of bits stored in bitmap.
+ * @param block_size Block size of the 2nd level bitmap.
+ *                   If set to zero, no 2nd level is used.
+ * @param data       Address of the memory used to hold the map.
+ *                   The optional 2nd level bitmap follows the 1st
+ *                   level bitmap.
+ *
+ */
+void bitmap_initialize(bitmap_t *bitmap, size_t elements, size_t block_size,
+    void *data)
+{
+	bitmap->elements = elements;
+	bitmap->bits = (uint8_t *) data;
+	
+	if (block_size > 0) {
+		bitmap->block_size = block_size;
+		bitmap->blocks = bitmap->bits +
+		    bitmap_size(elements, 0);
+	} else {
+		bitmap->block_size = 0;
+		bitmap->blocks = NULL;
+	}
+}
+
+static void bitmap_set_range_internal(uint8_t *bits, size_t start, size_t count)
+{
+	if (count == 0)
 		return;
-
-	if (start + bits < aligned_start) {
+	
+	size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT);
+	
+	/* Leading unaligned bits */
+	size_t lub = min(aligned_start - start, count);
+	
+	/* Aligned middle bits */
+	size_t amb = (count > lub) ? (count - lub) : 0;
+	
+	/* Trailing aligned bits */
+	size_t tab = amb % BITMAP_ELEMENT;
+	
+	if (start + count < aligned_start) {
 		/* Set bits in the middle of byte. */
-		bitmap->map[start / 8] |= ((1 << lub) - 1) << (start & 7);
+		bits[start / BITMAP_ELEMENT] |=
+		    ((1 << lub) - 1) << (start & BITMAP_REMAINER);
 		return;
 	}
@@ -93,82 +138,240 @@
 	if (lub) {
 		/* Make sure to set any leading unaligned bits. */
-		bitmap->map[start / 8] |= ~((1 << (8 - lub)) - 1);
-	}
-	for (i = 0; i < amb / 8; i++) {
+		bits[start / BITMAP_ELEMENT] |=
+		    ~((1 << (BITMAP_ELEMENT - lub)) - 1);
+	}
+	
+	size_t i;
+	
+	for (i = 0; i < amb / BITMAP_ELEMENT; i++) {
 		/* The middle bits can be set byte by byte. */
-		bitmap->map[aligned_start / 8 + i] = ALL_ONES;
-	}
+		bits[aligned_start / BITMAP_ELEMENT + i] = ALL_ONES;
+	}
+	
 	if (tab) {
 		/* Make sure to set any trailing aligned bits. */
-		bitmap->map[aligned_start / 8 + i] |= (1 << tab) - 1;
-	}
-	
-}
-
-/** Clear range of bits.
- *
- * @param bitmap	Bitmap structure.
- * @param start		Starting bit.
- * @param bits		Number of bits to clear.
- */
-void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t bits)
-{
-	size_t i = 0;
-	size_t aligned_start;
-	size_t lub;	/* leading unaligned bits */
-	size_t amb;	/* aligned middle bits */
-	size_t tab;	/* trailing aligned bits */
-	
-	ASSERT(start + bits <= bitmap->bits);
-	
-	aligned_start = ALIGN_UP(start, 8);
-	lub = min(aligned_start - start, bits);
-	amb = bits > lub ? bits - lub : 0;
-	tab = amb % 8;
-
-	if (!bits)
+		bits[aligned_start / BITMAP_ELEMENT + i] |= (1 << tab) - 1;
+	}
+}
+
+/** Set range of bits.
+ *
+ * @param bitmap Bitmap structure.
+ * @param start  Starting bit.
+ * @param count  Number of bits to set.
+ *
+ */
+void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t count)
+{
+	ASSERT(start + count <= bitmap->elements);
+	
+	bitmap_set_range_internal(bitmap->bits, start, count);
+	
+	if (bitmap->block_size > 0) {
+		size_t aligned_start = ALIGN_UP(start, bitmap->block_size);
+		
+		/* Leading unaligned bits */
+		size_t lub = min(aligned_start - start, count);
+		
+		/* Aligned middle bits */
+		size_t amb = (count > lub) ? (count - lub) : 0;
+		
+		size_t aligned_size = amb / bitmap->block_size;
+		
+		bitmap_set_range_internal(bitmap->blocks, aligned_start,
+		    aligned_size);
+	}
+}
+
+static void bitmap_clear_range_internal(uint8_t *bits, size_t start,
+    size_t count)
+{
+	if (count == 0)
 		return;
-
-	if (start + bits < aligned_start) {
+	
+	size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT);
+	
+	/* Leading unaligned bits */
+	size_t lub = min(aligned_start - start, count);
+	
+	/* Aligned middle bits */
+	size_t amb = (count > lub) ? (count - lub) : 0;
+	
+	/* Trailing aligned bits */
+	size_t tab = amb % BITMAP_ELEMENT;
+	
+	if (start + count < aligned_start) {
 		/* Set bits in the middle of byte */
-		bitmap->map[start / 8] &= ~(((1 << lub) - 1) << (start & 7));
+		bits[start / BITMAP_ELEMENT] &=
+		    ~(((1 << lub) - 1) << (start & BITMAP_REMAINER));
 		return;
 	}
-
+	
 	if (lub) {
 		/* Make sure to clear any leading unaligned bits. */
-		bitmap->map[start / 8] &= (1 << (8 - lub)) - 1;
-	}
-	for (i = 0; i < amb / 8; i++) {
+		bits[start / BITMAP_ELEMENT] &=
+		    (1 << (BITMAP_ELEMENT - lub)) - 1;
+	}
+	
+	size_t i;
+	
+	for (i = 0; i < amb / BITMAP_ELEMENT; i++) {
 		/* The middle bits can be cleared byte by byte. */
-		bitmap->map[aligned_start / 8 + i] = ALL_ZEROES;
-	}
+		bits[aligned_start / BITMAP_ELEMENT + i] = ALL_ZEROES;
+	}
+	
 	if (tab) {
 		/* Make sure to clear any trailing aligned bits. */
-		bitmap->map[aligned_start / 8 + i] &= ~((1 << tab) - 1);
-	}
-
+		bits[aligned_start / BITMAP_ELEMENT + i] &= ~((1 << tab) - 1);
+	}
+}
+
+/** Clear range of bits.
+ *
+ * @param bitmap Bitmap structure.
+ * @param start  Starting bit.
+ * @param count  Number of bits to clear.
+ *
+ */
+void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t count)
+{
+	ASSERT(start + count <= bitmap->elements);
+	
+	bitmap_clear_range_internal(bitmap->bits, start, count);
+	
+	if (bitmap->block_size > 0) {
+		size_t aligned_start = start / bitmap->block_size;
+		
+		size_t aligned_end = (start + count) / bitmap->block_size;
+		
+		if (((start + count) % bitmap->block_size) != 0)
+			aligned_end++;
+		
+		size_t aligned_size = aligned_end - aligned_start;
+		
+		bitmap_clear_range_internal(bitmap->blocks, aligned_start,
+		    aligned_size);
+	}
 }
 
 /** Copy portion of one bitmap into another bitmap.
  *
- * @param dst		Destination bitmap.
- * @param src		Source bitmap.
- * @param bits		Number of bits to copy.
- */
-void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t bits)
-{
+ * @param dst   Destination bitmap.
+ * @param src   Source bitmap.
+ * @param count Number of bits to copy.
+ *
+ */
+void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t count)
+{
+	ASSERT(count <= dst->elements);
+	ASSERT(count <= src->elements);
+	
 	size_t i;
 	
-	ASSERT(bits <= dst->bits);
-	ASSERT(bits <= src->bits);
-	
-	for (i = 0; i < bits / 8; i++)
-		dst->map[i] = src->map[i];
-	
-	if (bits % 8) {
-		bitmap_clear_range(dst, i * 8, bits % 8);
-		dst->map[i] |= src->map[i] & ((1 << (bits % 8)) - 1);
-	}
+	for (i = 0; i < count / BITMAP_ELEMENT; i++)
+		dst->bits[i] = src->bits[i];
+	
+	if (count % BITMAP_ELEMENT) {
+		bitmap_clear_range(dst, i * BITMAP_ELEMENT,
+		    count % BITMAP_ELEMENT);
+		dst->bits[i] |= src->bits[i] &
+		    ((1 << (count % BITMAP_ELEMENT)) - 1);
+	}
+}
+
+static int constraint_satisfy(size_t index, size_t base, size_t constraint)
+{
+	return (((base + index) & constraint) == 0);
+}
+
+/** Find a continuous zero bit range
+ *
+ * Find a continuous zero bit range in the bitmap. The address
+ * computed as the sum of the index of the first zero bit and
+ * the base argument needs to be compliant with the constraint
+ * (those bits that are set in the constraint cannot be set in
+ * the address).
+ *
+ * If the index argument is non-NULL, the continuous zero range
+ * is set and the index of the first bit is stored to index.
+ * Otherwise the bitmap stays untouched.
+ *
+ * @param bitmap     Bitmap structure.
+ * @param count      Number of continuous zero bits to find.
+ * @param base       Address of the first bit in the bitmap.
+ * @param constraint Constraint for the address of the first zero bit.
+ * @param index      Place to store the index of the first zero
+ *                   bit. Can be NULL (in which case the bitmap
+ *                   is not modified).
+ *
+ * @return Non-zero if a continuous range of zero bits satisfying
+ *         the constraint has been found.
+ * @return Zero otherwise.
+ *
+ */
+int bitmap_allocate_range(bitmap_t *bitmap, size_t count, size_t base,
+    size_t constraint, size_t *index)
+{
+	if (count == 0)
+		return false;
+	
+	/*
+	 * This is a trivial implementation that should be
+	 * optimized further.
+	 */
+	
+	for (size_t i = 0; i < bitmap->elements; i++) {
+		if (!constraint_satisfy(i, base, constraint))
+			continue;
+		
+		if (!bitmap_get(bitmap, i)) {
+			bool continuous = true;
+			
+			for (size_t j = 1; j < count; j++) {
+				if ((i + j >= bitmap->elements) ||
+				    (bitmap_get(bitmap, i + j))) {
+					continuous = false;
+					break;
+				}
+			}
+			
+			if (continuous) {
+				if (index != NULL) {
+					bitmap_set_range(bitmap, i, count);
+					*index = i;
+				}
+				
+				return true;
+			}
+		}
+		
+	}
+	
+	return false;
+}
+
+/** Clear range of set bits.
+ *
+ * This is essentially bitmap_clear_range(), but it also
+ * checks whether all the cleared bits are actually set.
+ *
+ * @param bitmap Bitmap structure.
+ * @param start  Starting bit.
+ * @param count  Number of bits to clear.
+ *
+ */
+void bitmap_free_range(bitmap_t *bitmap, size_t start, size_t count)
+{
+	/*
+	 * This is a trivial implementation that should be
+	 * optimized further.
+	 */
+	
+	for (size_t i = 0; i < count; i++) {
+		if (!bitmap_get(bitmap, start + i))
+			panic("Freeing a bitmap range that is not set");
+	}
+	
+	bitmap_clear_range(bitmap, start, count);
 }
 
Index: kernel/generic/src/adt/btree.c
===================================================================
--- kernel/generic/src/adt/btree.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/adt/btree.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -1031,9 +1031,5 @@
 	
 	printf("Printing list of leaves:\n");
-	list_foreach(t->leaf_list, cur) {
-		btree_node_t *node;
-		
-		node = list_get_instance(cur, btree_node_t, leaf_link);
-		
+	list_foreach(t->leaf_list, leaf_link, btree_node_t, node) {
 		ASSERT(node);
 		
Index: kernel/generic/src/adt/hash_table.c
===================================================================
--- kernel/generic/src/adt/hash_table.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/adt/hash_table.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -117,5 +117,6 @@
 	ASSERT(chain < h->entries);
 	
-	list_foreach(h->entry[chain], cur) {
+	link_t *cur = list_first(&h->entry[chain]);
+	while (cur != NULL) {
 		if (h->op->compare(key, h->max_keys, cur)) {
 			/*
@@ -124,4 +125,5 @@
 			return cur;
 		}
+		cur = list_next(cur, &h->entry[chain]);
 	}
 	
Index: kernel/generic/src/adt/list.c
===================================================================
--- kernel/generic/src/adt/list.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/adt/list.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -101,6 +101,8 @@
 	unsigned int count = 0;
 	
-	list_foreach(*list, link) {
+	link_t *link = list_first(list);
+	while (link != NULL) {
 		count++;
+		link = list_next(link, list);
 	}
 	
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/console/cmd.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -656,8 +656,5 @@
 	
 	size_t len = 0;
-	list_foreach(cmd_list, cur) {
-		cmd_info_t *hlp;
-		hlp = list_get_instance(cur, cmd_info_t, link);
-		
+	list_foreach(cmd_list, link, cmd_info_t, hlp) {
 		spinlock_lock(&hlp->lock);
 		if (str_length(hlp->name) > len)
@@ -672,8 +669,5 @@
 	}
 	
-	list_foreach(cmd_list, cur) {
-		cmd_info_t *hlp;
-		hlp = list_get_instance(cur, cmd_info_t, link);
-		
+	list_foreach(cmd_list, link, cmd_info_t, hlp) {
 		spinlock_lock(&hlp->lock);
 		printf("%-*s %s\n", _len, hlp->name, hlp->description);
@@ -912,8 +906,5 @@
 	spinlock_lock(&cmd_lock);
 	
-	list_foreach(cmd_list, cur) {
-		cmd_info_t *hlp;
-		
-		hlp = list_get_instance(cur, cmd_info_t, link);
+	list_foreach(cmd_list, link, cmd_info_t, hlp) {
 		spinlock_lock(&hlp->lock);
 		
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/console/console.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -125,6 +125,5 @@
 static void stdout_write(outdev_t *dev, wchar_t ch)
 {
-	list_foreach(dev->list, cur) {
-		outdev_t *sink = list_get_instance(cur, outdev_t, link);
+	list_foreach(dev->list, link, outdev_t, sink) {
 		if ((sink) && (sink->op->write))
 			sink->op->write(sink, ch);
@@ -134,6 +133,5 @@
 static void stdout_redraw(outdev_t *dev)
 {
-	list_foreach(dev->list, cur) {
-		outdev_t *sink = list_get_instance(cur, outdev_t, link);
+	list_foreach(dev->list, link, outdev_t, sink) {
 		if ((sink) && (sink->op->redraw))
 			sink->op->redraw(sink);
Index: kernel/generic/src/console/kconsole.c
===================================================================
--- kernel/generic/src/console/kconsole.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/console/kconsole.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -53,5 +53,4 @@
 #include <func.h>
 #include <str.h>
-#include <macros.h>
 #include <sysinfo/sysinfo.h>
 #include <ddi/device.h>
@@ -119,7 +118,5 @@
 	 * Make sure the command is not already listed.
 	 */
-	list_foreach(cmd_list, cur) {
-		cmd_info_t *hlp = list_get_instance(cur, cmd_info_t, link);
-		
+	list_foreach(cmd_list, link, cmd_info_t, hlp) {
 		if (hlp == cmd) {
 			/* The command is already there. */
@@ -613,6 +610,5 @@
 	cmd_info_t *cmd = NULL;
 	
-	list_foreach(cmd_list, cur) {
-		cmd_info_t *hlp = list_get_instance(cur, cmd_info_t, link);
+	list_foreach(cmd_list, link, cmd_info_t, hlp) {
 		spinlock_lock(&hlp->lock);
 		
Index: kernel/generic/src/cpu/cpu.c
===================================================================
--- kernel/generic/src/cpu/cpu.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/cpu/cpu.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -73,12 +73,15 @@
 		size_t i;
 		for (i = 0; i < config.cpu_count; i++) {
-			cpus[i].stack = (uint8_t *) frame_alloc(STACK_FRAMES,
-			    FRAME_LOWMEM | FRAME_KA | FRAME_ATOMIC);
+			uintptr_t stack_phys = frame_alloc(STACK_FRAMES,
+			    FRAME_LOWMEM | FRAME_ATOMIC, STACK_SIZE - 1);
+			if (!stack_phys)
+				panic("Cannot allocate CPU stack.");
+			
+			cpus[i].stack = (uint8_t *) PA2KA(stack_phys);
 			cpus[i].id = i;
 			
 			irq_spinlock_initialize(&cpus[i].lock, "cpus[].lock");
 			
-			unsigned int j;
-			for (j = 0; j < RQ_COUNT; j++) {
+			for (unsigned int j = 0; j < RQ_COUNT; j++) {
 				irq_spinlock_initialize(&cpus[i].rq[j].lock, "cpus[].rq[].lock");
 				list_initialize(&cpus[i].rq[j].rq);
Index: kernel/generic/src/ddi/ddi.c
===================================================================
--- kernel/generic/src/ddi/ddi.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/ddi/ddi.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -314,5 +314,5 @@
 
 NO_TRACE static int dmamem_map(uintptr_t virt, size_t size, unsigned int map_flags,
-    unsigned int flags, void **phys)
+    unsigned int flags, uintptr_t *phys)
 {
 	ASSERT(TASK);
@@ -322,29 +322,22 @@
 }
 
-NO_TRACE static int dmamem_map_anonymous(size_t size, unsigned int map_flags,
-    unsigned int flags, void **phys, uintptr_t *virt, uintptr_t bound)
+NO_TRACE static int dmamem_map_anonymous(size_t size, uintptr_t constraint,
+    unsigned int map_flags, unsigned int flags, uintptr_t *phys,
+    uintptr_t *virt, uintptr_t bound)
 {
 	ASSERT(TASK);
 	
-	size_t pages = SIZE2FRAMES(size);
-	uint8_t order;
-	
-	/* We need the 2^order >= pages */
-	if (pages == 1)
-		order = 0;
-	else
-		order = fnzb(pages - 1) + 1;
-	
-	*phys = frame_alloc_noreserve(order, FRAME_DMA);
-	if (*phys == NULL)
+	size_t frames = SIZE2FRAMES(size);
+	*phys = frame_alloc_noreserve(frames, 0, constraint);
+	if (*phys == 0)
 		return ENOMEM;
 	
 	mem_backend_data_t backend_data;
-	backend_data.base = (uintptr_t) *phys;
-	backend_data.frames = pages;
+	backend_data.base = *phys;
+	backend_data.frames = frames;
 	
 	if (!as_area_create(TASK->as, map_flags, size,
 	    AS_AREA_ATTR_NONE, &phys_backend, &backend_data, virt, bound)) {
-		frame_free_noreserve((uintptr_t) *phys);
+		frame_free_noreserve(*phys, frames);
 		return ENOMEM;
 	}
@@ -361,20 +354,6 @@
 NO_TRACE static int dmamem_unmap_anonymous(uintptr_t virt)
 {
-	// TODO: This is an ugly hack
-	as_t *as = TASK->as;
-
-	mutex_lock(&as->lock);
-	as_area_t *area = find_locked_area(as, virt);
-	if (!area) {
-		mutex_unlock(&as->lock);
-		return ENOENT;
-	}
-	frame_free_noreserve(area->backend_data.base);
-	area->backend_data.base = 0;
-	area->backend_data.frames = 0;
-	mutex_unlock(&area->lock);
-	mutex_unlock(&as->lock);
-
-	return as_area_destroy(as, virt);
+	// TODO: implement unlocking & unmap
+	return EOK;
 }
 
@@ -387,5 +366,5 @@
 		 */
 		
-		void *phys;
+		uintptr_t phys;
 		int rc = dmamem_map((uintptr_t) virt_ptr, size, map_flags,
 		    flags, &phys);
@@ -404,7 +383,13 @@
 		 */
 		
-		void *phys;
+		uintptr_t constraint;
+		int rc = copy_from_uspace(&constraint, phys_ptr,
+		    sizeof(constraint));
+		if (rc != EOK)
+			return rc;
+		
+		uintptr_t phys;
 		uintptr_t virt = (uintptr_t) -1;
-		int rc = dmamem_map_anonymous(size, map_flags, flags,
+		rc = dmamem_map_anonymous(size, constraint, map_flags, flags,
 		    &phys, &virt, bound);
 		if (rc != EOK)
Index: kernel/generic/src/debug/stacktrace.c
===================================================================
--- kernel/generic/src/debug/stacktrace.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/debug/stacktrace.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -39,5 +39,5 @@
 #include <print.h>
 
-#define STACK_FRAMES_MAX	20
+#define STACK_FRAMES_MAX  20
 
 void stack_trace_ctx(stack_trace_ops_t *ops, stack_trace_context_t *ctx)
@@ -49,6 +49,6 @@
 	uintptr_t pc;
 	
-	while (cnt++ < STACK_FRAMES_MAX &&
-	    ops->stack_trace_context_validate(ctx)) {
+	while ((cnt++ < STACK_FRAMES_MAX) &&
+	    (ops->stack_trace_context_validate(ctx))) {
 		if (ops->symbol_resolve &&
 		    ops->symbol_resolve(ctx->pc, &symbol, &offset)) {
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/ipc/ipc.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -774,7 +774,5 @@
 static void ipc_print_call_list(list_t *list)
 {
-	list_foreach(*list, cur) {
-		call_t *call = list_get_instance(cur, call_t, ab_link);
-		
+	list_foreach(*list, ab_link, call_t, call) {
 #ifdef __32_BITS__
 		printf("%10p ", call);
Index: kernel/generic/src/ipc/ipcrsc.c
===================================================================
--- kernel/generic/src/ipc/ipcrsc.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/ipc/ipcrsc.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -151,6 +151,5 @@
 	irq_spinlock_lock(&TASK->answerbox.lock, true);
 	
-	list_foreach(TASK->answerbox.dispatched_calls, lst) {
-		call_t *call = list_get_instance(lst, call_t, ab_link);
+	list_foreach(TASK->answerbox.dispatched_calls, ab_link, call_t, call) {
 		if ((sysarg_t) call == callid) {
 			result = call;
Index: kernel/generic/src/lib/ra.c
===================================================================
--- kernel/generic/src/lib/ra.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/lib/ra.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -391,7 +391,5 @@
 
 	irq_spinlock_lock(&arena->lock, true);
-	list_foreach(arena->spans, cur) {
-		ra_span_t *span = list_get_instance(cur, ra_span_t, span_link);
-
+	list_foreach(arena->spans, span_link, ra_span_t, span) {
 		base = ra_span_alloc(span, size, alignment);
 		if (base)
@@ -407,7 +405,5 @@
 {
 	irq_spinlock_lock(&arena->lock, true);
-	list_foreach(arena->spans, cur) {
-		ra_span_t *span = list_get_instance(cur, ra_span_t, span_link);
-
+	list_foreach(arena->spans, span_link, ra_span_t, span) {
 		if (iswithin(span->base, span->size, base, size)) {
 			ra_span_free(span, base, size);
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/mm/as.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -488,7 +488,5 @@
 	
 	/* Eventually check the addresses behind each area */
-	list_foreach(as->as_area_btree.leaf_list, cur) {
-		btree_node_t *node =
-		    list_get_instance(cur, btree_node_t, leaf_link);
+	list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t, node) {
 		
 		for (btree_key_t i = 0; i < node->keys; i++) {
@@ -672,11 +670,4 @@
 	
 	return NULL;
-}
-
-/** UGLY! UGLY! UGLY! */
-// TODO: REMOVE ASAP!
-as_area_t * find_locked_area(as_t *as, uintptr_t va)
-{
-	return find_area_and_lock(as, va);
 }
 
@@ -911,11 +902,10 @@
 		 * reference from all frames found there.
 		 */
-		list_foreach(sh_info->pagemap.leaf_list, cur) {
-			btree_node_t *node
-			    = list_get_instance(cur, btree_node_t, leaf_link);
+		list_foreach(sh_info->pagemap.leaf_list, leaf_link,
+		    btree_node_t, node) {
 			btree_key_t i;
 			
 			for (i = 0; i < node->keys; i++)
-				frame_free((uintptr_t) node->value[i]);
+				frame_free((uintptr_t) node->value[i], 1);
 		}
 		
@@ -963,9 +953,8 @@
 	 * Visit only the pages mapped by used_space B+tree.
 	 */
-	list_foreach(area->used_space.leaf_list, cur) {
-		btree_node_t *node;
+	list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
+	    node) {
 		btree_key_t i;
 		
-		node = list_get_instance(cur, btree_node_t, leaf_link);
 		for (i = 0; i < node->keys; i++) {
 			uintptr_t ptr = node->key[i];
@@ -1245,7 +1234,6 @@
 	size_t used_pages = 0;
 	
-	list_foreach(area->used_space.leaf_list, cur) {
-		btree_node_t *node
-		    = list_get_instance(cur, btree_node_t, leaf_link);
+	list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
+	    node) {
 		btree_key_t i;
 		
@@ -1271,7 +1259,6 @@
 	size_t frame_idx = 0;
 	
-	list_foreach(area->used_space.leaf_list, cur) {
-		btree_node_t *node = list_get_instance(cur, btree_node_t,
-		    leaf_link);
+	list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
+	    node) {
 		btree_key_t i;
 		
@@ -1323,7 +1310,6 @@
 	frame_idx = 0;
 	
-	list_foreach(area->used_space.leaf_list, cur) {
-		btree_node_t *node
-		    = list_get_instance(cur, btree_node_t, leaf_link);
+	list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
+	    node) {
 		btree_key_t i;
 		
@@ -2189,7 +2175,6 @@
 	size_t area_cnt = 0;
 	
-	list_foreach(as->as_area_btree.leaf_list, cur) {
-		btree_node_t *node =
-		    list_get_instance(cur, btree_node_t, leaf_link);
+	list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
+	    node) {
 		area_cnt += node->keys;
 	}
@@ -2202,7 +2187,6 @@
 	size_t area_idx = 0;
 	
-	list_foreach(as->as_area_btree.leaf_list, cur) {
-		btree_node_t *node =
-		    list_get_instance(cur, btree_node_t, leaf_link);
+	list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
+	    node) {
 		btree_key_t i;
 		
@@ -2238,7 +2222,6 @@
 	
 	/* Print out info about address space areas */
-	list_foreach(as->as_area_btree.leaf_list, cur) {
-		btree_node_t *node
-		    = list_get_instance(cur, btree_node_t, leaf_link);
+	list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
+	    node) {
 		btree_key_t i;
 		
Index: kernel/generic/src/mm/backend_anon.c
===================================================================
--- kernel/generic/src/mm/backend_anon.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/mm/backend_anon.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -118,9 +118,8 @@
 	 */
 	mutex_lock(&area->sh_info->lock);
-	list_foreach(area->used_space.leaf_list, cur) {
-		btree_node_t *node;
+	list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
+	    node) {
 		unsigned int i;
 		
-		node = list_get_instance(cur, btree_node_t, leaf_link);
 		for (i = 0; i < node->keys; i++) {
 			uintptr_t base = node->key[i];
@@ -295,5 +294,5 @@
 		 * the normal unreserving frame_free().
 		 */
-		frame_free(frame);
+		frame_free(frame, 1);
 	} else {
 		/*
@@ -302,5 +301,5 @@
 		 * manipulate the reserve or it would be given back twice.
 		 */
-		frame_free_noreserve(frame);
+		frame_free_noreserve(frame, 1);
 	}
 }
Index: kernel/generic/src/mm/backend_elf.c
===================================================================
--- kernel/generic/src/mm/backend_elf.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/mm/backend_elf.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -429,5 +429,5 @@
 			 * data.
 			 */
-			frame_free_noreserve(frame);
+			frame_free_noreserve(frame, 1);
 		}
 	} else {
@@ -437,5 +437,5 @@
 		 * anonymous). In any case, a frame needs to be freed.
 		 */
-		frame_free_noreserve(frame);
+		frame_free_noreserve(frame, 1);
 	}
 }
Index: rnel/generic/src/mm/buddy.c
===================================================================
--- kernel/generic/src/mm/buddy.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ 	(revision )
@@ -1,284 +1,0 @@
-/*
- * Copyright (c) 2005 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.
- */
-
-/** @addtogroup genericmm
- * @{
- */
-
-/**
- * @file
- * @brief	Buddy allocator framework.
- *
- * This file contains buddy system allocator framework.
- * Specialized functions are needed for this abstract framework to be useful.
- */
-
-#include <mm/buddy.h>
-#include <mm/frame.h>
-#include <typedefs.h>
-#include <debug.h>
-#include <print.h>
-#include <macros.h>
-
-/** Return size needed for the buddy configuration data. */
-size_t buddy_conf_size(size_t max_order)
-{
-	return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t);
-}
-
-
-/** Create buddy system.
- *
- * Allocate memory for and initialize new buddy system.
- *
- * @param b		Preallocated buddy system control data.
- * @param max_order	The biggest allocable size will be 2^max_order.
- * @param op		Operations for new buddy system.
- * @param data		Pointer to be used by implementation.
- *
- * @return		New buddy system.
- */
-void
-buddy_system_create(buddy_system_t *b, uint8_t max_order,
-    buddy_system_operations_t *op, void *data)
-{
-	int i;
-
-	ASSERT(max_order < BUDDY_SYSTEM_INNER_BLOCK);
-
-	ASSERT(op->find_buddy);
-	ASSERT(op->set_order);
-	ASSERT(op->get_order);
-	ASSERT(op->bisect);
-	ASSERT(op->coalesce);
-	ASSERT(op->mark_busy);
-
-	/*
-	 * Use memory after our own structure.
-	 */
-	b->order = (list_t *) (&b[1]);
-	
-	for (i = 0; i <= max_order; i++)
-		list_initialize(&b->order[i]);
-
-	b->max_order = max_order;
-	b->op = op;
-	b->data = data;
-}
-
-/** Check if buddy system can allocate block.
- *
- * @param b		Buddy system pointer.
- * @param i		Size of the block (2^i).
- *
- * @return		True if block can be allocated.
- */
-bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i)
-{
-	uint8_t k;
-	
-	/*
-	 * If requested block is greater then maximal block
-	 * we know immediatly that we cannot satisfy the request.
-	 */
-	if (i > b->max_order)
-		return false;
-
-	/*
-	 * Check if any bigger or equal order has free elements
-	 */
-	for (k = i; k <= b->max_order; k++) {
-		if (!list_empty(&b->order[k])) {
-			return true;
-		}
-	}
-	
-	return false;
-}
-
-/** Allocate PARTICULAR block from buddy system.
- *
- * @return		Block of data or NULL if no such block was found.
- */
-link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block)
-{
-	link_t *left,*right, *tmp;
-	uint8_t order;
-
-	left = b->op->find_block(b, block, BUDDY_SYSTEM_INNER_BLOCK);
-	ASSERT(left);
-	list_remove(left);
-	while (1) {
-		if (!b->op->get_order(b, left)) {
-			b->op->mark_busy(b, left);
-			return left;
-		}
-		
-		order = b->op->get_order(b, left);
-
-		right = b->op->bisect(b, left);
-		b->op->set_order(b, left, order - 1);
-		b->op->set_order(b, right, order - 1);
-
-		tmp = b->op->find_block(b, block, BUDDY_SYSTEM_INNER_BLOCK);
-
-		if (tmp == right) {
-			right = left;
-			left = tmp;
-		} 
-		ASSERT(tmp == left);
-		b->op->mark_busy(b, left);
-		buddy_system_free(b, right);
-		b->op->mark_available(b, left);
-	}
-}
-
-/** Allocate block from buddy system.
- *
- * @param b		Buddy system pointer.
- * @param i		Returned block will be 2^i big.
- *
- * @return		Block of data represented by link_t.
- */
-link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i)
-{
-	link_t *res, *hlp;
-
-	ASSERT(i <= b->max_order);
-
-	/*
-	 * If the list of order i is not empty,
-	 * the request can be immediatelly satisfied.
-	 */
-	res = list_first(&b->order[i]);
-	if (res != NULL) {
-		list_remove(res);
-		b->op->mark_busy(b, res);
-		return res;
-	}
-	/*
-	 * If order i is already the maximal order,
-	 * the request cannot be satisfied.
-	 */
-	if (i == b->max_order)
-		return NULL;
-
-	/*
-	 * Try to recursively satisfy the request from higher order lists.
-	 */	
-	hlp = buddy_system_alloc(b, i + 1);
-	
-	/*
-	 * The request could not be satisfied
-	 * from higher order lists.
-	 */
-	if (!hlp)
-		return NULL;
-		
-	res = hlp;
-	
-	/*
-	 * Bisect the block and set order of both of its parts to i.
-	 */
-	hlp = b->op->bisect(b, res);
-	b->op->set_order(b, res, i);
-	b->op->set_order(b, hlp, i);
-	
-	/*
-	 * Return the other half to buddy system. Mark the first part
-	 * full, so that it won't coalesce again.
-	 */
-	b->op->mark_busy(b, res);
-	buddy_system_free(b, hlp);
-	
-	return res;
-}
-
-/** Return block to buddy system.
- *
- * @param b		Buddy system pointer.
- * @param block		Block to return.
- */
-void buddy_system_free(buddy_system_t *b, link_t *block)
-{
-	link_t *buddy, *hlp;
-	uint8_t i;
-
-	/*
-	 * Determine block's order.
-	 */
-	i = b->op->get_order(b, block);
-
-	ASSERT(i <= b->max_order);
-
-	if (i != b->max_order) {
-		/*
-		 * See if there is any buddy in the list of order i.
-		 */
-		buddy = b->op->find_buddy(b, block);
-		if (buddy) {
-
-			ASSERT(b->op->get_order(b, buddy) == i);
-			/*
-			 * Remove buddy from the list of order i.
-			 */
-			list_remove(buddy);
-		
-			/*
-			 * Invalidate order of both block and buddy.
-			 */
-			b->op->set_order(b, block, BUDDY_SYSTEM_INNER_BLOCK);
-			b->op->set_order(b, buddy, BUDDY_SYSTEM_INNER_BLOCK);
-		
-			/*
-			 * Coalesce block and buddy into one block.
-			 */
-			hlp = b->op->coalesce(b, block, buddy);
-
-			/*
-			 * Set order of the coalesced block to i + 1.
-			 */
-			b->op->set_order(b, hlp, i + 1);
-
-			/*
-			 * Recursively add the coalesced block to the list of
-			 * order i + 1.
-			 */
-			buddy_system_free(b, hlp);
-			return;
-		}
-	}
-
-	/*
-	 * Insert block into the list of order i.
-	 */
-	list_append(block, &b->order[i]);
-}
-
-/** @}
- */
Index: kernel/generic/src/mm/frame.c
===================================================================
--- kernel/generic/src/mm/frame.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/mm/frame.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -38,7 +38,6 @@
  *
  * This file contains the physical frame allocator and memory zone management.
- * The frame allocator is built on top of the buddy allocator.
- *
- * @see buddy.c
+ * The frame allocator is built on top of the two-level bitmap structure.
+ *
  */
 
@@ -62,4 +61,6 @@
 #include <str.h>
 
+#define BITMAP_BLOCK_SIZE  1024
+
 zones_t zones;
 
@@ -92,9 +93,4 @@
 }
 
-NO_TRACE static inline size_t make_frame_index(zone_t *zone, frame_t *frame)
-{
-	return (frame - zone->frames);
-}
-
 /** Initialize frame structure.
  *
@@ -104,6 +100,6 @@
 NO_TRACE static void frame_initialize(frame_t *frame)
 {
-	frame->refcount = 1;
-	frame->buddy_order = 0;
+	frame->refcount = 0;
+	frame->parent = NULL;
 }
 
@@ -161,11 +157,6 @@
 	
 	/* Move other zones up */
-	size_t j;
-	for (j = zones.count; j > i; j--) {
+	for (size_t j = zones.count; j > i; j--)
 		zones.info[j] = zones.info[j - 1];
-		if (zones.info[j].buddy_system != NULL)
-			zones.info[j].buddy_system->data =
-			    (void *) &zones.info[j];
-	}
 	
 	zones.count++;
@@ -237,23 +228,31 @@
 }
 
-/** @return True if zone can allocate specified order */
-NO_TRACE static bool zone_can_alloc(zone_t *zone, uint8_t order)
-{
+/** @return True if zone can allocate specified number of frames */
+NO_TRACE static bool zone_can_alloc(zone_t *zone, size_t count,
+    pfn_t constraint)
+{
+	/*
+	 * The function bitmap_allocate_range() does not modify
+	 * the bitmap if the last argument is NULL.
+	 */
 	return ((zone->flags & ZONE_AVAILABLE) &&
-	    buddy_system_can_alloc(zone->buddy_system, order));
-}
-
-/** Find a zone that can allocate order frames.
+	    bitmap_allocate_range(&zone->bitmap, count, zone->base,
+	    constraint, NULL));
+}
+
+/** Find a zone that can allocate specified number of frames
  *
  * Assume interrupts are disabled and zones lock is
  * locked.
  *
- * @param order Size (2^order) of free space we are trying to find.
- * @param flags Required flags of the target zone.
- * @param hind  Preferred zone.
- *
- */
-NO_TRACE static size_t find_free_zone(uint8_t order, zone_flags_t flags,
-    size_t hint)
+ * @param count      Number of free frames we are trying to find.
+ * @param flags      Required flags of the target zone.
+ * @param constraint Indication of bits that cannot be set in the
+ *                   physical frame number of the first allocated frame.
+ * @param hind       Preferred zone.
+ *
+ */
+NO_TRACE static size_t find_free_zone(size_t count, zone_flags_t flags,
+    pfn_t constraint, size_t hint)
 {
 	if (hint >= zones.count)
@@ -267,7 +266,7 @@
 		if (ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) {
 			/*
-			 * Check if the zone has 2^order frames area available.
+			 * Check if the zone can satisfy the allocation request.
 			 */
-			if (zone_can_alloc(&zones.info[i], order))
+			if (zone_can_alloc(&zones.info[i], count, constraint))
 				return i;
 		}
@@ -282,169 +281,16 @@
 }
 
-/**************************/
-/* Buddy system functions */
-/**************************/
-
-/** Buddy system find_block implementation.
- *
- * Find block that is parent of current list.
- * That means go to lower addresses, until such block is found
- *
- * @param order Order of parent must be different then this
- *              parameter!!
- *
- */
-NO_TRACE static link_t *zone_buddy_find_block(buddy_system_t *buddy,
-    link_t *child, uint8_t order)
-{
-	frame_t *frame = list_get_instance(child, frame_t, buddy_link);
-	zone_t *zone = (zone_t *) buddy->data;
-	
-	size_t index = frame_index(zone, frame);
-	do {
-		if (zone->frames[index].buddy_order != order)
-			return &zone->frames[index].buddy_link;
-	} while (index-- > 0);
-	
-	return NULL;
-}
-
-/** Buddy system find_buddy implementation.
- *
- * @param buddy Buddy system.
- * @param block Block for which buddy should be found.
- *
- * @return Buddy for given block if found.
- *
- */
-NO_TRACE static link_t *zone_buddy_find_buddy(buddy_system_t *buddy,
-    link_t *block)
-{
-	frame_t *frame = list_get_instance(block, frame_t, buddy_link);
-	zone_t *zone = (zone_t *) buddy->data;
-	ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame),
-	    frame->buddy_order));
-	
-	bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
-	
-	size_t index;
-	if (is_left) {
-		index = (frame_index(zone, frame)) +
-		    (1 << frame->buddy_order);
-	} else {  /* is_right */
-		index = (frame_index(zone, frame)) -
-		    (1 << frame->buddy_order);
-	}
-	
-	if (frame_index_valid(zone, index)) {
-		if ((zone->frames[index].buddy_order == frame->buddy_order) &&
-		    (zone->frames[index].refcount == 0)) {
-			return &zone->frames[index].buddy_link;
-		}
-	}
-	
-	return NULL;
-}
-
-/** Buddy system bisect implementation.
- *
- * @param buddy Buddy system.
- * @param block Block to bisect.
- *
- * @return Right block.
- *
- */
-NO_TRACE static link_t *zone_buddy_bisect(buddy_system_t *buddy, link_t *block)
-{
-	frame_t *frame_l = list_get_instance(block, frame_t, buddy_link);
-	frame_t *frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
-	
-	return &frame_r->buddy_link;
-}
-
-/** Buddy system coalesce implementation.
- *
- * @param buddy   Buddy system.
- * @param block_1 First block.
- * @param block_2 First block's buddy.
- *
- * @return Coalesced block (actually block that represents lower
- *         address).
- *
- */
-NO_TRACE static link_t *zone_buddy_coalesce(buddy_system_t *buddy,
-    link_t *block_1, link_t *block_2)
-{
-	frame_t *frame1 = list_get_instance(block_1, frame_t, buddy_link);
-	frame_t *frame2 = list_get_instance(block_2, frame_t, buddy_link);
-	
-	return ((frame1 < frame2) ? block_1 : block_2);
-}
-
-/** Buddy system set_order implementation.
- *
- * @param buddy Buddy system.
- * @param block Buddy system block.
- * @param order Order to set.
- *
- */
-NO_TRACE static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block,
-    uint8_t order)
-{
-	list_get_instance(block, frame_t, buddy_link)->buddy_order = order;
-}
-
-/** Buddy system get_order implementation.
- *
- * @param buddy Buddy system.
- * @param block Buddy system block.
- *
- * @return Order of block.
- *
- */
-NO_TRACE static uint8_t zone_buddy_get_order(buddy_system_t *buddy,
-    link_t *block)
-{
-	return list_get_instance(block, frame_t, buddy_link)->buddy_order;
-}
-
-/** Buddy system mark_busy implementation.
- *
- * @param buddy Buddy system.
- * @param block Buddy system block.
- *
- */
-NO_TRACE static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t *block)
-{
-	list_get_instance(block, frame_t, buddy_link)->refcount = 1;
-}
-
-/** Buddy system mark_available implementation.
- *
- * @param buddy Buddy system.
- * @param block Buddy system block.
- *
- */
-NO_TRACE static void zone_buddy_mark_available(buddy_system_t *buddy,
-    link_t *block)
-{
-	list_get_instance(block, frame_t, buddy_link)->refcount = 0;
-}
-
-static buddy_system_operations_t zone_buddy_system_operations = {
-	.find_buddy = zone_buddy_find_buddy,
-	.bisect = zone_buddy_bisect,
-	.coalesce = zone_buddy_coalesce,
-	.set_order = zone_buddy_set_order,
-	.get_order = zone_buddy_get_order,
-	.mark_busy = zone_buddy_mark_busy,
-	.mark_available = zone_buddy_mark_available,
-	.find_block = zone_buddy_find_block
-};
-
 /******************/
 /* Zone functions */
 /******************/
 
+/** Return frame from zone. */
+NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t index)
+{
+	ASSERT(index < zone->count);
+	
+	return &zone->frames[index];
+}
+
 /** Allocate frame in particular zone.
  *
@@ -452,28 +298,37 @@
  * Panics if allocation is impossible.
  *
- * @param zone  Zone to allocate from.
- * @param order Allocate exactly 2^order frames.
+ * @param zone       Zone to allocate from.
+ * @param count      Number of frames to allocate
+ * @param constraint Indication of bits that cannot be set in the
+ *                   physical frame number of the first allocated frame.
  *
  * @return Frame index in zone.
  *
  */
-NO_TRACE static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
+NO_TRACE static size_t zone_frame_alloc(zone_t *zone, size_t count,
+    pfn_t constraint)
 {
 	ASSERT(zone->flags & ZONE_AVAILABLE);
 	
-	/* Allocate frames from zone buddy system */
-	link_t *link = buddy_system_alloc(zone->buddy_system, order);
-	
-	ASSERT(link);
+	/* Allocate frames from zone */
+	size_t index;
+	int avail = bitmap_allocate_range(&zone->bitmap, count, zone->base,
+	    constraint, &index);
+	
+	ASSERT(avail);
+	
+	/* Update frame reference count */
+	for (size_t i = 0; i < count; i++) {
+		frame_t *frame = zone_get_frame(zone, index + i);
+		
+		ASSERT(frame->refcount == 0);
+		frame->refcount = 1;
+	}
 	
 	/* Update zone information. */
-	zone->free_count -= (1 << order);
-	zone->busy_count += (1 << order);
-	
-	/* Frame will be actually a first frame of the block. */
-	frame_t *frame = list_get_instance(link, frame_t, buddy_link);
-	
-	/* Get frame address */
-	return make_frame_index(zone, frame);
+	zone->free_count -= count;
+	zone->busy_count += count;
+	
+	return index;
 }
 
@@ -482,54 +337,44 @@
  * Assume zone is locked and is available for deallocation.
  *
- * @param zone      Pointer to zone from which the frame is to be freed.
- * @param frame_idx Frame index relative to zone.
- *
- * @return          Number of freed frames.
- *
- */
-NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)
+ * @param zone  Pointer to zone from which the frame is to be freed.
+ * @param index Frame index relative to zone.
+ *
+ * @return Number of freed frames.
+ *
+ */
+NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t index)
 {
 	ASSERT(zone->flags & ZONE_AVAILABLE);
 	
-	frame_t *frame = &zone->frames[frame_idx];
-	size_t size = 0;
-	
-	ASSERT(frame->refcount);
+	frame_t *frame = zone_get_frame(zone, index);
+	
+	ASSERT(frame->refcount > 0);
 	
 	if (!--frame->refcount) {
-		size = 1 << frame->buddy_order;
-		buddy_system_free(zone->buddy_system, &frame->buddy_link);		
+		bitmap_free_range(&zone->bitmap, index, 1);
+		
 		/* Update zone information. */
-		zone->free_count += size;
-		zone->busy_count -= size;
-	}
-	
-	return size;
-}
-
-/** Return frame from zone. */
-NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t frame_idx)
-{
-	ASSERT(frame_idx < zone->count);
-	return &zone->frames[frame_idx];
+		zone->free_count++;
+		zone->busy_count--;
+		
+		return 1;
+	}
+	
+	return 0;
 }
 
 /** Mark frame in zone unavailable to allocation. */
-NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t frame_idx)
+NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t index)
 {
 	if (!(zone->flags & ZONE_AVAILABLE))
 		return;
-//	ASSERT(zone->flags & ZONE_AVAILABLE);
-	
-	frame_t *frame = zone_get_frame(zone, frame_idx);
-	if (frame->refcount)
+	
+	frame_t *frame = zone_get_frame(zone, index);
+	if (frame->refcount > 0)
 		return;
 	
-	link_t *link __attribute__ ((unused));
-	
-	link = buddy_system_alloc_block(zone->buddy_system,
-	    &frame->buddy_link);
-	
-	ASSERT(link);
+	frame->refcount = 1;
+	bitmap_set_range(&zone->bitmap, index, 1);
+	
 	zone->free_count--;
 	reserve_force_alloc(1);
@@ -538,16 +383,15 @@
 /** Merge two zones.
  *
- * Expect buddy to point to space at least zone_conf_size large.
  * Assume z1 & z2 are locked and compatible and zones lock is
  * locked.
  *
- * @param z1     First zone to merge.
- * @param z2     Second zone to merge.
- * @param old_z1 Original date of the first zone.
- * @param buddy  Merged zone buddy.
+ * @param z1       First zone to merge.
+ * @param z2       Second zone to merge.
+ * @param old_z1   Original data of the first zone.
+ * @param confdata Merged zone configuration data.
  *
  */
 NO_TRACE static void zone_merge_internal(size_t z1, size_t z2, zone_t *old_z1,
-    buddy_system_t *buddy)
+    void *confdata)
 {
 	ASSERT(zones.info[z1].flags & ZONE_AVAILABLE);
@@ -564,69 +408,27 @@
 	zones.info[z1].free_count += zones.info[z2].free_count;
 	zones.info[z1].busy_count += zones.info[z2].busy_count;
-	zones.info[z1].buddy_system = buddy;
-	
-	uint8_t order = fnzb(zones.info[z1].count);
-	buddy_system_create(zones.info[z1].buddy_system, order,
-	    &zone_buddy_system_operations, (void *) &zones.info[z1]);
-	
-	zones.info[z1].frames =
-	    (frame_t *) ((uint8_t *) zones.info[z1].buddy_system
-	    + buddy_conf_size(order));
-	
-	/* This marks all frames busy */
-	size_t i;
-	for (i = 0; i < zones.info[z1].count; i++)
-		frame_initialize(&zones.info[z1].frames[i]);
-	
-	/* Copy frames from both zones to preserve full frame orders,
-	 * parents etc. Set all free frames with refcount = 0 to 1, because
-	 * we add all free frames to buddy allocator later again, clearing
-	 * order to 0. Don't set busy frames with refcount = 0, as they
-	 * will not be reallocated during merge and it would make later
-	 * problems with allocation/free.
+	
+	bitmap_initialize(&zones.info[z1].bitmap, zones.info[z1].count,
+	    BITMAP_BLOCK_SIZE, confdata +
+	    (sizeof(frame_t) * zones.info[z1].count));
+	bitmap_clear_range(&zones.info[z1].bitmap, 0, zones.info[z1].count);
+	
+	zones.info[z1].frames = (frame_t *) confdata;
+	
+	/*
+	 * Copy frames and bits from both zones to preserve parents, etc.
 	 */
-	for (i = 0; i < old_z1->count; i++)
+	
+	for (size_t i = 0; i < old_z1->count; i++) {
+		bitmap_set(&zones.info[z1].bitmap, i,
+		    bitmap_get(&old_z1->bitmap, i));
 		zones.info[z1].frames[i] = old_z1->frames[i];
-	
-	for (i = 0; i < zones.info[z2].count; i++)
-		zones.info[z1].frames[base_diff + i]
-		    = zones.info[z2].frames[i];
-	
-	i = 0;
-	while (i < zones.info[z1].count) {
-		if (zones.info[z1].frames[i].refcount) {
-			/* Skip busy frames */
-			i += 1 << zones.info[z1].frames[i].buddy_order;
-		} else {
-			/* Free frames, set refcount = 1
-			 * (all free frames have refcount == 0, we need not
-			 * to check the order)
-			 */
-			zones.info[z1].frames[i].refcount = 1;
-			zones.info[z1].frames[i].buddy_order = 0;
-			i++;
-		}
-	}
-	
-	/* Add free blocks from the original zone z1 */
-	while (zone_can_alloc(old_z1, 0)) {
-		/* Allocate from the original zone */
-		pfn_t frame_idx = zone_frame_alloc(old_z1, 0);
-		
-		/* Free the frame from the merged zone */
-		frame_t *frame = &zones.info[z1].frames[frame_idx];
-		frame->refcount = 0;
-		buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
-	}
-	
-	/* Add free blocks from the original zone z2 */
-	while (zone_can_alloc(&zones.info[z2], 0)) {
-		/* Allocate from the original zone */
-		pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0);
-		
-		/* Free the frame from the merged zone */
-		frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx];
-		frame->refcount = 0;
-		buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
+	}
+	
+	for (size_t i = 0; i < zones.info[z2].count; i++) {
+		bitmap_set(&zones.info[z1].bitmap, base_diff + i,
+		    bitmap_get(&zones.info[z2].bitmap, i));
+		zones.info[z1].frames[base_diff + i] =
+		    zones.info[z2].frames[i];
 	}
 }
@@ -651,55 +453,11 @@
 	size_t cframes = SIZE2FRAMES(zone_conf_size(count));
 	
-	if ((pfn < zones.info[znum].base)
-	    || (pfn >= zones.info[znum].base + zones.info[znum].count))
+	if ((pfn < zones.info[znum].base) ||
+	    (pfn >= zones.info[znum].base + zones.info[znum].count))
 		return;
 	
-	frame_t *frame __attribute__ ((unused));
-
-	frame = &zones.info[znum].frames[pfn - zones.info[znum].base];
-	ASSERT(!frame->buddy_order);
-	
-	size_t i;
-	for (i = 0; i < cframes; i++) {
-		zones.info[znum].busy_count++;
+	for (size_t i = 0; i < cframes; i++)
 		(void) zone_frame_free(&zones.info[znum],
 		    pfn - zones.info[znum].base + i);
-	}
-}
-
-/** Reduce allocated block to count of order 0 frames.
- *
- * The allocated block needs 2^order frames. Reduce all frames
- * in the block to order 0 and free the unneeded frames. This means that
- * when freeing the previously allocated block starting with frame_idx,
- * you have to free every frame.
- *
- * @param znum      Zone.
- * @param frame_idx Index the first frame of the block.
- * @param count     Allocated frames in block.
- *
- */
-NO_TRACE static void zone_reduce_region(size_t znum, pfn_t frame_idx,
-    size_t count)
-{
-	ASSERT(zones.info[znum].flags & ZONE_AVAILABLE);
-	ASSERT(frame_idx + count < zones.info[znum].count);
-	
-	uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;
-	ASSERT((size_t) (1 << order) >= count);
-	
-	/* Reduce all blocks to order 0 */
-	size_t i;
-	for (i = 0; i < (size_t) (1 << order); i++) {
-		frame_t *frame = &zones.info[znum].frames[i + frame_idx];
-		frame->buddy_order = 0;
-		if (!frame->refcount)
-			frame->refcount = 1;
-		ASSERT(frame->refcount == 1);
-	}
-	
-	/* Free unneeded frames */
-	for (i = count; i < (size_t) (1 << order); i++)
-		(void) zone_frame_free(&zones.info[znum], i + frame_idx);
 }
 
@@ -721,5 +479,6 @@
 	bool ret = true;
 	
-	/* We can join only 2 zones with none existing inbetween,
+	/*
+	 * We can join only 2 zones with none existing inbetween,
 	 * the zones have to be available and with the same
 	 * set of flags
@@ -735,16 +494,12 @@
 	    + zones.info[z2].count));
 	
-	uint8_t order;
-	if (cframes == 1)
-		order = 0;
-	else
-		order = fnzb(cframes - 1) + 1;
-	
 	/* Allocate merged zone data inside one of the zones */
 	pfn_t pfn;
-	if (zone_can_alloc(&zones.info[z1], order)) {
-		pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order);
-	} else if (zone_can_alloc(&zones.info[z2], order)) {
-		pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order);
+	if (zone_can_alloc(&zones.info[z1], cframes, 0)) {
+		pfn = zones.info[z1].base +
+		    zone_frame_alloc(&zones.info[z1], cframes, 0);
+	} else if (zone_can_alloc(&zones.info[z2], cframes, 0)) {
+		pfn = zones.info[z2].base +
+		    zone_frame_alloc(&zones.info[z2], cframes, 0);
 	} else {
 		ret = false;
@@ -754,12 +509,7 @@
 	/* Preserve original data from z1 */
 	zone_t old_z1 = zones.info[z1];
-	old_z1.buddy_system->data = (void *) &old_z1;
 	
 	/* Do zone merging */
-	buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn));
-	zone_merge_internal(z1, z2, &old_z1, buddy);
-	
-	/* Free unneeded config frames */
-	zone_reduce_region(z1, pfn - zones.info[z1].base, cframes);
+	zone_merge_internal(z1, z2, &old_z1, (void *) PA2KA(PFN2ADDR(pfn)));
 	
 	/* Subtract zone information from busy frames */
@@ -774,11 +524,6 @@
 	
 	/* Move zones down */
-	size_t i;
-	for (i = z2 + 1; i < zones.count; i++) {
+	for (size_t i = z2 + 1; i < zones.count; i++)
 		zones.info[i - 1] = zones.info[i];
-		if (zones.info[i - 1].buddy_system != NULL)
-			zones.info[i - 1].buddy_system->data =
-			    (void *) &zones.info[i - 1];
-	}
 	
 	zones.count--;
@@ -799,7 +544,8 @@
 void zone_merge_all(void)
 {
-	size_t i = 0;
+	size_t i = 1;
+	
 	while (i < zones.count) {
-		if (!zone_merge(i, i + 1))
+		if (!zone_merge(i - 1, i))
 			i++;
 	}
@@ -808,15 +554,15 @@
 /** Create new frame zone.
  *
- * @param zone  Zone to construct.
- * @param buddy Address of buddy system configuration information.
- * @param start Physical address of the first frame within the zone.
- * @param count Count of frames in zone.
- * @param flags Zone flags.
+ * @param zone     Zone to construct.
+ * @param start    Physical address of the first frame within the zone.
+ * @param count    Count of frames in zone.
+ * @param flags    Zone flags.
+ * @param confdata Configuration data of the zone.
  *
  * @return Initialized zone.
  *
  */
-NO_TRACE static void zone_construct(zone_t *zone, buddy_system_t *buddy,
-    pfn_t start, size_t count, zone_flags_t flags)
+NO_TRACE static void zone_construct(zone_t *zone, pfn_t start, size_t count,
+    zone_flags_t flags, void *confdata)
 {
 	zone->base = start;
@@ -825,31 +571,27 @@
 	zone->free_count = count;
 	zone->busy_count = 0;
-	zone->buddy_system = buddy;
 	
 	if (flags & ZONE_AVAILABLE) {
 		/*
-		 * Compute order for buddy system and initialize
+		 * Initialize frame bitmap (located after the array of
+		 * frame_t structures in the configuration space).
 		 */
-		uint8_t order = fnzb(count);
-		buddy_system_create(zone->buddy_system, order,
-		    &zone_buddy_system_operations, (void *) zone);
-		
-		/* Allocate frames _after_ the confframe */
-		
-		/* Check sizes */
-		zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +
-		    buddy_conf_size(order));
-		
-		size_t i;
-		for (i = 0; i < count; i++)
+		
+		bitmap_initialize(&zone->bitmap, count, BITMAP_BLOCK_SIZE,
+		    confdata + (sizeof(frame_t) * count));
+		bitmap_clear_range(&zone->bitmap, 0, count);
+		
+		/*
+		 * Initialize the array of frame_t structures.
+		 */
+		
+		zone->frames = (frame_t *) confdata;
+		
+		for (size_t i = 0; i < count; i++)
 			frame_initialize(&zone->frames[i]);
-		
-		/* Stuffing frames */
-		for (i = 0; i < count; i++) {
-			zone->frames[i].refcount = 0;
-			buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link);
-		}
-	} else
+	} else {
+		bitmap_initialize(&zone->bitmap, 0, 0, NULL);
 		zone->frames = NULL;
+	}
 }
 
@@ -863,5 +605,6 @@
 size_t zone_conf_size(size_t count)
 {
-	return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
+	return (count * sizeof(frame_t) +
+	    bitmap_size(count, BITMAP_BLOCK_SIZE));
 }
 
@@ -869,9 +612,8 @@
 pfn_t zone_external_conf_alloc(size_t count)
 {
-	size_t size = zone_conf_size(count);
-	size_t order = ispwr2(size) ? fnzb(size) : (fnzb(size) + 1);
-
-	return ADDR2PFN((uintptr_t) frame_alloc(order - FRAME_WIDTH,
-	    FRAME_LOWMEM | FRAME_ATOMIC));
+	size_t frames = SIZE2FRAMES(zone_conf_size(count));
+	
+	return ADDR2PFN((uintptr_t)
+	    frame_alloc(frames, FRAME_LOWMEM | FRAME_ATOMIC, 0));
 }
 
@@ -881,5 +623,5 @@
  * @param count     Size of zone in frames.
  * @param confframe Where configuration frames are supposed to be.
- *                  Automatically checks, that we will not disturb the
+ *                  Automatically checks that we will not disturb the
  *                  kernel and possibly init. If confframe is given
  *                  _outside_ this zone, it is expected, that the area is
@@ -898,17 +640,20 @@
 	
 	if (flags & ZONE_AVAILABLE) {  /* Create available zone */
-		/* Theoretically we could have NULL here, practically make sure
+		/*
+		 * Theoretically we could have NULL here, practically make sure
 		 * nobody tries to do that. If some platform requires, remove
 		 * the assert
 		 */
 		ASSERT(confframe != ADDR2PFN((uintptr_t ) NULL));
-
+		
 		/* Update the known end of physical memory. */
 		config.physmem_end = max(config.physmem_end, PFN2ADDR(start + count));
 		
-		/* If confframe is supposed to be inside our zone, then make sure
+		/*
+		 * If confframe is supposed to be inside our zone, then make sure
 		 * it does not span kernel & init
 		 */
 		size_t confcount = SIZE2FRAMES(zone_conf_size(count));
+		
 		if ((confframe >= start) && (confframe < start + count)) {
 			for (; confframe < start + count; confframe++) {
@@ -923,6 +668,5 @@
 				
 				bool overlap = false;
-				size_t i;
-				for (i = 0; i < init.cnt; i++)
+				for (size_t i = 0; i < init.cnt; i++) {
 					if (overlaps(addr, PFN2ADDR(confcount),
 					    init.tasks[i].paddr,
@@ -931,4 +675,6 @@
 						break;
 					}
+				}
+				
 				if (overlap)
 					continue;
@@ -937,9 +683,6 @@
 			}
 			
-			if (confframe >= start + count) {
-				flags &= ~ZONE_AVAILABLE;
-				goto nonavail;
-//				panic("Cannot find configuration data for zone.");
-			}
+			if (confframe >= start + count)
+				panic("Cannot find configuration data for zone.");
 		}
 		
@@ -950,11 +693,10 @@
 		}
 		
-		buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe));
-		zone_construct(&zones.info[znum], buddy, start, count, flags);
+		void *confdata = (void *) PA2KA(PFN2ADDR(confframe));
+		zone_construct(&zones.info[znum], start, count, flags, confdata);
 		
 		/* If confdata in zone, mark as unavailable */
 		if ((confframe >= start) && (confframe < start + count)) {
-			size_t i;
-			for (i = confframe; i < confframe + confcount; i++)
+			for (size_t i = confframe; i < confframe + confcount; i++)
 				zone_mark_unavailable(&zones.info[znum],
 				    i - zones.info[znum].base);
@@ -965,6 +707,5 @@
 		return znum;
 	}
-nonavail:
-	(void)0; // label trick
+	
 	/* Non-available zone */
 	size_t znum = zones_insert_zone(start, count, flags);
@@ -973,5 +714,6 @@
 		return (size_t) -1;
 	}
-	zone_construct(&zones.info[znum], NULL, start, count, flags);
+	
+	zone_construct(&zones.info[znum], start, count, flags, NULL);
 	
 	irq_spinlock_unlock(&zones.lock, true);
@@ -1015,24 +757,29 @@
 }
 
-/** Allocate power-of-two frames of physical memory.
- *
- * @param order Allocate exactly 2^order frames.
- * @param flags Flags for host zone selection and address processing.
- * @param pzone Preferred zone.
+/** Allocate frames of physical memory.
+ *
+ * @param count      Number of continuous frames to allocate.
+ * @param flags      Flags for host zone selection and address processing.
+ * @param constraint Indication of physical address bits that cannot be
+ *                   set in the address of the first allocated frame.
+ * @param pzone      Preferred zone.
  *
  * @return Physical address of the allocated frame.
  *
  */
-void *frame_alloc_generic(uint8_t order, frame_flags_t flags, size_t *pzone)
-{
-	size_t size = ((size_t) 1) << order;
+uintptr_t frame_alloc_generic(size_t count, frame_flags_t flags,
+    uintptr_t constraint, size_t *pzone)
+{
+	ASSERT(count > 0);
+	
 	size_t hint = pzone ? (*pzone) : 0;
+	pfn_t frame_constraint = ADDR2PFN(constraint);
 	
 	/*
 	 * If not told otherwise, we must first reserve the memory.
 	 */
-	if (!(flags & FRAME_NO_RESERVE)) 
-		reserve_force_alloc(size);
-
+	if (!(flags & FRAME_NO_RESERVE))
+		reserve_force_alloc(count);
+	
 loop:
 	irq_spinlock_lock(&zones.lock, true);
@@ -1041,9 +788,11 @@
 	 * First, find suitable frame zone.
 	 */
-	size_t znum = find_free_zone(order,
-	    FRAME_TO_ZONE_FLAGS(flags), hint);
-	
-	/* If no memory, reclaim some slab memory,
-	   if it does not help, reclaim all */
+	size_t znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
+	    frame_constraint, hint);
+	
+	/*
+	 * If no memory, reclaim some slab memory,
+	 * if it does not help, reclaim all.
+	 */
 	if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
 		irq_spinlock_unlock(&zones.lock, true);
@@ -1052,6 +801,6 @@
 		
 		if (freed > 0)
-			znum = find_free_zone(order,
-			    FRAME_TO_ZONE_FLAGS(flags), hint);
+			znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
+			    frame_constraint, hint);
 		
 		if (znum == (size_t) -1) {
@@ -1061,6 +810,6 @@
 			
 			if (freed > 0)
-				znum = find_free_zone(order,
-				    FRAME_TO_ZONE_FLAGS(flags), hint);
+				znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
+				    frame_constraint, hint);
 		}
 	}
@@ -1069,7 +818,9 @@
 		if (flags & FRAME_ATOMIC) {
 			irq_spinlock_unlock(&zones.lock, true);
+			
 			if (!(flags & FRAME_NO_RESERVE))
-				reserve_free(size);
-			return NULL;
+				reserve_free(count);
+			
+			return 0;
 		}
 		
@@ -1081,5 +832,6 @@
 		
 		if (!THREAD)
-			panic("Cannot wait for memory to become available.");
+			panic("Cannot wait for %zu frames to become available "
+			    "(%zu available).", count, avail);
 		
 		/*
@@ -1088,11 +840,11 @@
 		
 #ifdef CONFIG_DEBUG
-		printf("Thread %" PRIu64 " waiting for %zu frames, "
-		    "%zu available.\n", THREAD->tid, size, avail);
+		printf("Thread %" PRIu64 " waiting for %zu frames "
+		    "(%zu available).\n", THREAD->tid, count, avail);
 #endif
 		
 		/*
-		 * Since the mem_avail_mtx is an active mutex, we need to disable interrupts
-		 * to prevent deadlock with TLB shootdown.
+		 * Since the mem_avail_mtx is an active mutex, we need to
+		 * disable interrupts to prevent deadlock with TLB shootdown.
 		 */
 		ipl_t ipl = interrupts_disable();
@@ -1100,7 +852,8 @@
 		
 		if (mem_avail_req > 0)
-			mem_avail_req = min(mem_avail_req, size);
+			mem_avail_req = min(mem_avail_req, count);
 		else
-			mem_avail_req = size;
+			mem_avail_req = count;
+		
 		size_t gen = mem_avail_gen;
 		
@@ -1118,6 +871,6 @@
 	}
 	
-	pfn_t pfn = zone_frame_alloc(&zones.info[znum], order)
-	    + zones.info[znum].base;
+	pfn_t pfn = zone_frame_alloc(&zones.info[znum], count,
+	    frame_constraint) + zones.info[znum].base;
 	
 	irq_spinlock_unlock(&zones.lock, true);
@@ -1126,45 +879,48 @@
 		*pzone = znum;
 	
-	if (flags & FRAME_KA)
-		return (void *) PA2KA(PFN2ADDR(pfn));
-	
-	return (void *) PFN2ADDR(pfn);
-}
-
-void *frame_alloc(uint8_t order, frame_flags_t flags)
-{
-	return frame_alloc_generic(order, flags, NULL);
-}
-
-void *frame_alloc_noreserve(uint8_t order, frame_flags_t flags)
-{
-	return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, NULL);
-}
-
-/** Free a frame.
- *
- * Find respective frame structure for supplied physical frame address.
- * Decrement frame reference count. If it drops to zero, move the frame
- * structure to free list.
- *
- * @param frame Physical Address of of the frame to be freed.
+	return PFN2ADDR(pfn);
+}
+
+uintptr_t frame_alloc(size_t count, frame_flags_t flags, uintptr_t constraint)
+{
+	return frame_alloc_generic(count, flags, constraint, NULL);
+}
+
+uintptr_t frame_alloc_noreserve(size_t count, frame_flags_t flags,
+    uintptr_t constraint)
+{
+	return frame_alloc_generic(count, flags | FRAME_NO_RESERVE, constraint,
+	    NULL);
+}
+
+/** Free frames of physical memory.
+ *
+ * Find respective frame structures for supplied physical frames.
+ * Decrement each frame reference count. If it drops to zero, mark
+ * the frames as available.
+ *
+ * @param start Physical Address of the first frame to be freed.
+ * @param count Number of frames to free.
  * @param flags Flags to control memory reservation.
  *
  */
-void frame_free_generic(uintptr_t frame, frame_flags_t flags)
-{
-	size_t size;
+void frame_free_generic(uintptr_t start, size_t count, frame_flags_t flags)
+{
+	size_t freed = 0;
 	
 	irq_spinlock_lock(&zones.lock, true);
 	
-	/*
-	 * First, find host frame zone for addr.
-	 */
-	pfn_t pfn = ADDR2PFN(frame);
-	size_t znum = find_zone(pfn, 1, 0);
-
-	ASSERT(znum != (size_t) -1);
-	
-	size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
+	for (size_t i = 0; i < count; i++) {
+		/*
+		 * First, find host frame zone for addr.
+		 */
+		pfn_t pfn = ADDR2PFN(start) + i;
+		size_t znum = find_zone(pfn, 1, 0);
+		
+		ASSERT(znum != (size_t) -1);
+		
+		freed += zone_frame_free(&zones.info[znum],
+		    pfn - zones.info[znum].base);
+	}
 	
 	irq_spinlock_unlock(&zones.lock, true);
@@ -1172,15 +928,14 @@
 	/*
 	 * Signal that some memory has been freed.
+	 * Since the mem_avail_mtx is an active mutex,
+	 * we need to disable interruptsto prevent deadlock
+	 * with TLB shootdown.
 	 */
-
-	
-	/*
-	 * Since the mem_avail_mtx is an active mutex, we need to disable interrupts
-	 * to prevent deadlock with TLB shootdown.
-	 */
+	
 	ipl_t ipl = interrupts_disable();
 	mutex_lock(&mem_avail_mtx);
+	
 	if (mem_avail_req > 0)
-		mem_avail_req -= min(mem_avail_req, size);
+		mem_avail_req -= min(mem_avail_req, freed);
 	
 	if (mem_avail_req == 0) {
@@ -1188,19 +943,20 @@
 		condvar_broadcast(&mem_avail_cv);
 	}
+	
 	mutex_unlock(&mem_avail_mtx);
 	interrupts_restore(ipl);
 	
 	if (!(flags & FRAME_NO_RESERVE))
-		reserve_free(size);
-}
-
-void frame_free(uintptr_t frame)
-{
-	frame_free_generic(frame, 0);
-}
-
-void frame_free_noreserve(uintptr_t frame)
-{
-	frame_free_generic(frame, FRAME_NO_RESERVE);
+		reserve_free(freed);
+}
+
+void frame_free(uintptr_t frame, size_t count)
+{
+	frame_free_generic(frame, count, 0);
+}
+
+void frame_free_noreserve(uintptr_t frame, size_t count)
+{
+	frame_free_generic(frame, count, FRAME_NO_RESERVE);
 }
 
@@ -1236,7 +992,7 @@
 	irq_spinlock_lock(&zones.lock, true);
 	
-	size_t i;
-	for (i = 0; i < count; i++) {
+	for (size_t i = 0; i < count; i++) {
 		size_t znum = find_zone(start + i, 1, 0);
+		
 		if (znum == (size_t) -1)  /* PFN not found */
 			continue;
@@ -1263,4 +1019,5 @@
 	/* Tell the architecture to create some memory */
 	frame_low_arch_init();
+	
 	if (config.cpu_active == 1) {
 		frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
@@ -1269,10 +1026,7 @@
 		    SIZE2FRAMES(config.stack_size));
 		
-		size_t i;
-		for (i = 0; i < init.cnt; i++) {
-			pfn_t pfn = ADDR2PFN(init.tasks[i].paddr);
-			frame_mark_unavailable(pfn,
+		for (size_t i = 0; i < init.cnt; i++)
+			frame_mark_unavailable(ADDR2PFN(init.tasks[i].paddr),
 			    SIZE2FRAMES(init.tasks[i].size));
-		}
 		
 		if (ballocs.size)
@@ -1280,9 +1034,11 @@
 			    SIZE2FRAMES(ballocs.size));
 		
-		/* Black list first frame, as allocating NULL would
+		/*
+		 * Blacklist first frame, as allocating NULL would
 		 * fail in some places
 		 */
 		frame_mark_unavailable(0, 1);
 	}
+	
 	frame_high_arch_init();
 }
@@ -1290,21 +1046,24 @@
 /** Adjust bounds of physical memory region according to low/high memory split.
  *
- * @param low[in]	If true, the adjustment is performed to make the region
- *			fit in the low memory. Otherwise the adjustment is
- *			performed to make the region fit in the high memory.
- * @param basep[inout]	Pointer to a variable which contains the region's base
- *			address and which may receive the adjusted base address.
- * @param sizep[inout]	Pointer to a variable which contains the region's size
- *			and which may receive the adjusted size.
- * @retun		True if the region still exists even after the
- *			adjustment, false otherwise.
+ * @param low[in]      If true, the adjustment is performed to make the region
+ *                     fit in the low memory. Otherwise the adjustment is
+ *                     performed to make the region fit in the high memory.
+ * @param basep[inout] Pointer to a variable which contains the region's base
+ *                     address and which may receive the adjusted base address.
+ * @param sizep[inout] Pointer to a variable which contains the region's size
+ *                     and which may receive the adjusted size.
+ *
+ * @return True if the region still exists even after the adjustment.
+ * @return False otherwise.
+ *
  */
 bool frame_adjust_zone_bounds(bool low, uintptr_t *basep, size_t *sizep)
 {
 	uintptr_t limit = KA2PA(config.identity_base) + config.identity_size;
-
+	
 	if (low) {
 		if (*basep > limit)
 			return false;
+		
 		if (*basep + *sizep > limit)
 			*sizep = limit - *basep;
@@ -1312,4 +1071,5 @@
 		if (*basep + *sizep <= limit)
 			return false;
+		
 		if (*basep <= limit) {
 			*sizep -= limit - *basep;
@@ -1317,4 +1077,5 @@
 		}
 	}
+	
 	return true;
 }
@@ -1328,6 +1089,6 @@
 	
 	uint64_t total = 0;
-	size_t i;
-	for (i = 0; i < zones.count; i++)
+	
+	for (size_t i = 0; i < zones.count; i++)
 		total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
 	
@@ -1352,6 +1113,5 @@
 	*free = 0;
 	
-	size_t i;
-	for (i = 0; i < zones.count; i++) {
+	for (size_t i = 0; i < zones.count; i++) {
 		*total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
 		
@@ -1390,6 +1150,5 @@
 	 */
 	
-	size_t i;
-	for (i = 0;; i++) {
+	for (size_t i = 0;; i++) {
 		irq_spinlock_lock(&zones.lock, true);
 		
@@ -1444,6 +1203,5 @@
 	size_t znum = (size_t) -1;
 	
-	size_t i;
-	for (i = 0; i < zones.count; i++) {
+	for (size_t i = 0; i < zones.count; i++) {
 		if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
 			znum = i;
@@ -1458,9 +1216,9 @@
 	}
 	
-	uintptr_t base = PFN2ADDR(zones.info[i].base);
-	zone_flags_t flags = zones.info[i].flags;
-	size_t count = zones.info[i].count;
-	size_t free_count = zones.info[i].free_count;
-	size_t busy_count = zones.info[i].busy_count;
+	uintptr_t base = PFN2ADDR(zones.info[znum].base);
+	zone_flags_t flags = zones.info[znum].flags;
+	size_t count = zones.info[znum].count;
+	size_t free_count = zones.info[znum].free_count;
+	size_t busy_count = zones.info[znum].busy_count;
 	
 	irq_spinlock_unlock(&zones.lock, true);
Index: kernel/generic/src/mm/km.c
===================================================================
--- kernel/generic/src/mm/km.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/mm/km.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -239,30 +239,30 @@
 uintptr_t km_temporary_page_get(uintptr_t *framep, frame_flags_t flags)
 {
-	uintptr_t frame;
-	uintptr_t page;
-
 	ASSERT(THREAD);
 	ASSERT(framep);
 	ASSERT(!(flags & ~(FRAME_NO_RESERVE | FRAME_ATOMIC)));
-
+	
 	/*
 	 * Allocate a frame, preferably from high memory.
 	 */
-	frame = (uintptr_t) frame_alloc(ONE_FRAME,
-	    FRAME_HIGHMEM | FRAME_ATOMIC | flags); 
+	uintptr_t page;
+	uintptr_t frame =
+	    frame_alloc(1, FRAME_HIGHMEM | FRAME_ATOMIC | flags, 0);
 	if (frame) {
 		page = km_map(frame, PAGE_SIZE,
 		    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
-		ASSERT(page);	// FIXME
+		
+		// FIXME
+		ASSERT(page);
 	} else {
-		frame = (uintptr_t) frame_alloc(ONE_FRAME,
-		    FRAME_LOWMEM | flags);
+		frame = frame_alloc(1, FRAME_LOWMEM | flags, 0);
 		if (!frame)
 			return (uintptr_t) NULL;
+		
 		page = PA2KA(frame);
 	}
-
+	
 	*framep = frame;
-	return page;	
+	return page;
 }
 
Index: kernel/generic/src/mm/page.c
===================================================================
--- kernel/generic/src/mm/page.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/mm/page.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -169,5 +169,5 @@
 }
 
-int page_find_mapping(uintptr_t virt, void **phys)
+int page_find_mapping(uintptr_t virt, uintptr_t *phys)
 {
 	page_table_lock(AS, true);
@@ -179,5 +179,5 @@
 	}
 	
-	*phys = (void *) PTE_GET_FRAME(pte) +
+	*phys = PTE_GET_FRAME(pte) +
 	    (virt - ALIGN_DOWN(virt, PAGE_SIZE));
 	
@@ -193,7 +193,7 @@
  *
  */
-sysarg_t sys_page_find_mapping(uintptr_t virt, void *phys_ptr)
-{
-	void *phys;
+sysarg_t sys_page_find_mapping(uintptr_t virt, uintptr_t *phys_ptr)
+{
+	uintptr_t phys;
 	int rc = page_find_mapping(virt, &phys);
 	if (rc != EOK)
Index: kernel/generic/src/mm/slab.c
===================================================================
--- kernel/generic/src/mm/slab.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/mm/slab.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -182,8 +182,10 @@
 	size_t zone = 0;
 	
-	void *data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
-	if (!data) {
+	uintptr_t data_phys =
+	    frame_alloc_generic(cache->frames, flags, 0, &zone);
+	if (!data_phys)
 		return NULL;
-	}
+	
+	void *data = (void *) PA2KA(data_phys);
 	
 	slab_t *slab;
@@ -193,9 +195,9 @@
 		slab = slab_alloc(slab_extern_cache, flags);
 		if (!slab) {
-			frame_free(KA2PA(data));
+			frame_free(KA2PA(data), cache->frames);
 			return NULL;
 		}
 	} else {
-		fsize = (PAGE_SIZE << cache->order);
+		fsize = FRAMES2SIZE(cache->frames);
 		slab = data + fsize - sizeof(*slab);
 	}
@@ -203,5 +205,5 @@
 	/* Fill in slab structures */
 	size_t i;
-	for (i = 0; i < ((size_t) 1 << cache->order); i++)
+	for (i = 0; i < cache->frames; i++)
 		frame_set_parent(ADDR2PFN(KA2PA(data)) + i, slab, zone);
 	
@@ -225,5 +227,5 @@
 NO_TRACE static size_t slab_space_free(slab_cache_t *cache, slab_t *slab)
 {
-	frame_free(KA2PA(slab->start));
+	frame_free(KA2PA(slab->start), slab->cache->frames);
 	if (!(cache->flags & SLAB_CACHE_SLINSIDE))
 		slab_free(slab_extern_cache, slab);
@@ -231,5 +233,5 @@
 	atomic_dec(&cache->allocated_slabs);
 	
-	return (1 << cache->order);
+	return cache->frames;
 }
 
@@ -558,8 +560,8 @@
 {
 	if (cache->flags & SLAB_CACHE_SLINSIDE)
-		return ((PAGE_SIZE << cache->order)
-		    - sizeof(slab_t)) / cache->size;
+		return (FRAMES2SIZE(cache->frames) - sizeof(slab_t)) /
+		    cache->size;
 	else
-		return (PAGE_SIZE << cache->order) / cache->size;
+		return FRAMES2SIZE(cache->frames) / cache->size;
 }
 
@@ -570,5 +572,5 @@
 {
 	size_t objects = comp_objects(cache);
-	size_t ssize = PAGE_SIZE << cache->order;
+	size_t ssize = FRAMES2SIZE(cache->frames);
 	
 	if (cache->flags & SLAB_CACHE_SLINSIDE)
@@ -634,15 +636,9 @@
 		cache->flags |= SLAB_CACHE_SLINSIDE;
 	
-	/* Minimum slab order */
-	size_t pages = SIZE2FRAMES(cache->size);
-	
-	/* We need the 2^order >= pages */
-	if (pages == 1)
-		cache->order = 0;
-	else
-		cache->order = fnzb(pages - 1) + 1;
+	/* Minimum slab frames */
+	cache->frames = SIZE2FRAMES(cache->size);
 	
 	while (badness(cache) > SLAB_MAX_BADNESS(cache))
-		cache->order += 1;
+		cache->frames <<= 1;
 	
 	cache->objects = comp_objects(cache);
@@ -810,6 +806,5 @@
 	
 	size_t frames = 0;
-	list_foreach(slab_cache_list, cur) {
-		slab_cache_t *cache = list_get_instance(cur, slab_cache_t, link);
+	list_foreach(slab_cache_list, link, slab_cache_t, cache) {
 		frames += _slab_reclaim(cache, flags);
 	}
@@ -871,5 +866,5 @@
 		
 		const char *name = cache->name;
-		uint8_t order = cache->order;
+		size_t frames = cache->frames;
 		size_t size = cache->size;
 		size_t objects = cache->objects;
@@ -881,6 +876,6 @@
 		irq_spinlock_unlock(&slab_cache_lock, true);
 		
-		printf("%-18s %8zu %8u %8zu %8ld %8ld %8ld %-5s\n",
-		    name, size, (1 << order), objects, allocated_slabs,
+		printf("%-18s %8zu %8zu %8zu %8ld %8ld %8ld %-5s\n",
+		    name, size, frames, objects, allocated_slabs,
 		    cached_objs, allocated_objs,
 		    flags & SLAB_CACHE_SLINSIDE ? "in" : "out");
@@ -936,6 +931,5 @@
 	irq_spinlock_lock(&slab_cache_lock, false);
 	
-	list_foreach(slab_cache_list, cur) {
-		slab_cache_t *slab = list_get_instance(cur, slab_cache_t, link);
+	list_foreach(slab_cache_list, link, slab_cache_t, slab) {
 		if ((slab->flags & SLAB_CACHE_MAGDEFERRED) !=
 		    SLAB_CACHE_MAGDEFERRED)
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/proc/scheduler.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -739,7 +739,6 @@
 			
 			printf("\trq[%u]: ", i);
-			list_foreach(cpus[cpu].rq[i].rq, cur) {
-				thread_t *thread = list_get_instance(cur,
-				    thread_t, rq_link);
+			list_foreach(cpus[cpu].rq[i].rq, rq_link, thread_t,
+			    thread) {
 				printf("%" PRIu64 "(%s) ", thread->tid,
 				    thread_states[thread->state]);
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/proc/task.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -452,7 +452,5 @@
 	
 	/* Current values of threads */
-	list_foreach(task->threads, cur) {
-		thread_t *thread = list_get_instance(cur, thread_t, th_link);
-		
+	list_foreach(task->threads, th_link, thread_t, thread) {
 		irq_spinlock_lock(&thread->lock, false);
 		
@@ -484,6 +482,5 @@
 	 */
 	
-	list_foreach(task->threads, cur) {
-		thread_t *thread = list_get_instance(cur, thread_t, th_link);
+	list_foreach(task->threads, th_link, thread_t, thread) {
 		bool sleeping = false;
 		
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/proc/thread.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -192,6 +192,7 @@
 	kmflags &= ~FRAME_HIGHMEM;
 	
-	thread->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags);
-	if (!thread->kstack) {
+	uintptr_t stack_phys =
+	    frame_alloc(STACK_FRAMES, kmflags, STACK_SIZE - 1);
+	if (!stack_phys) {
 #ifdef CONFIG_FPU
 		if (thread->saved_fpu_context)
@@ -201,4 +202,6 @@
 	}
 	
+	thread->kstack = (uint8_t *) PA2KA(stack_phys);
+	
 #ifdef CONFIG_UDEBUG
 	mutex_initialize(&thread->udebug.lock, MUTEX_PASSIVE);
@@ -216,5 +219,5 @@
 	thr_destructor_arch(thread);
 	
-	frame_free(KA2PA(thread->kstack));
+	frame_free(KA2PA(thread->kstack), STACK_FRAMES);
 	
 #ifdef CONFIG_FPU
Index: kernel/generic/src/synch/futex.c
===================================================================
--- kernel/generic/src/synch/futex.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/synch/futex.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -274,9 +274,7 @@
 	mutex_lock(&TASK->futexes_lock);
 
-	list_foreach(TASK->futexes.leaf_list, cur) {
-		btree_node_t *node;
+	list_foreach(TASK->futexes.leaf_list, leaf_link, btree_node_t, node) {
 		unsigned int i;
 		
-		node = list_get_instance(cur, btree_node_t, leaf_link);
 		for (i = 0; i < node->keys; i++) {
 			futex_t *ftx;
Index: kernel/generic/src/sysinfo/stats.c
===================================================================
--- kernel/generic/src/sysinfo/stats.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/sysinfo/stats.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -175,8 +175,6 @@
 	
 	/* Walk the B+ tree and count pages */
-	list_foreach(as->as_area_btree.leaf_list, cur) {
-		btree_node_t *node =
-		    list_get_instance(cur, btree_node_t, leaf_link);
-		
+	list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
+	    node) {
 		unsigned int i;
 		for (i = 0; i < node->keys; i++) {
@@ -218,8 +216,5 @@
 	
 	/* Walk the B+ tree and count pages */
-	list_foreach(as->as_area_btree.leaf_list, cur) {
-		btree_node_t *node =
-		    list_get_instance(cur, btree_node_t, leaf_link);
-		
+	list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t, node) {
 		unsigned int i;
 		for (i = 0; i < node->keys; i++) {
Index: kernel/generic/src/time/clock.c
===================================================================
--- kernel/generic/src/time/clock.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/time/clock.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -81,6 +81,6 @@
 void clock_counter_init(void)
 {
-	void *faddr = frame_alloc(ONE_FRAME, FRAME_ATOMIC);
-	if (!faddr)
+	uintptr_t faddr = frame_alloc(1, FRAME_ATOMIC, 0);
+	if (faddr == 0)
 		panic("Cannot allocate page for clock.");
 	
@@ -91,5 +91,5 @@
 	uptime->useconds = 0;
 	
-	clock_parea.pbase = (uintptr_t) faddr;
+	clock_parea.pbase = faddr;
 	clock_parea.frames = 1;
 	clock_parea.unpriv = true;
Index: kernel/generic/src/udebug/udebug.c
===================================================================
--- kernel/generic/src/udebug/udebug.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/udebug/udebug.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -406,7 +406,5 @@
 	
 	/* Finish debugging of all userspace threads */
-	list_foreach(task->threads, cur) {
-		thread_t *thread = list_get_instance(cur, thread_t, th_link);
-		
+	list_foreach(task->threads, th_link, thread_t, thread) {
 		mutex_lock(&thread->udebug.lock);
 		
Index: kernel/generic/src/udebug/udebug_ops.c
===================================================================
--- kernel/generic/src/udebug/udebug_ops.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/generic/src/udebug/udebug_ops.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -196,7 +196,5 @@
 	/* Set udebug.active on all of the task's userspace threads. */
 	
-	list_foreach(TASK->threads, cur) {
-		thread_t *thread = list_get_instance(cur, thread_t, th_link);
-		
+	list_foreach(TASK->threads, th_link, thread_t, thread) {
 		mutex_lock(&thread->udebug.lock);
 		if (thread->uspace) {
@@ -389,7 +387,5 @@
 	
 	/* FIXME: make sure the thread isn't past debug shutdown... */
-	list_foreach(TASK->threads, cur) {
-		thread_t *thread = list_get_instance(cur, thread_t, th_link);
-		
+	list_foreach(TASK->threads, th_link, thread_t, thread) {
 		irq_spinlock_lock(&thread->lock, false);
 		bool uspace = thread->uspace;
Index: kernel/test/mm/falloc1.c
===================================================================
--- kernel/test/mm/falloc1.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/test/mm/falloc1.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -37,5 +37,5 @@
 #include <align.h>
 
-#define MAX_FRAMES  1024U
+#define MAX_FRAMES  1024
 #define MAX_ORDER   8
 #define TEST_RUNS   2
@@ -51,24 +51,19 @@
 		return "Unable to allocate frames";
 	
-	unsigned int results[MAX_ORDER + 1];
+	unsigned int results[MAX_FRAMES + 1];
+	
 	for (unsigned int run = 0; run < TEST_RUNS; run++) {
-		for (unsigned int order = 0; order <= MAX_ORDER; order++) {
-			TPRINTF("Allocating %u frames blocks ... ", 1 << order);
+		for (size_t count = 1; count <= MAX_FRAMES; count++) {
+			size_t bytes = FRAMES2SIZE(count);
+			
+			TPRINTF("Allocating %zu frames blocks (%zu bytes) ... ",
+			    count, bytes);
 			
 			unsigned int allocated = 0;
-			for (unsigned int i = 0; i < (MAX_FRAMES >> order); i++) {
-				frames[allocated] = (uintptr_t)
-				    frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
-				
-				if (ALIGN_UP(frames[allocated], FRAME_SIZE << order) !=
-				    frames[allocated]) {
-					TPRINTF("Block at address %p (size %u) is not aligned\n",
-					    (void *) frames[allocated], (FRAME_SIZE << order) >> 10);
-					return "Test failed";
-				}
-				
-				if (frames[allocated])
+			for (unsigned int i = 0; i < (MAX_FRAMES / count); i++) {
+				frames[allocated] = frame_alloc(count, FRAME_ATOMIC, 0);
+				if (frames[allocated]) {
 					allocated++;
-				else {
+				} else {
 					TPRINTF("done. ");
 					break;
@@ -78,14 +73,14 @@
 			TPRINTF("%d blocks allocated.\n", allocated);
 			
-			if (run) {
-				if (results[order] != allocated)
+			if (run > 0) {
+				if (results[count] != allocated)
 					return "Possible frame leak";
 			} else
-				results[order] = allocated;
+				results[count] = allocated;
 			
 			TPRINTF("Deallocating ... ");
 			
 			for (unsigned int i = 0; i < allocated; i++)
-				frame_free(KA2PA(frames[i]));
+				frame_free(frames[i], count);
 			
 			TPRINTF("done.\n");
Index: kernel/test/mm/falloc2.c
===================================================================
--- kernel/test/mm/falloc2.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/test/mm/falloc2.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -40,6 +40,5 @@
 #include <arch.h>
 
-#define MAX_FRAMES  256U
-#define MAX_ORDER   8
+#define MAX_FRAMES  256
 
 #define THREAD_RUNS  1
@@ -53,6 +52,6 @@
 	uint8_t val = THREAD->tid % THREADS;
 	
-	void **frames = (void **)
-	    malloc(MAX_FRAMES * sizeof(void *), FRAME_ATOMIC);
+	uintptr_t *frames = (uintptr_t *)
+	    malloc(MAX_FRAMES * sizeof(uintptr_t), FRAME_ATOMIC);
 	if (frames == NULL) {
 		TPRINTF("Thread #%" PRIu64 " (cpu%u): "
@@ -66,15 +65,16 @@
 	
 	for (unsigned int run = 0; run < THREAD_RUNS; run++) {
-		for (unsigned int order = 0; order <= MAX_ORDER; order++) {
+		for (size_t count = 1; count <= MAX_FRAMES; count++) {
+			size_t bytes = FRAMES2SIZE(count);
+			
 			TPRINTF("Thread #%" PRIu64 " (cpu%u): "
-			    "Allocating %u frames blocks ... \n", THREAD->tid,
-			    CPU->id, 1 << order);
+			    "Allocating %zu frames blocks (%zu bytes) ... \n", THREAD->tid,
+			    CPU->id, count, bytes);
 			
 			unsigned int allocated = 0;
-			for (unsigned int i = 0; i < (MAX_FRAMES >> order); i++) {
-				frames[allocated] =
-				    frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
+			for (unsigned int i = 0; i < (MAX_FRAMES / count); i++) {
+				frames[allocated] = frame_alloc(count, FRAME_ATOMIC, 0);
 				if (frames[allocated]) {
-					memsetb(frames[allocated], FRAME_SIZE << order, val);
+					memsetb((void *) PA2KA(frames[allocated]), bytes, val);
 					allocated++;
 				} else
@@ -89,10 +89,9 @@
 			
 			for (unsigned int i = 0; i < allocated; i++) {
-				for (size_t k = 0; k <= (((size_t) FRAME_SIZE << order) - 1);
-				    k++) {
-					if (((uint8_t *) frames[i])[k] != val) {
+				for (size_t k = 0; k < bytes; k++) {
+					if (((uint8_t *) PA2KA(frames[i]))[k] != val) {
 						TPRINTF("Thread #%" PRIu64 " (cpu%u): "
-						    "Unexpected data (%c) in block %p offset %zu\n",
-						    THREAD->tid, CPU->id, ((char *) frames[i])[k],
+						    "Unexpected data (%c) in block %zu offset %zu\n",
+						    THREAD->tid, CPU->id, ((char *) PA2KA(frames[i]))[k],
 						    frames[i], k);
 						atomic_inc(&thread_fail);
@@ -100,5 +99,5 @@
 					}
 				}
-				frame_free(KA2PA(frames[i]));
+				frame_free(frames[i], count);
 			}
 			
Index: kernel/test/mm/mapping1.c
===================================================================
--- kernel/test/mm/mapping1.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ kernel/test/mm/mapping1.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -41,55 +41,51 @@
 const char *test_mapping1(void)
 {
-	uintptr_t page0, page1;
-	uintptr_t frame;
-	uint32_t v;
-	int i;
+	uintptr_t frame = frame_alloc(1, FRAME_NONE, 0);
 	
-	frame = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_NONE);
-
-	page0 = km_map(frame, FRAME_SIZE,
+	uintptr_t page0 = km_map(frame, FRAME_SIZE,
 	    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
 	TPRINTF("Virtual address %p mapped to physical address %p.\n",
 	    (void *) page0, (void *) frame);
-	page1 = km_map(frame, FRAME_SIZE,
+	
+	uintptr_t page1 = km_map(frame, FRAME_SIZE,
 	    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
 	TPRINTF("Virtual address %p mapped to physical address %p.\n",
 	    (void *) page1, (void *) frame);
 	
-	for (i = 0; i < 2; i++) {
+	for (unsigned int i = 0; i < 2; i++) {
 		TPRINTF("Writing magic using the first virtual address.\n");
-
+		
 		*((uint32_t *) page0) = TEST_MAGIC;
-
+		
 		TPRINTF("Reading magic using the second virtual address.\n");
-
-		v = *((uint32_t *) page1);
-	
+		
+		uint32_t v = *((uint32_t *) page1);
+		
 		if (v != TEST_MAGIC) {
 			km_unmap(page0, PAGE_SIZE);
 			km_unmap(page1, PAGE_SIZE);
-			frame_free(frame);
+			frame_free(frame, 1);
 			return "Criss-cross read does not match the value written.";
 		}
-
+		
 		TPRINTF("Writing zero using the second virtual address.\n");
-	
+		
 		*((uint32_t *) page1) = 0;
-
+		
 		TPRINTF("Reading zero using the first virtual address.\n");
-	
+		
 		v = *((uint32_t *) page0);
-	
+		
 		if (v != 0) {
 			km_unmap(page0, PAGE_SIZE);
 			km_unmap(page1, PAGE_SIZE);
-			frame_free(frame);
+			frame_free(frame, 1);
 			return "Criss-cross read does not match the value written.";
 		}
 	}
-
+	
 	km_unmap(page0, PAGE_SIZE);
 	km_unmap(page1, PAGE_SIZE);
-	frame_free(frame);
+	frame_free(frame, 1);
 	
 	return NULL;
Index: tools/toolchain.sh
===================================================================
--- tools/toolchain.sh	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ tools/toolchain.sh	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -254,4 +254,31 @@
 }
 
+check_dirs() {
+	OUTSIDE="$1"
+	BASE="$2"
+	ORIGINAL="`pwd`"
+	
+	cd "${OUTSIDE}"
+	check_error $? "Unable to change directory to ${OUTSIDE}."
+	ABS_OUTSIDE="`pwd`"
+	
+	cd "${BASE}"
+	check_error $? "Unable to change directory to ${BASE}."
+	ABS_BASE="`pwd`"
+	
+	cd "${ORIGINAL}"
+	check_error $? "Unable to change directory to ${ORIGINAL}."
+	
+	BASE_LEN="${#ABS_BASE}"
+	OUTSIDE_TRIM="${ABS_OUTSIDE:0:${BASE_LEN}}"
+	
+	if [ "${OUTSIDE_TRIM}" == "${ABS_BASE}" ] ; then
+		echo
+		echo "CROSS_PREFIX cannot reside within the working directory."
+		
+		exit 5
+	fi
+}
+
 unpack_tarball() {
 	FILE="$1"
@@ -306,4 +333,6 @@
 	create_dir "${PREFIX}" "destination directory"
 	create_dir "${OBJDIR}" "GCC object directory"
+	
+	check_dirs "${PREFIX}" "${WORKDIR}"
 	
 	echo ">>> Unpacking tarballs"
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/Makefile	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -38,4 +38,5 @@
 	app/blkdump \
 	app/bnchmark \
+	app/corecfg \
 	app/devctl \
 	app/dnscfg \
@@ -189,4 +190,11 @@
 endif
 
+ifeq ($(UARCH), $(filter $(UARCH),mips32 mips32eb))
+	DIRS += \
+		drv/infrastructure/rootmalta \
+		drv/bus/pci/pciintel \
+		drv/bus/isa
+endif
+
 ifeq ($(UARCH),ppc32)
 	DIRS += \
Index: uspace/app/bdsh/cmds/modules/mount/mount.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mount/mount.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/app/bdsh/cmds/modules/mount/mount.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -74,8 +74,5 @@
 	get_mtab_list(&mtab_list);
 
-	list_foreach(mtab_list, cur) {
-		mtab_ent_t *mtab_ent = list_get_instance(cur, mtab_ent_t,
-		    link);
-
+	list_foreach(mtab_list, link, mtab_ent_t, mtab_ent) {
 		if (old_ent)
 			free(old_ent);
Index: uspace/app/corecfg/Makefile
===================================================================
--- uspace/app/corecfg/Makefile	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/app/corecfg/Makefile	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2013 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.
+#
+
+USPACE_PREFIX = ../..
+BINARY = corecfg
+
+SOURCES = \
+	corecfg.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/corecfg/corecfg.c
===================================================================
--- uspace/app/corecfg/corecfg.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/app/corecfg/corecfg.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 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 corecfg
+ * @{
+ */
+/** @file Core file configuration utility.
+ */
+
+#include <corecfg.h>
+#include <errno.h>
+#include <stdio.h>
+
+#define NAME "dnscfg"
+
+static void print_syntax(void)
+{
+	printf("Syntax:\n");
+	printf("\t%s [get]\n", NAME);
+	printf("\t%s enable\n", NAME);
+	printf("\t%s disable\n", NAME);
+}
+
+static int corecfg_print(void)
+{
+	bool enable;
+	int rc;
+
+	rc = corecfg_get_enable(&enable);
+	if (rc != EOK) {
+		printf("Failed getting core file setting.\n");
+		return 1;
+	}
+
+	printf("Core files: %s.\n", enable ? "enabled" : "disabled");
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+
+	rc = corecfg_init();
+	if (rc != EOK) {
+		printf("Failed contacting corecfg service.\n");
+		return 1;
+	}
+
+	if ((argc < 2) || (str_cmp(argv[1], "get") == 0))
+		return corecfg_print();
+	else if (str_cmp(argv[1], "enable") == 0)
+		return corecfg_set_enable(true);
+	else if (str_cmp(argv[1], "disable") == 0)
+		return corecfg_set_enable(false);
+	else {
+		printf("%s: Unknown command '%s'.\n", NAME, argv[1]);
+		print_syntax();
+		return 1;
+	}
+
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/devctl/devctl.c
===================================================================
--- uspace/app/devctl/devctl.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/app/devctl/devctl.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -35,4 +35,5 @@
 #include <devman.h>
 #include <errno.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -44,6 +45,28 @@
 #define MAX_NAME_LENGTH 1024
 
-char name[MAX_NAME_LENGTH];
-char drv_name[MAX_NAME_LENGTH];
+static char name[MAX_NAME_LENGTH];
+static char drv_name[MAX_NAME_LENGTH];
+static bool verbose = false;
+
+static const char *drv_state_str(driver_state_t state)
+{
+	const char *sstate;
+
+	switch (state) {
+	case DRIVER_NOT_STARTED:
+		sstate = "not started";
+		break;
+	case DRIVER_STARTING:
+		sstate = "starting";
+		break;
+	case DRIVER_RUNNING:
+		sstate = "running";
+		break;
+	default:
+		sstate = "unknown";
+	}
+
+	return sstate;
+}
 
 static int fun_subtree_print(devman_handle_t funh, int lvl)
@@ -52,4 +75,5 @@
 	devman_handle_t *cfuns;
 	size_t count, i;
+	unsigned int score;
 	int rc;
 	int j;
@@ -74,4 +98,18 @@
 		printf("%s : %s\n", name, drv_name);
 
+	if (verbose) {
+		for (i = 0; true; i++) {
+			rc = devman_fun_get_match_id(funh, i, name, MAX_NAME_LENGTH,
+			    &score);
+			if (rc != EOK)
+				break;
+
+			for (j = 0; j < lvl; j++)
+				printf("    ");
+
+			printf("    %u %s\n", score, name);
+		}
+	}
+
 	rc = devman_fun_get_child(funh, &devh);
 	if (rc == ENOENT)
@@ -159,7 +197,137 @@
 }
 
+static int drv_list(void)
+{
+	devman_handle_t *devs;
+	devman_handle_t *drvs;
+	driver_state_t state;
+	const char *sstate;
+	size_t ndrvs;
+	size_t ndevs;
+	size_t i;
+	int rc;
+
+	rc = devman_get_drivers(&drvs, &ndrvs);
+	if (rc != EOK)
+		return rc;
+
+	for (i = 0; i < ndrvs; i++) {
+		devs = NULL;
+
+		rc = devman_driver_get_name(drvs[i], drv_name, MAX_NAME_LENGTH);
+		if (rc != EOK)
+			goto skip;
+		rc = devman_driver_get_state(drvs[i], &state);
+		if (rc != EOK)
+			goto skip;
+		rc = devman_driver_get_devices(drvs[i], &devs, &ndevs);
+		if (rc != EOK)
+			goto skip;
+
+		sstate = drv_state_str(state);
+
+		printf("%-11s %3zu %s\n", sstate, ndevs, drv_name);
+skip:
+		free(devs);
+	}
+	free(drvs);
+
+	return EOK;
+}
+
+static int drv_show(char *drvname)
+{
+	devman_handle_t *devs;
+	devman_handle_t drvh;
+	devman_handle_t funh;
+	driver_state_t state;
+	const char *sstate;
+	unsigned int score;
+	size_t ndevs;
+	size_t i;
+	int rc;
+
+	rc = devman_driver_get_handle(drvname, &drvh);
+	if (rc != EOK)
+		return rc;
+
+	devs = NULL;
+
+	rc = devman_driver_get_name(drvh, drv_name, MAX_NAME_LENGTH);
+	if (rc != EOK)
+		return rc;
+
+	rc = devman_driver_get_state(drvh, &state);
+	if (rc != EOK)
+		return rc;
+
+	rc = devman_driver_get_devices(drvh, &devs, &ndevs);
+	if (rc != EOK)
+		return rc;
+
+	sstate = drv_state_str(state);
+
+	printf("Driver: %s\n", drv_name);
+	printf("State: %s\n", sstate);
+
+	printf("Attached devices:\n");
+
+	for (i = 0; i < ndevs; i++) {
+		rc = devman_dev_get_parent(devs[i], &funh);
+		if (rc != EOK)
+			goto error;
+
+		rc = devman_fun_get_path(funh, name, MAX_NAME_LENGTH);
+		if (rc != EOK)
+			goto error;
+		printf("\t%s\n", name);
+	}
+
+	printf("Match IDs:\n");
+
+	for (i = 0; true; i++) {
+		rc = devman_driver_get_match_id(drvh, i, name, MAX_NAME_LENGTH,
+		    &score);
+		if (rc != EOK)
+			break;
+
+		printf("\t%u %s\n", score, name);
+	}
+
+error:
+	free(devs);
+
+	return EOK;
+}
+
+static int drv_load(const char *drvname)
+{
+	int rc;
+	devman_handle_t drvh;
+
+	rc = devman_driver_get_handle(drvname, &drvh);
+	if (rc != EOK) {
+		printf("Failed resolving driver '%s' (%d).\n", drvname, rc);
+		return rc;
+	}
+
+	rc = devman_driver_load(drvh);
+	if (rc != EOK) {
+		printf("Failed loading driver '%s' (%d).\n", drvname, rc);
+		return rc;
+	}
+
+	return EOK;
+}
+
 static void print_syntax(void)
 {
-	printf("syntax: devctl [(online|offline) <function>]\n");
+	printf("syntax:\n");
+	printf("\tdevctl\n");
+	printf("\tdevctl online <function>]\n");
+	printf("\tdevctl offline <function>]\n");
+	printf("\tdevctl list-drv\n");
+	printf("\tdevctl show-drv <driver-name>\n");
+	printf("\tdevctl load-drv <driver-name>\n");
 }
 
@@ -168,5 +336,14 @@
 	int rc;
 
-	if (argc == 1) {
+	if (argc == 1 || argv[1][0] == '-') {
+		if (argc > 1) {
+			if (str_cmp(argv[1], "-v") == 0) {
+				verbose = true;
+			} else {
+				printf(NAME ": Invalid argument '%s'\n", argv[1]);
+				print_syntax();
+				return 1;
+			}
+		}
 		rc = fun_tree_print();
 		if (rc != EOK)
@@ -194,4 +371,29 @@
 			return 2;
 		}
+	} else if (str_cmp(argv[1], "list-drv") == 0) {
+		rc = drv_list();
+		if (rc != EOK)
+			return 2;
+	} else if (str_cmp(argv[1], "show-drv") == 0) {
+		if (argc < 3) {
+			printf(NAME ": Argument missing.\n");
+			print_syntax();
+			return 1;
+		}
+
+		rc = drv_show(argv[2]);
+		if (rc != EOK) {
+			return 2;
+		}
+	} else if (str_cmp(argv[1], "load-drv") == 0) {
+		if (argc < 3) {
+			printf(NAME ": Argument missing.\n");
+			print_syntax();
+			return 1;
+		}
+
+		rc = drv_load(argv[2]);
+		if (rc != EOK)
+			return 2;
 	} else {
 		printf(NAME ": Invalid argument '%s'.\n", argv[1]);
Index: uspace/app/edit/sheet.c
===================================================================
--- uspace/app/edit/sheet.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/app/edit/sheet.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -105,5 +105,4 @@
 	char *ipp;
 	size_t sz;
-	tag_t *tag;
 	char *newp;
 
@@ -128,7 +127,5 @@
 	/* Adjust tags. */
 
-	list_foreach(sh->tags, link) {
-		tag = list_get_instance(link, tag_t, link);
-
+	list_foreach(sh->tags, link, tag_t, tag) {
 		if (tag->b_off > pos->b_off)
 			tag->b_off += sz;
@@ -154,5 +151,4 @@
 	char *spp;
 	size_t sz;
-	tag_t *tag;
 	char *newp;
 	size_t shrink_size;
@@ -165,7 +161,5 @@
 
 	/* Adjust tags. */
-	list_foreach(sh->tags, link) {
-		tag = list_get_instance(link, tag_t, link);
-
+	list_foreach(sh->tags, link, tag_t, tag) {
 		if (tag->b_off >= epos->b_off)
 			tag->b_off -= sz;
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/app/init/init.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -384,4 +384,5 @@
 	srv_start("/srv/input", HID_INPUT);
 	srv_start("/srv/output", HID_OUTPUT);
+	srv_start("/srv/hound");
 	
 	int rc = compositor(HID_INPUT, HID_COMPOSITOR_SERVER);
Index: uspace/app/klog/klog.c
===================================================================
--- uspace/app/klog/klog.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/app/klog/klog.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -206,6 +206,6 @@
 	klog_length = size / sizeof(wchar_t);
 	
-	rc = physmem_map((void *) faddr, pages,
-	    AS_AREA_READ | AS_AREA_CACHEABLE, (void *) &klog);
+	rc = physmem_map(faddr, pages, AS_AREA_READ | AS_AREA_CACHEABLE,
+	    (void *) &klog);
 	if (rc != EOK) {
 		fprintf(stderr, "%s: Unable to map klog\n", NAME);
Index: uspace/app/tester/mm/common.c
===================================================================
--- uspace/app/tester/mm/common.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/app/tester/mm/common.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -84,8 +84,6 @@
 }
 
-static bool overlap_match(link_t *link, void *addr, size_t size)
-{
-	mem_block_t *block = list_get_instance(link, mem_block_t, link);
-	
+static bool overlap_match(mem_block_t *block, void *addr, size_t size)
+{
 	/* Entry block control structure <mbeg, mend) */
 	uint8_t *mbeg = (uint8_t *) block;
@@ -125,6 +123,6 @@
 	bool fnd = false;
 	
-	list_foreach(mem_blocks, link) {
-		if (overlap_match(link, addr, size)) {
+	list_foreach(mem_blocks, link, mem_block_t, block) {
+		if (overlap_match(block, addr, size)) {
 			fnd = true;
 			break;
Index: uspace/app/usbinfo/dump.c
===================================================================
--- uspace/app/usbinfo/dump.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/app/usbinfo/dump.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -103,7 +103,5 @@
 void dump_match_ids(match_id_list_t *matches, const char *line_prefix)
 {
-	list_foreach(matches->ids, link) {
-		match_id_t *match = list_get_instance(link, match_id_t, link);
-
+	list_foreach(matches->ids, link, match_id_t, match) {
 		printf("%s%3d %s\n", line_prefix, match->score, match->id);
 	}
Index: uspace/app/usbinfo/hid.c
===================================================================
--- uspace/app/usbinfo/hid.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/app/usbinfo/hid.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -100,13 +100,11 @@
 	printf("%sParsed HID report descriptor for interface %d\n",
 	    get_indent(0), iface_no);
-	list_foreach(report->reports, report_it) {
-		usb_hid_report_description_t *description = list_get_instance(
-		    report_it, usb_hid_report_description_t, reports_link);
+	list_foreach(report->reports, reports_link,
+	    usb_hid_report_description_t, description) {
 		printf("%sReport %d (type %d)\n", get_indent(1),
 		    (int) description->report_id,
 		    (int) description->type);
-		list_foreach(description->report_items, item_it) {
-			usb_hid_report_field_t *field = list_get_instance(
-			    item_it, usb_hid_report_field_t, ritems_link);
+		list_foreach(description->report_items, ritems_link,
+		    usb_hid_report_field_t, field) {
 			printf("%sUsage page = 0x%04x    Usage = 0x%04x\n",
 			    get_indent(2),
Index: uspace/drv/audio/sb16/dsp.c
===================================================================
--- uspace/drv/audio/sb16/dsp.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/audio/sb16/dsp.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -173,19 +173,23 @@
 {
 	assert(dsp);
-	if (size > MAX_BUFFER_SIZE || size == 0 || (size % 2) == 1)
+	
+	if ((size > MAX_BUFFER_SIZE) || (size == 0) || ((size % 2) == 1))
 		size = MAX_BUFFER_SIZE;
-	void *buffer = NULL, *pa = NULL;
-	int ret = dmamem_map_anonymous(size, AS_AREA_WRITE | AS_AREA_READ,
-	    0, &pa, &buffer);
+	
+	uintptr_t pa = 0;
+	void *buffer = NULL;
+	
+	int ret = dmamem_map_anonymous(size, DMAMEM_16MiB,
+	    AS_AREA_WRITE | AS_AREA_READ, 0, &pa, &buffer);
 	if (ret != EOK) {
 		ddf_log_error("Failed to allocate DMA buffer.");
 		return ENOMEM;
 	}
-
-	ddf_log_verbose("Setup dma buffer at %p(%p) %zu.", buffer, pa, size);
-	assert((uintptr_t)pa < (1 << 25));
-
+	
+	ddf_log_verbose("Setup DMA buffer at %p (%zu) %zu.", buffer, pa, size);
+	assert(pa < (1 << 24));
+	
 	/* Setup 16 bit channel */
-	ret = setup_dma(dsp, (uintptr_t)pa, size);
+	ret = setup_dma(dsp, pa, size);
 	if (ret == EOK) {
 		dsp->buffer.data = buffer;
@@ -196,4 +200,5 @@
 		dmamem_unmap_anonymous(buffer);
 	}
+	
 	return ret;
 }
Index: uspace/drv/block/ahci/ahci.c
===================================================================
--- uspace/drv/block/ahci/ahci.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/block/ahci/ahci.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -119,6 +119,6 @@
 static int ahci_identify_device(sata_dev_t *);
 static int ahci_set_highest_ultra_dma_mode(sata_dev_t *);
-static int ahci_rb_fpdma(sata_dev_t *, void *, uint64_t);
-static int ahci_wb_fpdma(sata_dev_t *, void *, uint64_t);
+static int ahci_rb_fpdma(sata_dev_t *, uintptr_t, uint64_t);
+static int ahci_wb_fpdma(sata_dev_t *, uintptr_t, uint64_t);
 
 static void ahci_sata_devices_create(ahci_dev_t *, ddf_dev_t *);
@@ -233,8 +233,8 @@
 	sata_dev_t *sata = fun_sata_dev(fun);
 	
-	void *phys;
+	uintptr_t phys;
 	void *ibuf;
-	int rc = dmamem_map_anonymous(sata->block_size, AS_AREA_READ | AS_AREA_WRITE,
-	    0, &phys, (void **) &ibuf);
+	int rc = dmamem_map_anonymous(sata->block_size, DMAMEM_4GiB,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, &ibuf);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Cannot allocate read buffer.");
@@ -276,8 +276,8 @@
 	sata_dev_t *sata = fun_sata_dev(fun);
 	
-	void *phys;
+	uintptr_t phys;
 	void *ibuf;
-	int rc = dmamem_map_anonymous(sata->block_size, AS_AREA_READ | AS_AREA_WRITE,
-	    0, &phys, (void **) &ibuf);
+	int rc = dmamem_map_anonymous(sata->block_size, DMAMEM_4GiB,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, &ibuf);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Cannot allocate write buffer.");
@@ -336,5 +336,5 @@
  *
  */
-static void ahci_identify_device_cmd(sata_dev_t *sata, void *phys)
+static void ahci_identify_device_cmd(sata_dev_t *sata, uintptr_t phys)
 {
 	volatile sata_std_command_frame_t *cmd =
@@ -381,5 +381,5 @@
  *
  */
-static void ahci_identify_packet_device_cmd(sata_dev_t *sata, void *phys)
+static void ahci_identify_packet_device_cmd(sata_dev_t *sata, uintptr_t phys)
 {
 	volatile sata_std_command_frame_t *cmd =
@@ -435,8 +435,9 @@
 	}
 	
-	void *phys;
+	uintptr_t phys;
 	sata_identify_data_t *idata;
 	int rc = dmamem_map_anonymous(SATA_IDENTIFY_DEVICE_BUFFER_LENGTH,
-	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, (void **) &idata);
+	    DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0, &phys,
+	    (void **) &idata);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Cannot allocate buffer to identify device.");
@@ -561,5 +562,5 @@
  *
  */
-static void ahci_set_mode_cmd(sata_dev_t *sata, void* phys, uint8_t mode)
+static void ahci_set_mode_cmd(sata_dev_t *sata, uintptr_t phys, uint8_t mode)
 {
 	volatile sata_std_command_frame_t *cmd =
@@ -567,5 +568,5 @@
 	
 	cmd->fis_type = SATA_CMD_FIS_TYPE;
-	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR; 
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR;
 	cmd->command = 0xef;
 	cmd->features = 0x03;
@@ -628,8 +629,9 @@
 	}
 	
-	void *phys;
+	uintptr_t phys;
 	sata_identify_data_t *idata;
 	int rc = dmamem_map_anonymous(SATA_SET_FEATURE_BUFFER_LENGTH,
-	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, (void **) &idata);
+	    DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0, &phys,
+	    (void **) &idata);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Cannot allocate buffer for device set mode.");
@@ -677,5 +679,6 @@
  *
  */
-static void ahci_rb_fpdma_cmd(sata_dev_t *sata, void *phys, uint64_t blocknum)
+static void ahci_rb_fpdma_cmd(sata_dev_t *sata, uintptr_t phys,
+    uint64_t blocknum)
 {
 	volatile sata_ncq_command_frame_t *cmd =
@@ -734,5 +737,5 @@
  *
  */
-static int ahci_rb_fpdma(sata_dev_t *sata, void *phys, uint64_t blocknum)
+static int ahci_rb_fpdma(sata_dev_t *sata, uintptr_t phys, uint64_t blocknum)
 {
 	if (sata->is_invalid_device) {
@@ -763,5 +766,6 @@
  *
  */
-static void ahci_wb_fpdma_cmd(sata_dev_t *sata, void *phys, uint64_t blocknum)
+static void ahci_wb_fpdma_cmd(sata_dev_t *sata, uintptr_t phys,
+    uint64_t blocknum)
 {
 	volatile sata_ncq_command_frame_t *cmd =
@@ -821,5 +825,5 @@
  *
  */
-static int ahci_wb_fpdma(sata_dev_t *sata, void *phys, uint64_t blocknum)
+static int ahci_wb_fpdma(sata_dev_t *sata, uintptr_t phys, uint64_t blocknum)
 {
 	if (sata->is_invalid_device) {
@@ -933,5 +937,5 @@
 {
 	size_t size = 4096;
-	void *phys = NULL;
+	uintptr_t phys = 0;
 	void *virt_fb = NULL;
 	void *virt_cmd = NULL;
@@ -949,6 +953,6 @@
 	
 	/* Allocate and init retfis structure. */
-	int rc = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE, 0,
-	    &phys, &virt_fb);
+	int rc = dmamem_map_anonymous(size, DMAMEM_4GiB,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, &virt_fb);
 	if (rc != EOK)
 		goto error_retfis;
@@ -959,6 +963,6 @@
 	
 	/* Allocate and init command header structure. */
-	rc = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE, 0,
-	    &phys, &virt_cmd);
+	rc = dmamem_map_anonymous(size, DMAMEM_4GiB,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, &virt_cmd);
 	if (rc != EOK)
 		goto error_cmd;
@@ -970,6 +974,6 @@
 	
 	/* Allocate and init command table structure. */
-	rc = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE, 0,
-	    &phys, &virt_table);
+	rc = dmamem_map_anonymous(size, DMAMEM_4GiB,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, &virt_table);
 	if (rc != EOK)
 		goto error_table;
@@ -1153,5 +1157,5 @@
 	ahci->memregs = NULL;
 	
-	physmem_map((void *) (size_t) (hw_res_parsed.mem_ranges.ranges[0].address),
+	physmem_map((uintptr_t) (hw_res_parsed.mem_ranges.ranges[0].address),
 	    AHCI_MEMREGS_PAGES_COUNT, AS_AREA_READ | AS_AREA_WRITE,
 	    (void **) &ahci->memregs);
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/bus/isa/isa.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -67,4 +67,5 @@
 
 #include <device/hw_res.h>
+#include <device/pio_window.h>
 
 #include "i8237.h"
@@ -79,4 +80,5 @@
 	ddf_dev_t *dev;
 	ddf_fun_t *fctl;
+	pio_window_t pio_win;
 	list_t functions;
 } isa_bus_t;
@@ -405,7 +407,10 @@
 	hw_resource_t *resources = fun->hw_resources.resources;
 
+	isa_bus_t *isa = isa_bus(ddf_fun_get_dev(fun->fnode));
+
 	if (count < ISA_MAX_HW_RES) {
 		resources[count].type = IO_RANGE;
 		resources[count].res.io_range.address = addr;
+		resources[count].res.io_range.address += isa->pio_win.io.base;
 		resources[count].res.io_range.size = len;
 		resources[count].res.io_range.endianness = LITTLE_ENDIAN;
@@ -604,4 +609,7 @@
 static int isa_dev_add(ddf_dev_t *dev)
 {
+	async_sess_t *sess;
+	int rc;
+
 	ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d",
 	    (int) ddf_dev_get_handle(dev));
@@ -614,4 +622,18 @@
 	isa->dev = dev;
 	list_initialize(&isa->functions);
+
+	sess = ddf_dev_parent_sess_create(dev, EXCHANGE_SERIALIZE);
+	if (sess == NULL) {
+		ddf_msg(LVL_ERROR, "isa_dev_add failed to connect to the "
+		    "parent driver.");
+		return ENOENT;
+	}
+
+	rc = pio_window_get(sess, &isa->pio_win);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "isa_dev_add failed to get PIO window "
+		    "for the device.");
+		return rc;
+	}	
 
 	/* Make the bus device more visible. Does not do anything. */
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -57,4 +57,6 @@
 #include <ops/hw_res.h>
 #include <device/hw_res.h>
+#include <ops/pio_window.h>
+#include <device/pio_window.h>
 #include <ddi.h>
 #include <pci_dev_iface.h>
@@ -141,4 +143,14 @@
 }
 
+static pio_window_t *pciintel_get_pio_window(ddf_fun_t *fnode)
+{
+	pci_fun_t *fun = pci_fun(fnode);
+	
+	if (fun == NULL)
+		return NULL;
+	return &fun->pio_window;
+}
+
+
 static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address,
     uint32_t data)
@@ -198,4 +210,8 @@
 	.get_resource_list = &pciintel_get_resources,
 	.enable_interrupt = &pciintel_enable_interrupt,
+};
+
+static pio_window_ops_t pciintel_pio_window_ops = {
+	.get_pio_window = &pciintel_get_pio_window
 };
 
@@ -211,4 +227,5 @@
 static ddf_dev_ops_t pci_fun_ops = {
 	.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
+	.interfaces[PIO_WINDOW_DEV_IFACE] = &pciintel_pio_window_ops,
 	.interfaces[PCI_DEV_IFACE] = &pci_dev_ops
 };
@@ -233,23 +250,28 @@
 static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
 {
+	const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
 	pci_bus_t *bus = pci_bus_from_fun(fun);
+	uint32_t val;
 	
 	fibril_mutex_lock(&bus->conf_mutex);
-	
-	const uint32_t 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, host2uint32_t_le(conf_addr));
-	
+
+	/*
+	 * Always read full 32-bits from the PCI conf_data_port register and
+	 * get the desired portion of it afterwards. Some architectures do not
+	 * support shorter PIO reads offset from this register.
+ 	 */
+	val = uint32_t_le2host(pio_read_32(bus->conf_data_port));
+
 	switch (len) {
 	case 1:
-		/* No endianness change for 1 byte */
-		buf[0] = pio_read_8(addr);
+		*buf = (uint8_t) (val >> ((reg & 3) * 8));
 		break;
 	case 2:
-		((uint16_t *) buf)[0] = uint16_t_le2host(pio_read_16(addr));
+		*((uint16_t *) buf) = (uint16_t) (val >> ((reg & 3)) * 8);
 		break;
 	case 4:
-		((uint32_t *) buf)[0] = uint32_t_le2host(pio_read_32(addr));
+		*((uint32_t *) buf) = (uint32_t) val;
 		break;
 	}
@@ -260,25 +282,41 @@
 static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
 {
+	const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
 	pci_bus_t *bus = pci_bus_from_fun(fun);
+	uint32_t val;
 	
 	fibril_mutex_lock(&bus->conf_mutex);
-	
-	const uint32_t 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, host2uint32_t_le(conf_addr));
+
+	/*
+	 * Prepare to write full 32-bits to the PCI conf_data_port register.
+	 * Some architectures do not support shorter PIO writes offset from this
+	 * register.
+ 	 */
+
+	if (len < 4) {
+		/*
+ 		 * We have fewer than full 32-bits, so we need to read the
+ 		 * missing bits first.
+ 		 */
+		pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
+		val = uint32_t_le2host(pio_read_32(bus->conf_data_port));
+	}
 	
 	switch (len) {
 	case 1:
-		/* No endianness change for 1 byte */
-		pio_write_8(addr, buf[0]);
+		val &= ~(0xffU << ((reg & 3) * 8));
+		val |= *buf << ((reg & 3) * 8);
 		break;
 	case 2:
-		pio_write_16(addr, host2uint16_t_le(((uint16_t *) buf)[0]));
+		val &= ~(0xffffU << ((reg & 3) * 8));
+		val |= *((uint16_t *) buf) << ((reg & 3) * 8);
 		break;
 	case 4:
-		pio_write_32(addr, host2uint32_t_le(((uint32_t *) buf)[0]));
+		val = *((uint32_t *) buf);
 		break;
 	}
+
+	pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
+	pio_write_32(bus->conf_data_port, host2uint32_t_le(val));
 	
 	fibril_mutex_unlock(&bus->conf_mutex);
@@ -433,5 +471,8 @@
 {
 	/* Value of the BAR */
-	uint32_t val, mask;
+	uint32_t val;
+	uint32_t bar;
+	uint32_t mask;
+
 	/* IO space address */
 	bool io;
@@ -471,6 +512,14 @@
 	/* Get the address mask. */
 	pci_conf_write_32(fun, addr, 0xffffffff);
-	mask &= pci_conf_read_32(fun, addr);
-	
+	bar = pci_conf_read_32(fun, addr);
+
+	/*
+ 	 * Unimplemented BARs read back as all 0's.
+ 	 */
+	if (!bar)
+		return addr + (addrw64 ? 8 : 4);
+
+	mask &= bar;	
+
 	/* Restore the original value. */
 	pci_conf_write_32(fun, addr, val);
@@ -520,5 +569,7 @@
 {
 	uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
-	if (irq != 0xff)
+	uint8_t pin = pci_conf_read_8(fun, PCI_BRIDGE_INT_PIN);
+
+	if (pin != 0 && irq != 0xff)
 		pci_add_interrupt(fun, irq);
 }
@@ -583,4 +634,7 @@
 			pci_read_bars(fun);
 			pci_read_interrupt(fun);
+
+			/* Propagate the PIO window to the function. */
+			fun->pio_window = bus->pio_win;
 			
 			ddf_fun_set_ops(fun->fnode, &pci_fun_ops);
@@ -613,4 +667,5 @@
 static int pci_dev_add(ddf_dev_t *dnode)
 {
+	hw_resource_list_t hw_resources;
 	pci_bus_t *bus = NULL;
 	ddf_fun_t *ctl = NULL;
@@ -638,6 +693,11 @@
 		goto fail;
 	}
-	
-	hw_resource_list_t hw_resources;
+
+	rc = pio_window_get(sess, &bus->pio_win);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "pci_dev_add failed to get PIO window "
+		    "for the device.");
+		goto fail;
+	}
 	
 	rc = hw_res_get_resource_list(sess, &hw_resources);
@@ -729,6 +789,4 @@
 {
 	ddf_log_init(NAME);
-	pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
-	pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
 }
 
Index: uspace/drv/bus/pci/pciintel/pci.h
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/bus/pci/pciintel/pci.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -40,5 +40,5 @@
 #include "pci_regs.h"
 
-#define PCI_MAX_HW_RES 8
+#define PCI_MAX_HW_RES 10 
 
 typedef struct pciintel_bus {
@@ -49,4 +49,5 @@
 	void *conf_data_port;
 	void *conf_addr_port;
+	pio_window_t pio_win;
 	fibril_mutex_t conf_mutex;
 } pci_bus_t;
@@ -68,4 +69,5 @@
 	hw_resource_list_t hw_resources;
 	hw_resource_t resources[PCI_MAX_HW_RES];
+	pio_window_t pio_window;
 } pci_fun_t;
 
Index: uspace/drv/bus/usb/uhci/utils/malloc32.h
===================================================================
--- uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -92,5 +92,7 @@
  */
 static inline void free32(void *addr)
-	{ free(addr); }
+{
+	free(addr);
+}
 
 /** Create 4KB page mapping
@@ -98,10 +100,14 @@
  * @return Address of the mapped page, NULL on failure.
  */
-static inline void * get_page(void)
+static inline void *get_page(void)
 {
-	void *address, *phys;
+	uintptr_t phys;
+	void *address;
+	
 	const int ret = dmamem_map_anonymous(UHCI_REQUIRED_PAGE_SIZE,
-	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, &address);
-	return ret == EOK ? address : NULL;
+	    DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0, &phys,
+	    &address);
+	
+	return ((ret == EOK) ? address : NULL);
 }
 
Index: uspace/drv/bus/usb/usbmid/explore.c
===================================================================
--- uspace/drv/bus/usb/usbmid/explore.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/bus/usb/usbmid/explore.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -56,6 +56,5 @@
 static bool interface_in_list(const list_t *list, int interface_no)
 {
-	list_foreach(*list, l) {
-		usbmid_interface_t *iface = usbmid_interface_from_link(l);
+	list_foreach(*list, link, usbmid_interface_t, iface) {
 		if (iface->interface_no == interface_no) {
 			return true;
@@ -190,7 +189,5 @@
 
 	/* Start child function for every interface. */
-	list_foreach(usb_mid->interface_list, link) {
-		usbmid_interface_t *iface = usbmid_interface_from_link(link);
-
+	list_foreach(usb_mid->interface_list, link, usbmid_interface_t, iface) {
 		usb_log_info("Creating child for interface %d (%s).\n",
 		    iface->interface_no,
Index: uspace/drv/bus/usb/usbmid/usbmid.c
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/bus/usb/usbmid/usbmid.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -135,6 +135,5 @@
 	}
 
-	list_foreach(match_ids.ids, link) {
-		match_id_t *match_id = list_get_instance(link, match_id_t, link);
+	list_foreach(match_ids.ids, link, match_id_t, match_id) {
 		rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
 		if (rc != EOK) {
Index: uspace/drv/bus/usb/vhc/transfer.c
===================================================================
--- uspace/drv/bus/usb/vhc/transfer.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/bus/usb/vhc/transfer.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -92,6 +92,5 @@
 
 	bool target_found = false;
-	list_foreach(vhc->devices, pos) {
-		vhc_virtdev_t *dev = list_get_instance(pos, vhc_virtdev_t, link);
+	list_foreach(vhc->devices, link, vhc_virtdev_t, dev) {
 		fibril_mutex_lock(&dev->guard);
 		if (dev->address == transfer->address) {
Index: uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c
===================================================================
--- uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -273,11 +273,13 @@
 	ddf_log_note("Setting mode: %ux%ux%u\n", x, y, bpp*8);
 	const size_t size = ALIGN_UP(x * y * bpp, PAGE_SIZE);
-	void *buffer, *pa;
-	int ret = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE,
-	    0, &pa, &buffer);
+	uintptr_t pa;
+	void *buffer;
+	int ret = dmamem_map_anonymous(size, DMAMEM_4GiB,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &pa, &buffer);
 	if (ret != EOK) {
 		ddf_log_error("Failed to get new FB\n");
 		return ret;
 	}
+	
 	amdm37x_dispc_setup_fb(dispc->regs, x, y, bpp *8, (uint32_t)pa);
 	dispc->active_fb.idx = mode.index;
Index: uspace/drv/fb/kfb/port.c
===================================================================
--- uspace/drv/fb/kfb/port.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/fb/kfb/port.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -333,5 +333,5 @@
 	
 	kfb.size = scanline * height;
-	rc = physmem_map((void *) paddr + offset,
+	rc = physmem_map(paddr + offset,
 	    ALIGN_UP(kfb.size, PAGE_SIZE) >> PAGE_WIDTH,
 	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kfb.addr);
Index: uspace/drv/infrastructure/rootmalta/Makefile
===================================================================
--- uspace/drv/infrastructure/rootmalta/Makefile	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/drv/infrastructure/rootmalta/Makefile	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = rootmalta
+
+SOURCES = \
+	rootmalta.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/infrastructure/rootmalta/rootmalta.c
===================================================================
--- uspace/drv/infrastructure/rootmalta/rootmalta.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/drv/infrastructure/rootmalta/rootmalta.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2013 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.
+ */
+
+/**
+ * @defgroup root_malta Malta board platform driver.
+ * @brief HelenOS Malta board platform driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+
+#include <ddi.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <ipc/dev_iface.h>
+#include <ops/hw_res.h>
+#include <device/hw_res.h>
+#include <ops/pio_window.h>
+#include <device/pio_window.h>
+#include <byteorder.h>
+
+#define NAME "rootmalta"
+
+#define GT_BASE		UINT32_C(0x1be00000)
+#define GT_SIZE 	(2 * 1024 * 1024)
+
+#define GT_PCI_CMD	0xc00
+#define GT_PCI_CONFADDR	0xcf8
+#define GT_PCI_CONFDATA	0xcfc
+
+#define GT_PCI_CMD_MBYTESWAP	0x1
+
+#define GT_PCI_MEMBASE	UINT32_C(0x10000000)
+#define GT_PCI_MEMSIZE	UINT32_C(0x08000000)
+
+#define GT_PCI_IOBASE	UINT32_C(0x18000000)
+#define GT_PCI_IOSIZE	UINT32_C(0x00200000)
+
+typedef struct rootmalta_fun {
+	hw_resource_list_t hw_resources;
+	pio_window_t pio_window;
+} rootmalta_fun_t;
+
+static int rootmalta_dev_add(ddf_dev_t *dev);
+static void root_malta_init(void);
+
+/** The root device driver's standard operations. */
+static driver_ops_t rootmalta_ops = {
+	.dev_add = &rootmalta_dev_add
+};
+
+/** The root device driver structure. */
+static driver_t rootmalta_driver = {
+	.name = NAME,
+	.driver_ops = &rootmalta_ops
+};
+
+static hw_resource_t pci_conf_regs[] = {
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = GT_BASE + GT_PCI_CONFADDR,
+			.size = 4,
+			.endianness = LITTLE_ENDIAN
+		}
+	},
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = GT_BASE + GT_PCI_CONFDATA,
+			.size = 4,
+			.endianness = LITTLE_ENDIAN
+		}
+	}
+};
+
+static rootmalta_fun_t pci_data = {
+	.hw_resources = {
+		sizeof(pci_conf_regs) / sizeof(pci_conf_regs[0]),
+		pci_conf_regs
+	},
+	.pio_window = {
+		.mem = {
+			.base = GT_PCI_MEMBASE,
+			.size = GT_PCI_MEMSIZE
+		},
+		.io = {
+			.base = GT_PCI_IOBASE,
+			.size = GT_PCI_IOSIZE
+		}
+	}
+};
+
+/** Obtain function soft-state from DDF function node */
+static rootmalta_fun_t *rootmalta_fun(ddf_fun_t *fnode)
+{
+	return ddf_fun_data_get(fnode);
+}
+
+static hw_resource_list_t *rootmalta_get_resources(ddf_fun_t *fnode)
+{
+	rootmalta_fun_t *fun = rootmalta_fun(fnode);
+	
+	assert(fun != NULL);
+	return &fun->hw_resources;
+}
+
+static bool rootmalta_enable_interrupt(ddf_fun_t *fun)
+{
+	/* TODO */
+	
+	return false;
+}
+
+static pio_window_t *rootmalta_get_pio_window(ddf_fun_t *fnode)
+{
+	rootmalta_fun_t *fun = rootmalta_fun(fnode);
+
+	assert(fun != NULL);
+	return &fun->pio_window;
+}
+
+static hw_res_ops_t fun_hw_res_ops = {
+	.get_resource_list = &rootmalta_get_resources,
+	.enable_interrupt = &rootmalta_enable_interrupt,
+};
+
+static pio_window_ops_t fun_pio_window_ops = {
+	.get_pio_window = &rootmalta_get_pio_window
+};
+
+/* Initialized in root_malta_init() function. */
+static ddf_dev_ops_t rootmalta_fun_ops;
+
+static bool
+rootmalta_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
+    rootmalta_fun_t *fun_proto)
+{
+	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
+	
+	ddf_fun_t *fnode = NULL;
+	int rc;
+	
+	/* Create new device. */
+	fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL)
+		goto failure;
+	
+	rootmalta_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(rootmalta_fun_t));
+	*fun = *fun_proto;
+	
+	/* Add match ID */
+	rc = ddf_fun_add_match_id(fnode, str_match_id, 100);
+	if (rc != EOK)
+		goto failure;
+	
+	/* Set provided operations to the device. */
+	ddf_fun_set_ops(fnode, &rootmalta_fun_ops);
+	
+	/* Register function. */
+	if (ddf_fun_bind(fnode) != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
+		goto failure;
+	}
+	
+	return true;
+	
+failure:
+	if (fnode != NULL)
+		ddf_fun_destroy(fnode);
+	
+	ddf_msg(LVL_ERROR, "Failed adding function '%s'.", name);
+	
+	return false;
+}
+
+static bool rootmalta_add_functions(ddf_dev_t *dev)
+{
+	return rootmalta_add_fun(dev, "pci0", "intel_pci", &pci_data);
+}
+
+/** Get the root device.
+ *
+ * @param dev		The device which is root of the whole device tree (both
+ *			of HW and pseudo devices).
+ * @return		Zero on success, negative error number otherwise.
+ */
+static int rootmalta_dev_add(ddf_dev_t *dev)
+{
+	ioport32_t *gt;
+	uint32_t val;
+	int ret;
+
+	ddf_msg(LVL_DEBUG, "rootmalta_dev_add, device handle = %d",
+	    (int)ddf_dev_get_handle(dev));
+
+	/*
+ 	 * We need to disable byte swapping of the outgoing and incoming
+ 	 * PCI data, because the PCI driver assumes no byte swapping behind
+ 	 * the scenes and takes care of it itself.
+ 	 */
+	ret = pio_enable((void *) GT_BASE, GT_SIZE, (void **) &gt);
+	if (ret != EOK)
+                return ret;
+	val = uint32_t_le2host(pio_read_32(
+	    &gt[GT_PCI_CMD / sizeof(ioport32_t)]));
+	val |= GT_PCI_CMD_MBYTESWAP;
+	pio_write_32(
+	    &gt[GT_PCI_CMD / sizeof(ioport32_t)], host2uint32_t_le(val));
+
+	
+	/* Register functions. */
+	if (!rootmalta_add_functions(dev)) {
+		ddf_msg(LVL_ERROR, "Failed to add functions for the Malta platform.");
+	}
+	
+	return EOK;
+}
+
+static void root_malta_init(void)
+{
+	ddf_log_init(NAME);
+	rootmalta_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
+	rootmalta_fun_ops.interfaces[PIO_WINDOW_DEV_IFACE] = &fun_pio_window_ops;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS Malta platform driver\n");
+	root_malta_init();
+	return ddf_driver_main(&rootmalta_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/infrastructure/rootmalta/rootmalta.ma
===================================================================
--- uspace/drv/infrastructure/rootmalta/rootmalta.ma	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/drv/infrastructure/rootmalta/rootmalta.ma	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,1 @@
+10 platform/malta
Index: uspace/drv/infrastructure/rootpc/rootpc.c
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/infrastructure/rootpc/rootpc.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -51,4 +51,6 @@
 #include <ops/hw_res.h>
 #include <device/hw_res.h>
+#include <ops/pio_window.h>
+#include <device/pio_window.h>
 
 #define NAME "rootpc"
@@ -56,4 +58,5 @@
 typedef struct rootpc_fun {
 	hw_resource_list_t hw_resources;
+	pio_window_t pio_window;
 } rootpc_fun_t;
 
@@ -93,6 +96,16 @@
 static rootpc_fun_t pci_data = {
 	.hw_resources = {
-		sizeof(pci_conf_regs)/sizeof(pci_conf_regs[0]),
+		sizeof(pci_conf_regs) / sizeof(pci_conf_regs[0]),
 		pci_conf_regs
+	},
+	.pio_window = {
+		.mem = {
+			.base = UINT32_C(0),
+			.size = UINT32_C(0xffffffff) /* practical maximum */
+		},
+		.io = {
+			.base = UINT32_C(0),
+			.size = UINT32_C(0x10000)
+		}
 	}
 };
@@ -117,4 +130,12 @@
 	
 	return false;
+}
+
+static pio_window_t *rootpc_get_pio_window(ddf_fun_t *fnode)
+{
+	rootpc_fun_t *fun = rootpc_fun(fnode);
+	
+	assert(fun != NULL);
+	return &fun->pio_window;
 }
 
@@ -122,4 +143,8 @@
 	.get_resource_list = &rootpc_get_resources,
 	.enable_interrupt = &rootpc_enable_interrupt,
+};
+
+static pio_window_ops_t fun_pio_window_ops = {
+	.get_pio_window = &rootpc_get_pio_window
 };
 
@@ -197,4 +222,5 @@
 	ddf_log_init(NAME);
 	rootpc_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
+	rootpc_fun_ops.interfaces[PIO_WINDOW_DEV_IFACE] = &fun_pio_window_ops;
 }
 
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/nic/e1k/e1k.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -59,7 +59,7 @@
 #define E1000_DEFAULT_INTERRUPT_INTERVAL_USEC  250
 
-/* Must be power of 8 */ //TODO power or multiple? previous value was 128
-#define E1000_RX_FRAME_COUNT  8
-#define E1000_TX_FRAME_COUNT  8
+/* Must be power of 8 */
+#define E1000_RX_FRAME_COUNT  128
+#define E1000_TX_FRAME_COUNT  128
 
 #define E1000_RECEIVE_ADDRESS  16
@@ -129,20 +129,20 @@
 	
 	/** Physical tx ring address */
-	void *tx_ring_phys;
+	uintptr_t tx_ring_phys;
 	/** Virtual tx ring address */
 	void *tx_ring_virt;
 	
 	/** Ring of TX frames, physical address */
-	void **tx_frame_phys;
+	uintptr_t *tx_frame_phys;
 	/** Ring of TX frames, virtual address */
 	void **tx_frame_virt;
 	
 	/** Physical rx ring address */
-	void *rx_ring_phys;
+	uintptr_t rx_ring_phys;
 	/** Virtual rx ring address */
 	void *rx_ring_virt;
 	
 	/** Ring of RX frames, physical address */
-	void **rx_frame_phys;
+	uintptr_t *rx_frame_phys;
 	/** Ring of RX frames, virtual address */
 	void **rx_frame_virt;
@@ -1377,6 +1377,6 @@
 	int rc = dmamem_map_anonymous(
 	    E1000_RX_FRAME_COUNT * sizeof(e1000_rx_descriptor_t),
-	    AS_AREA_READ | AS_AREA_WRITE, 0, &e1000->rx_ring_phys,
-	    &e1000->rx_ring_virt);
+	    DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
+	    &e1000->rx_ring_phys, &e1000->rx_ring_virt);
 	if (rc != EOK)
 		return rc;
@@ -1387,9 +1387,9 @@
 	    (uint32_t) PTR_TO_U64(e1000->rx_ring_phys));
 	
-	e1000->rx_frame_phys =
-	    calloc(E1000_RX_FRAME_COUNT, sizeof(void *));
+	e1000->rx_frame_phys = (uintptr_t *)
+	    calloc(E1000_RX_FRAME_COUNT, sizeof(uintptr_t));
 	e1000->rx_frame_virt =
 	    calloc(E1000_RX_FRAME_COUNT, sizeof(void *));
-	if (e1000->rx_frame_phys == NULL || e1000->rx_frame_virt == NULL) {
+	if ((e1000->rx_frame_phys == NULL) || (e1000->rx_frame_virt == NULL)) {
 		rc = ENOMEM;
 		goto error;
@@ -1397,16 +1397,16 @@
 	
 	size_t i;
+	uintptr_t frame_phys;
 	void *frame_virt;
-	void *frame_phys;
 	
 	for (i = 0; i < E1000_RX_FRAME_COUNT; i++) {
-		rc = dmamem_map_anonymous(
-		    E1000_MAX_SEND_FRAME_SIZE, AS_AREA_READ | AS_AREA_WRITE,
-		    0, &frame_phys, &frame_virt);
+		rc = dmamem_map_anonymous(E1000_MAX_SEND_FRAME_SIZE,
+		    DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
+		    &frame_phys, &frame_virt);
 		if (rc != EOK)
 			goto error;
 		
+		e1000->rx_frame_phys[i] = frame_phys;
 		e1000->rx_frame_virt[i] = frame_virt;
-		e1000->rx_frame_phys[i] = frame_phys;
 	}
 	
@@ -1424,6 +1424,6 @@
 		if (e1000->rx_frame_virt[i] != NULL) {
 			dmamem_unmap_anonymous(e1000->rx_frame_virt[i]);
+			e1000->rx_frame_phys[i] = 0;
 			e1000->rx_frame_virt[i] = NULL;
-			e1000->rx_frame_phys[i] = NULL;
 		}
 	}
@@ -1436,5 +1436,5 @@
 	if (e1000->rx_frame_virt != NULL) {
 		free(e1000->rx_frame_virt);
-		e1000->rx_frame_phys = NULL;
+		e1000->rx_frame_virt = NULL;
 	}
 	
@@ -1454,12 +1454,13 @@
 	for (unsigned int offset = 0; offset < E1000_RX_FRAME_COUNT; offset++) {
 		dmamem_unmap_anonymous(e1000->rx_frame_virt[offset]);
+		e1000->rx_frame_phys[offset] = 0;
 		e1000->rx_frame_virt[offset] = NULL;
-		e1000->rx_frame_phys[offset] = NULL;
 	}
 	
 	free(e1000->rx_frame_virt);
-	free(e1000->rx_frame_phys);
+	
+	e1000->rx_frame_phys = NULL;
 	e1000->rx_frame_virt = NULL;
-	e1000->rx_frame_phys = NULL;
+	
 	dmamem_unmap_anonymous(e1000->rx_ring_virt);
 }
@@ -1569,6 +1570,7 @@
 	fibril_mutex_lock(&e1000->tx_lock);
 	
-	e1000->tx_ring_phys = NULL;
+	e1000->tx_ring_phys = 0;
 	e1000->tx_ring_virt = NULL;
+	
 	e1000->tx_frame_phys = NULL;
 	e1000->tx_frame_virt = NULL;
@@ -1576,6 +1578,6 @@
 	int rc = dmamem_map_anonymous(
 	    E1000_TX_FRAME_COUNT * sizeof(e1000_tx_descriptor_t),
-	    AS_AREA_READ | AS_AREA_WRITE, 0, &e1000->tx_ring_phys,
-	    &e1000->tx_ring_virt);
+	    DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
+	    &e1000->tx_ring_phys, &e1000->tx_ring_virt);
 	if (rc != EOK)
 		goto error;
@@ -1584,8 +1586,10 @@
 	    E1000_TX_FRAME_COUNT * sizeof(e1000_tx_descriptor_t));
 	
-	e1000->tx_frame_phys = calloc(E1000_TX_FRAME_COUNT, sizeof(void *));
-	e1000->tx_frame_virt = calloc(E1000_TX_FRAME_COUNT, sizeof(void *));
-
-	if (e1000->tx_frame_phys == NULL || e1000->tx_frame_virt == NULL) {
+	e1000->tx_frame_phys = (uintptr_t *)
+	    calloc(E1000_TX_FRAME_COUNT, sizeof(uintptr_t));
+	e1000->tx_frame_virt =
+	    calloc(E1000_TX_FRAME_COUNT, sizeof(void *));
+
+	if ((e1000->tx_frame_phys == NULL) || (e1000->tx_frame_virt == NULL)) {
 		rc = ENOMEM;
 		goto error;
@@ -1593,6 +1597,6 @@
 	
 	for (i = 0; i < E1000_TX_FRAME_COUNT; i++) {
-		rc = dmamem_map_anonymous(
-		    E1000_MAX_SEND_FRAME_SIZE, AS_AREA_READ | AS_AREA_WRITE,
+		rc = dmamem_map_anonymous(E1000_MAX_SEND_FRAME_SIZE,
+		    DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE,
 		    0, &e1000->tx_frame_phys[i], &e1000->tx_frame_virt[i]);
 		if (rc != EOK)
@@ -1616,10 +1620,10 @@
 	}
 	
-	if (e1000->tx_frame_phys != NULL && e1000->tx_frame_virt != NULL) {
+	if ((e1000->tx_frame_phys != NULL) && (e1000->tx_frame_virt != NULL)) {
 		for (i = 0; i < E1000_TX_FRAME_COUNT; i++) {
 			if (e1000->tx_frame_virt[i] != NULL) {
 				dmamem_unmap_anonymous(e1000->tx_frame_virt[i]);
+				e1000->tx_frame_phys[i] = 0;
 				e1000->tx_frame_virt[i] = NULL;
-				e1000->tx_frame_phys[i] = NULL;
 			}
 		}
@@ -1633,5 +1637,5 @@
 	if (e1000->tx_frame_virt != NULL) {
 		free(e1000->tx_frame_virt);
-		e1000->tx_frame_phys = NULL;
+		e1000->tx_frame_virt = NULL;
 	}
 	
@@ -1650,6 +1654,6 @@
 	for (i = 0; i < E1000_TX_FRAME_COUNT; i++) {
 		dmamem_unmap_anonymous(e1000->tx_frame_virt[i]);
+		e1000->tx_frame_phys[i] = 0;
 		e1000->tx_frame_virt[i] = NULL;
-		e1000->tx_frame_phys[i] = NULL;
 	}
 	
@@ -1661,5 +1665,5 @@
 	if (e1000->tx_frame_virt != NULL) {
 		free(e1000->tx_frame_virt);
-		e1000->tx_frame_phys = NULL;
+		e1000->tx_frame_virt = NULL;
 	}
 	
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -1144,6 +1144,6 @@
 	ddf_msg(LVL_DEBUG, "Creating buffers");
 
-	rc = dmamem_map_anonymous(TX_PAGES * PAGE_SIZE, AS_AREA_WRITE, 0,
-	    &rtl8139->tx_buff_phys, &rtl8139->tx_buff_virt);
+	rc = dmamem_map_anonymous(TX_PAGES * PAGE_SIZE, DMAMEM_4GiB,
+	    AS_AREA_WRITE, 0, &rtl8139->tx_buff_phys, &rtl8139->tx_buff_virt);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Can not allocate transmitter buffers.");
@@ -1164,6 +1164,6 @@
 	    RxBUF_TOT_LENGTH);
 
-	rc = dmamem_map_anonymous(RxBUF_TOT_LENGTH, AS_AREA_READ, 0,
-	    &rtl8139->rx_buff_phys, &rtl8139->rx_buff_virt);
+	rc = dmamem_map_anonymous(RxBUF_TOT_LENGTH, DMAMEM_4GiB,
+	    AS_AREA_READ, 0, &rtl8139->rx_buff_phys, &rtl8139->rx_buff_virt);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Can not allocate receive buffer.");
Index: uspace/drv/nic/rtl8139/driver.h
===================================================================
--- uspace/drv/nic/rtl8139/driver.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/drv/nic/rtl8139/driver.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -100,5 +100,5 @@
 	 *  Each buffer takes 2kB
 	 */
-	void *tx_buff_phys;
+	uintptr_t tx_buff_phys;
 	void *tx_buff_virt;
 
@@ -117,5 +117,5 @@
 
 	/** Buffer for receiving frames */
-	void *rx_buff_phys;
+	uintptr_t rx_buff_phys;
 	void *rx_buff_virt;
 
Index: uspace/lib/block/block.c
===================================================================
--- uspace/lib/block/block.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/block/block.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -93,6 +93,5 @@
 	fibril_mutex_lock(&dcl_lock);
 	
-	list_foreach(dcl, cur) {
-		devcon_t *devcon = list_get_instance(cur, devcon_t, link);
+	list_foreach(dcl, link, devcon_t, devcon) {
 		if (devcon->service_id == service_id) {
 			fibril_mutex_unlock(&dcl_lock);
@@ -124,6 +123,5 @@
 	
 	fibril_mutex_lock(&dcl_lock);
-	list_foreach(dcl, cur) {
-		devcon_t *d = list_get_instance(cur, devcon_t, link);
+	list_foreach(dcl, link, devcon_t, d) {
 		if (d->service_id == service_id) {
 			fibril_mutex_unlock(&dcl_lock);
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/Makefile	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -65,7 +65,9 @@
 	generic/cfg.c \
 	generic/clipboard.c \
+	generic/corecfg.c \
 	generic/devman.c \
 	generic/device/hw_res.c \
 	generic/device/hw_res_parsed.c \
+	generic/device/pio_window.c \
 	generic/device/char_dev.c \
 	generic/device/clock_dev.c \
Index: uspace/lib/c/generic/adt/hash_table.c
===================================================================
--- uspace/lib/c/generic/adt/hash_table.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/generic/adt/hash_table.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -227,10 +227,9 @@
 	
 	/* Check for duplicates. */
-	list_foreach(h->bucket[idx], cur) {
+	list_foreach(h->bucket[idx], link, ht_link_t, cur_link) {
 		/* 
 		 * We could filter out items using their hashes first, but 
 		 * calling equal() might very well be just as fast.
 		 */
-		ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
 		if (h->op->equal(cur_link, item))
 			return false;
@@ -258,6 +257,5 @@
 	size_t idx = h->op->key_hash(key) % h->bucket_cnt;
 
-	list_foreach(h->bucket[idx], cur) {
-		ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
+	list_foreach(h->bucket[idx], link, ht_link_t, cur_link) {
 		/* 
 		 * Is this is the item we are looking for? We could have first 
Index: uspace/lib/c/generic/adt/list.c
===================================================================
--- uspace/lib/c/generic/adt/list.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/generic/adt/list.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -102,6 +102,8 @@
 	unsigned int count = 0;
 	
-	list_foreach(*list, link) {
+	link_t *link = list_first(list);
+	while (link != NULL) {
 		count++;
+		link = list_next(link, list);
 	}
 	
Index: uspace/lib/c/generic/cfg.c
===================================================================
--- uspace/lib/c/generic/cfg.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/generic/cfg.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -83,7 +83,5 @@
 		return true;
 	
-	list_foreach(data->sections, link) {
-		const cfg_section_t *section = cfg_section_instance(link);
-		
+	cfg_file_foreach(data, section) {
 		if (!list_empty(&section->entries))
 			return false;
@@ -413,7 +411,5 @@
 const cfg_section_t *cfg_find_section(const cfg_file_t *data, const char *title)
 {
-	list_foreach(data->sections, link) {
-		const cfg_section_t *section = cfg_section_instance(link);
-		
+	cfg_file_foreach(data, section) {
 		if (str_cmp(section->title, title) == 0)
 			return section;
@@ -434,7 +430,5 @@
 const char *cfg_find_value(const cfg_section_t *section, const char *key)
 {
-	list_foreach(section->entries, link) {
-		const cfg_entry_t *entry = cfg_entry_instance(link);
-		
+	cfg_section_foreach(section, entry) {
 		if (str_cmp(entry->key, key) == 0)
 			return entry->value;
Index: uspace/lib/c/generic/corecfg.c
===================================================================
--- uspace/lib/c/generic/corecfg.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/lib/c/generic/corecfg.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013 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 <async.h>
+#include <assert.h>
+#include <corecfg.h>
+#include <errno.h>
+#include <ipc/corecfg.h>
+#include <ipc/services.h>
+#include <loc.h>
+#include <stdlib.h>
+
+static async_sess_t *corecfg_sess = NULL;
+
+int corecfg_init(void)
+{
+	service_id_t corecfg_svc;
+	int rc;
+
+	assert(corecfg_sess == NULL);
+
+	rc = loc_service_get_id(SERVICE_NAME_CORECFG, &corecfg_svc,
+	    IPC_FLAG_BLOCKING);
+	if (rc != EOK)
+		return ENOENT;
+
+	corecfg_sess = loc_service_connect(EXCHANGE_SERIALIZE, corecfg_svc,
+	    IPC_FLAG_BLOCKING);
+	if (corecfg_sess == NULL)
+		return ENOENT;
+
+	return EOK;
+}
+
+/** Get core dump enable status. */
+int corecfg_get_enable(bool *renable)
+{
+	async_exch_t *exch = async_exchange_begin(corecfg_sess);
+	sysarg_t enable;
+
+	int rc = async_req_0_1(exch, CORECFG_GET_ENABLE, &enable);
+
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		return rc;
+
+	*renable = enable;
+	return EOK;
+}
+
+/** Enable or disable core dumps. */
+int corecfg_set_enable(bool enable)
+{
+	async_exch_t *exch = async_exchange_begin(corecfg_sess);
+	int rc = async_req_1_0(exch, CORECFG_SET_ENABLE, (sysarg_t) enable);
+
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/ddi.c
===================================================================
--- uspace/lib/c/generic/ddi.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/generic/ddi.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -76,5 +76,5 @@
  *
  */
-int physmem_map(void *phys, size_t pages, unsigned int flags, void **virt)
+int physmem_map(uintptr_t phys, size_t pages, unsigned int flags, void **virt)
 {
 	return __SYSCALL5(SYS_PHYSMEM_MAP, (sysarg_t) phys,
@@ -83,5 +83,5 @@
 
 int dmamem_map(void *virt, size_t size, unsigned int map_flags,
-    unsigned int flags, void **phys)
+    unsigned int flags, uintptr_t *phys)
 {
 	return (int) __SYSCALL6(SYS_DMAMEM_MAP, (sysarg_t) size,
@@ -90,7 +90,9 @@
 }
 
-int dmamem_map_anonymous(size_t size, unsigned int map_flags,
-    unsigned int flags, void **phys, void **virt)
-{
+int dmamem_map_anonymous(size_t size, uintptr_t constraint,
+    unsigned int map_flags, unsigned int flags, uintptr_t *phys, void **virt)
+{
+	*phys = constraint;
+	
 	return (int) __SYSCALL6(SYS_DMAMEM_MAP, (sysarg_t) size,
 	    (sysarg_t) map_flags, (sysarg_t) flags | DMAMEM_FLAGS_ANONYMOUS,
@@ -158,8 +160,8 @@
 	if (!virt)
 		return EINVAL;
-
-	void *phys_frame =
-	    (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
-	size_t offset = pio_addr - phys_frame;
+	
+	uintptr_t phys_frame =
+	    ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
+	size_t offset = (uintptr_t) pio_addr - phys_frame;
 	size_t pages = SIZE2PAGES(offset + size);
 	
Index: uspace/lib/c/generic/device/pio_window.c
===================================================================
--- uspace/lib/c/generic/device/pio_window.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/lib/c/generic/device/pio_window.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+
+ /** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <device/pio_window.h>
+#include <errno.h>
+#include <async.h>
+
+int pio_window_get(async_sess_t *sess, pio_window_t *pio_win)
+{
+	int rc;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return ENOMEM;
+
+	rc = async_req_1_0(exch, DEV_IFACE_ID(PIO_WINDOW_DEV_IFACE),
+	    PIO_WINDOW_GET);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		return rc;
+	}
+	
+	rc = async_data_read_start(exch, pio_win, sizeof(*pio_win));
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** @}
+ */
+
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/generic/devman.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2007 Josef Cejka
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2013 Jiri Svoboda
  * Copyright (c) 2010 Lenka Trochtova
  * All rights reserved.
@@ -230,9 +230,5 @@
 	}
 	
-	match_id_t *match_id = NULL;
-	
-	list_foreach(match_ids->ids, link) {
-		match_id = list_get_instance(link, match_id_t, link);
-		
+	list_foreach(match_ids->ids, link, match_id_t, match_id) {
 		ipc_call_t answer2;
 		aid_t req2 = async_send_1(exch, DEVMAN_ADD_MATCH_ID,
@@ -405,6 +401,6 @@
 }
 
-static int devman_get_str_internal(sysarg_t method, sysarg_t arg1, char *buf,
-    size_t buf_size)
+static int devman_get_str_internal(sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t *r1, char *buf, size_t buf_size)
 {
 	async_exch_t *exch;
@@ -416,5 +412,5 @@
 	
 	ipc_call_t answer;
-	aid_t req = async_send_1(exch, method, arg1, &answer);
+	aid_t req = async_send_2(exch, method, arg1, arg2, &answer);
 	aid_t dreq = async_data_read(exch, buf, buf_size - 1, &dreply);
 	async_wait_for(dreq, &dretval);
@@ -434,4 +430,6 @@
 	}
 	
+	if (r1 != NULL)
+		*r1 = IPC_GET_ARG1(answer);
 	act_size = IPC_GET_ARG2(dreply);
 	assert(act_size <= buf_size - 1);
@@ -443,18 +441,33 @@
 int devman_fun_get_path(devman_handle_t handle, char *buf, size_t buf_size)
 {
-	return devman_get_str_internal(DEVMAN_FUN_GET_PATH, handle, buf,
-	    buf_size);
+	return devman_get_str_internal(DEVMAN_FUN_GET_PATH, handle, 0, NULL,
+	    buf, buf_size);
+}
+
+int devman_fun_get_match_id(devman_handle_t handle, size_t index, char *buf,
+    size_t buf_size, unsigned int *rscore)
+{
+	int rc;
+	sysarg_t score = 0;
+
+	rc = devman_get_str_internal(DEVMAN_FUN_GET_MATCH_ID, handle, index,
+	    &score, buf, buf_size);
+	if (rc != EOK)
+		return rc;
+
+	*rscore = score;
+	return rc;
 }
 
 int devman_fun_get_name(devman_handle_t handle, char *buf, size_t buf_size)
 {
-	return devman_get_str_internal(DEVMAN_FUN_GET_NAME, handle, buf,
-	    buf_size);
+	return devman_get_str_internal(DEVMAN_FUN_GET_NAME, handle, 0, NULL,
+	    buf, buf_size);
 }
 
 int devman_fun_get_driver_name(devman_handle_t handle, char *buf, size_t buf_size)
 {
-	return devman_get_str_internal(DEVMAN_FUN_GET_DRIVER_NAME, handle, buf,
-	    buf_size);
+	return devman_get_str_internal(DEVMAN_FUN_GET_DRIVER_NAME, handle, 0,
+	    NULL, buf, buf_size);
 }
 
@@ -583,4 +596,17 @@
 }
 
+int devman_dev_get_parent(devman_handle_t devh, devman_handle_t *funh)
+{
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	sysarg_t retval = async_req_1_1(exch, DEVMAN_DEV_GET_PARENT,
+	    devh, funh);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
+}
+
 int devman_fun_sid_to_handle(service_id_t sid, devman_handle_t *handle)
 {
@@ -596,4 +622,103 @@
 }
 
+int devman_get_drivers(devman_handle_t **drvs,
+    size_t *count)
+{
+	return devman_get_handles_internal(DEVMAN_GET_DRIVERS, 0, drvs, count);
+}
+
+int devman_driver_get_devices(devman_handle_t drvh, devman_handle_t **devs,
+    size_t *count)
+{
+	return devman_get_handles_internal(DEVMAN_DRIVER_GET_DEVICES,
+	    drvh, devs, count);
+}
+
+int devman_driver_get_handle(const char *drvname, devman_handle_t *handle)
+{
+	async_exch_t *exch;
+
+	exch = devman_exchange_begin(DEVMAN_CLIENT);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, DEVMAN_DRIVER_GET_HANDLE, &answer);
+	sysarg_t retval = async_data_write_start(exch, drvname,
+	    str_size(drvname));
+	
+	devman_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_forget(req);
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		if (handle != NULL)
+			*handle = (devman_handle_t) -1;
+		
+		return retval;
+	}
+	
+	if (handle != NULL)
+		*handle = (devman_handle_t) IPC_GET_ARG1(answer);
+	
+	return retval;
+}
+
+int devman_driver_get_match_id(devman_handle_t handle, size_t index, char *buf,
+    size_t buf_size, unsigned int *rscore)
+{
+	int rc;
+	sysarg_t score = 0;
+
+	rc = devman_get_str_internal(DEVMAN_DRIVER_GET_MATCH_ID, handle, index,
+	    &score, buf, buf_size);
+	if (rc != EOK)
+		return rc;
+
+	*rscore = score;
+	return rc;
+}
+
+int devman_driver_get_name(devman_handle_t handle, char *buf, size_t buf_size)
+{
+	return devman_get_str_internal(DEVMAN_DRIVER_GET_NAME, handle, 0, NULL,
+	    buf, buf_size);
+}
+
+int devman_driver_get_state(devman_handle_t drvh, driver_state_t *rstate)
+{
+	sysarg_t state;
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	int rc = async_req_1_1(exch, DEVMAN_DRIVER_GET_STATE, drvh,
+	    &state);
+	
+	devman_exchange_end(exch);
+	if (rc != EOK)
+		return rc;
+
+	*rstate = state;
+	return rc;
+}
+
+int devman_driver_load(devman_handle_t drvh)
+{
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	int rc = async_req_1_0(exch, DEVMAN_DRIVER_LOAD, drvh);
+	
+	devman_exchange_end(exch);
+	return rc;
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/futex.c
===================================================================
--- uspace/lib/c/generic/futex.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/generic/futex.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -35,4 +35,5 @@
 #include <futex.h>
 #include <atomic.h>
+#include <libarch/barrier.h>
 #include <libc.h>
 #include <sys/types.h>
@@ -59,5 +60,10 @@
 int futex_trydown(futex_t *futex)
 {
-	return cas(futex, 1, 0);
+	int rc;
+
+	rc = cas(futex, 1, 0);
+	CS_ENTER_BARRIER();
+
+	return rc;
 }
 
@@ -73,5 +79,9 @@
 int futex_down(futex_t *futex)
 {
-	if ((atomic_signed_t) atomic_predec(futex) < 0)
+	atomic_signed_t nv;
+
+	nv = (atomic_signed_t) atomic_predec(futex);
+	CS_ENTER_BARRIER();
+	if (nv < 0)
 		return __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->count);
 	
@@ -89,4 +99,6 @@
 int futex_up(futex_t *futex)
 {
+	CS_LEAVE_BARRIER();
+
 	if ((atomic_signed_t) atomic_postinc(futex) < 0)
 		return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->count);
Index: uspace/lib/c/generic/pio_trace.c
===================================================================
--- uspace/lib/c/generic/pio_trace.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/generic/pio_trace.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -95,8 +95,5 @@
 	pio_regions_t *regions = get_regions();
 	fibril_rwlock_read_lock(&regions->guard);
-	list_foreach(regions->list, it) {
-		assert(it);
-		region_t *reg = region_instance(it);
-		assert(reg);
+	list_foreach(regions->list, link, region_t, reg) {
 		if ((r >= reg->base) && (r < reg->base + reg->size)) {
 			if (reg->log)
@@ -131,10 +128,8 @@
 	fibril_rwlock_write_lock(&regions->guard);
 	list_foreach_safe(regions->list, it, next) {
-		assert(it);
 		region_t *reg = region_instance(it);
-		assert(reg);
 		if (r >= reg->base && (r < reg->base + reg->size)) {
-				list_remove(&reg->link);
-				region_destroy(reg);
+			list_remove(&reg->link);
+			region_destroy(reg);
 		}
 	}
Index: uspace/lib/c/generic/time.c
===================================================================
--- uspace/lib/c/generic/time.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/generic/time.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -556,6 +556,6 @@
 		
 		void *addr;
-		rc = physmem_map((void *) faddr, 1,
-		    AS_AREA_READ | AS_AREA_CACHEABLE, &addr);
+		rc = physmem_map(faddr, 1, AS_AREA_READ | AS_AREA_CACHEABLE,
+		    &addr);
 		if (rc != EOK) {
 			as_area_destroy(addr);
Index: uspace/lib/c/include/adt/list.h
===================================================================
--- uspace/lib/c/include/adt/list.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/include/adt/list.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2001-2004 Jakub Jermar
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2013 Jiri Svoboda
  * All rights reserved.
  *
@@ -65,12 +65,14 @@
 
 #define list_get_instance(link, type, member) \
-	((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member))))
-
-#define list_foreach(list, iterator) \
-	for (link_t *iterator = (list).head.next; \
-	    iterator != &(list).head; iterator = iterator->next)
+	((type *) (((void *)(link)) - list_link_to_void(&(((type *) NULL)->member))))
+
+#define list_foreach(list, member, itype, iterator) \
+	for (itype *iterator = NULL; iterator == NULL; iterator = (itype *) 1) \
+	    for (link_t *_link = (list).head.next; \
+	    iterator = list_get_instance(_link, itype, member), \
+	    _link != &(list).head; _link = _link->next)
 
 /** Unlike list_foreach(), allows removing items while traversing a list.
- * 
+ *
  * @code
  * list_t mylist;
@@ -238,5 +240,31 @@
 static inline link_t *list_last(list_t *list)
 {
-	return ((list->head.prev == &list->head) ? NULL : list->head.prev);
+	return (list->head.prev == &list->head) ? NULL : list->head.prev;
+}
+
+/** Get next item in list.
+ *
+ * @param link Current item link
+ * @param list List containing @a link
+ *
+ * @return Next item or NULL if @a link is the last item.
+ *
+ */
+static inline link_t *list_next(link_t *link, const list_t *list)
+{
+	return (link->next == &list->head) ? NULL : link->next;
+}
+
+/** Get previous item in list.
+ *
+ * @param link Current item link
+ * @param list List containing @a link
+ *
+ * @return Previous item or NULL if @a link is the first item.
+ *
+ */
+static inline link_t *list_prev(link_t *link, const list_t *list)
+{
+	return (link->prev == &list->head) ? NULL : link->prev;
 }
 
@@ -308,12 +336,23 @@
 	unsigned int cnt = 0;
 	
-	list_foreach(*list, link) {
+	link_t *link = list_first(list);
+	while (link != NULL) {
 		if (cnt == n)
 			return link;
 		
 		cnt++;
+		link = list_next(link, list);
 	}
 	
 	return NULL;
+}
+
+/** Verify that argument type is a pointer to link_t (at compile time).
+ *
+ * This can be used to check argument type in a macro.
+ */
+static inline const void *list_link_to_void(const link_t *link)
+{
+	return link;
 }
 
Index: uspace/lib/c/include/cfg.h
===================================================================
--- uspace/lib/c/include/cfg.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/include/cfg.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -80,5 +80,5 @@
 
 #define cfg_file_foreach(file, cur) \
-	list_foreach((file)->sections, (cur))
+	list_foreach((file)->sections, link, const cfg_section_t, (cur))
 
 #define cfg_section_instance(cur) \
@@ -86,5 +86,5 @@
 
 #define cfg_section_foreach(section, cur) \
-	list_foreach((section)->entries, (cur))
+	list_foreach((section)->entries, link, const cfg_entry_t, (cur))
 
 #define cfg_entry_instance(cur) \
Index: uspace/lib/c/include/corecfg.h
===================================================================
--- uspace/lib/c/include/corecfg.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/lib/c/include/corecfg.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_INET_INETCFG_H_
+#define LIBC_INET_INETCFG_H_
+
+#include <stdbool.h>
+
+extern int corecfg_init(void);
+extern int corecfg_set_enable(bool);
+extern int corecfg_get_enable(bool *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ddi.h
===================================================================
--- uspace/lib/c/include/ddi.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/include/ddi.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -42,11 +42,14 @@
 #include <task.h>
 
+#define DMAMEM_16MiB  ((uintptr_t) UINT64_C(0xffffffffff000000))
+#define DMAMEM_4GiB   ((uintptr_t) UINT64_C(0xffffffff00000000))
+
 extern int device_assign_devno(void);
 
-extern int physmem_map(void *, size_t, unsigned int, void **);
+extern int physmem_map(uintptr_t, size_t, unsigned int, void **);
 
-extern int dmamem_map(void *, size_t, unsigned int, unsigned int, void **);
-extern int dmamem_map_anonymous(size_t, unsigned int, unsigned int, void **,
-    void **);
+extern int dmamem_map(void *, size_t, unsigned int, unsigned int, uintptr_t *);
+extern int dmamem_map_anonymous(size_t, uintptr_t, unsigned int, unsigned int,
+    uintptr_t *, void **);
 extern int dmamem_unmap(void *, size_t);
 extern int dmamem_unmap_anonymous(void *);
@@ -69,6 +72,6 @@
 extern uint32_t pio_read_32(const ioport32_t *);
 
-static inline uint8_t pio_change_8(
-    ioport8_t *reg, uint8_t val, uint8_t mask, useconds_t delay)
+static inline uint8_t pio_change_8(ioport8_t *reg, uint8_t val, uint8_t mask,
+    useconds_t delay)
 {
 	uint8_t v = pio_read_8(reg);
@@ -78,6 +81,6 @@
 }
 
-static inline uint16_t pio_change_16(
-    ioport16_t *reg, uint16_t val, uint16_t mask, useconds_t delay)
+static inline uint16_t pio_change_16(ioport16_t *reg, uint16_t val,
+    uint16_t mask, useconds_t delay)
 {
 	uint16_t v = pio_read_16(reg);
@@ -87,6 +90,6 @@
 }
 
-static inline uint32_t pio_change_32(
-    ioport32_t *reg, uint32_t val, uint32_t mask, useconds_t delay)
+static inline uint32_t pio_change_32(ioport32_t *reg, uint32_t val,
+    uint32_t mask, useconds_t delay)
 {
 	uint32_t v = pio_read_32(reg);
Index: uspace/lib/c/include/device/pio_window.h
===================================================================
--- uspace/lib/c/include/device/pio_window.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/lib/c/include/device/pio_window.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_DEVICE_PIO_WINDOW_H_
+#define LIBC_DEVICE_PIO_WINDOW_H_
+
+#include <ipc/dev_iface.h>
+#include <async.h>
+
+/** PIO_WINDOW provider interface */
+typedef enum {
+	PIO_WINDOW_GET = 0,
+} pio_window_method_t;
+
+typedef struct {
+	struct {
+		uintptr_t base;
+		size_t size;
+	} mem, io;
+} pio_window_t;
+
+extern int pio_window_get(async_sess_t *, pio_window_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/devman.h
===================================================================
--- uspace/lib/c/include/devman.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/include/devman.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -61,6 +61,9 @@
     unsigned int);
 extern int devman_fun_get_child(devman_handle_t, devman_handle_t *);
+extern int devman_dev_get_parent(devman_handle_t, devman_handle_t *);
 extern int devman_dev_get_functions(devman_handle_t, devman_handle_t **,
     size_t *);
+extern int devman_fun_get_match_id(devman_handle_t, size_t, char *, size_t,
+    unsigned int *);
 extern int devman_fun_get_name(devman_handle_t, char *, size_t);
 extern int devman_fun_get_driver_name(devman_handle_t, char *, size_t);
@@ -71,4 +74,13 @@
 extern int devman_add_device_to_category(devman_handle_t, const char *);
 extern int devman_fun_sid_to_handle(service_id_t, devman_handle_t *);
+extern int devman_get_drivers(devman_handle_t **, size_t *);
+extern int devman_driver_get_devices(devman_handle_t, devman_handle_t **,
+    size_t *);
+extern int devman_driver_get_handle(const char *, devman_handle_t *);
+extern int devman_driver_get_match_id(devman_handle_t, size_t, char *, size_t,
+    unsigned int *);
+extern int devman_driver_get_name(devman_handle_t, char *, size_t);
+extern int devman_driver_get_state(devman_handle_t, driver_state_t *);
+extern int devman_driver_load(devman_handle_t);
 
 #endif
Index: uspace/lib/c/include/ipc/corecfg.h
===================================================================
--- uspace/lib/c/include/ipc/corecfg.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/lib/c/include/ipc/corecfg.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013 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 libcipc
+ * @{
+ */
+
+#ifndef LIBC_IPC_CORECFG_H_
+#define LIBC_IPC_CORECFG_H_
+
+#include <ipc/common.h>
+
+typedef enum {
+	CORECFG_GET_ENABLE = IPC_FIRST_USER_METHOD,
+	CORECFG_SET_ENABLE
+} corecfg_request_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -36,4 +36,5 @@
 typedef enum {
 	HW_RES_DEV_IFACE = 0,
+	PIO_WINDOW_DEV_IFACE,
 
 	/** Character device interface */
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/include/ipc/devman.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -42,4 +42,18 @@
 
 typedef sysarg_t devman_handle_t;
+
+typedef enum {
+	/** Driver has not been started. */
+	DRIVER_NOT_STARTED = 0,
+	
+	/**
+	 * Driver has been started, but has not registered as running and ready
+	 * to receive requests.
+	 */
+	DRIVER_STARTING,
+	
+	/** Driver is running and prepared to serve incomming requests. */
+	DRIVER_RUNNING
+} driver_state_t;
 
 typedef enum {
@@ -155,5 +169,7 @@
 	DEVMAN_DEVICE_GET_HANDLE = IPC_FIRST_USER_METHOD,
 	DEVMAN_DEV_GET_FUNCTIONS,
+	DEVMAN_DEV_GET_PARENT,
 	DEVMAN_FUN_GET_CHILD,
+	DEVMAN_FUN_GET_MATCH_ID,
 	DEVMAN_FUN_GET_NAME,
 	DEVMAN_FUN_GET_DRIVER_NAME,
@@ -161,5 +177,12 @@
 	DEVMAN_FUN_OFFLINE,
 	DEVMAN_FUN_GET_PATH,
-	DEVMAN_FUN_SID_TO_HANDLE
+	DEVMAN_FUN_SID_TO_HANDLE,
+	DEVMAN_GET_DRIVERS,
+	DEVMAN_DRIVER_GET_DEVICES,
+	DEVMAN_DRIVER_GET_HANDLE,
+	DEVMAN_DRIVER_GET_MATCH_ID,
+	DEVMAN_DRIVER_GET_NAME,
+	DEVMAN_DRIVER_GET_STATE,
+	DEVMAN_DRIVER_LOAD
 } client_to_devman_t;
 
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/c/include/ipc/services.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -53,4 +53,5 @@
 } services_t;
 
+#define SERVICE_NAME_CORECFG	"corecfg"
 #define SERVICE_NAME_DNSR       "net/dnsr"
 #define SERVICE_NAME_INET       "net/inet"
Index: uspace/lib/draw/drawctx.c
===================================================================
--- uspace/lib/draw/drawctx.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/draw/drawctx.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -188,6 +188,5 @@
 	 * transferred to the original surface. */
 
-	list_foreach(*((list_t *) path), link) {
-		path_step_t *step = (path_step_t *) link;
+	list_foreach(*((list_t *) path), link, path_step_t, step) {
 		switch (step->type) {
 		case PATH_STEP_MOVETO:
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/drv/Makefile	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -41,4 +41,5 @@
 	generic/remote_audio_pcm.c \
 	generic/remote_hw_res.c \
+	generic/remote_pio_window.c \
 	generic/remote_char_dev.c \
 	generic/remote_graph_dev.c \
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/drv/generic/dev_iface.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -40,4 +40,5 @@
 #include "dev_iface.h"
 #include "remote_hw_res.h"
+#include "remote_pio_window.h"
 #include "remote_char_dev.h"
 #include "remote_clock_dev.h"
@@ -58,4 +59,5 @@
 		[AUDIO_PCM_BUFFER_IFACE] = &remote_audio_pcm_iface,
 		[HW_RES_DEV_IFACE] = &remote_hw_res_iface,
+		[PIO_WINDOW_DEV_IFACE] = &remote_pio_window_iface,
 		[CHAR_DEV_IFACE] = &remote_char_dev_iface,
 		[GRAPH_DEV_IFACE] = &remote_graph_dev_iface,
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/drv/generic/driver.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -98,10 +98,7 @@
 static ddf_dev_t *driver_get_device(devman_handle_t handle)
 {
-	ddf_dev_t *dev = NULL;
-	
 	assert(fibril_mutex_is_locked(&devices_mutex));
 	
-	list_foreach(devices, link) {
-		dev = list_get_instance(link, ddf_dev_t, link);
+	list_foreach(devices, link, ddf_dev_t, dev) {
 		if (dev->handle == handle)
 			return dev;
@@ -113,10 +110,7 @@
 static ddf_fun_t *driver_get_function(devman_handle_t handle)
 {
-	ddf_fun_t *fun = NULL;
-	
 	assert(fibril_mutex_is_locked(&functions_mutex));
 	
-	list_foreach(functions, link) {
-		fun = list_get_instance(link, ddf_fun_t, link);
+	list_foreach(functions, link, ddf_fun_t, fun) {
 		if (fun->handle == handle)
 			return fun;
Index: uspace/lib/drv/generic/interrupt.c
===================================================================
--- uspace/lib/drv/generic/interrupt.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/drv/generic/interrupt.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -138,10 +138,7 @@
     interrupt_context_list_t *list, int id)
 {
-	interrupt_context_t *ctx;
-	
-	fibril_mutex_lock(&list->mutex);
-	
-	list_foreach(list->contexts, link) {
-		ctx = list_get_instance(link, interrupt_context_t, link);
+	fibril_mutex_lock(&list->mutex);
+	
+	list_foreach(list->contexts, link, interrupt_context_t, ctx) {
 		if (ctx->id == id) {
 			fibril_mutex_unlock(&list->mutex);
@@ -157,10 +154,7 @@
     interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
 {
-	interrupt_context_t *ctx;
-	
-	fibril_mutex_lock(&list->mutex);
-	
-	list_foreach(list->contexts, link) {
-		ctx = list_get_instance(link, interrupt_context_t, link);
+	fibril_mutex_lock(&list->mutex);
+	
+	list_foreach(list->contexts, link, interrupt_context_t, ctx) {
 		if (ctx->irq == irq && ctx->dev == dev) {
 			fibril_mutex_unlock(&list->mutex);
Index: uspace/lib/drv/generic/remote_pio_window.c
===================================================================
--- uspace/lib/drv/generic/remote_pio_window.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/lib/drv/generic/remote_pio_window.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+
+#include "ops/pio_window.h"
+#include "ddf/driver.h"
+
+static void remote_pio_window_get(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+
+static remote_iface_func_ptr_t remote_pio_window_iface_ops [] = {
+	[PIO_WINDOW_GET] = &remote_pio_window_get
+};
+
+remote_iface_t remote_pio_window_iface = {
+	.method_count = sizeof(remote_pio_window_iface_ops) /
+	    sizeof(remote_iface_func_ptr_t),
+	.methods = remote_pio_window_iface_ops
+};
+
+static void remote_pio_window_get(ddf_fun_t *fun, void *ops,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	pio_window_ops_t *pio_win_ops = (pio_window_ops_t *) ops;
+	size_t len;
+
+	if (!pio_win_ops->get_pio_window) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	pio_window_t *pio_window = pio_win_ops->get_pio_window(fun);
+	if (!pio_window) {
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	async_answer_0(callid, EOK);
+
+	if (!async_data_read_receive(&callid, &len)) {
+		/* Protocol error - the recipient is not accepting data */
+		return;
+	}
+
+	async_data_read_finalize(callid, pio_window, len);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/ops/pio_window.h
===================================================================
--- uspace/lib/drv/include/ops/pio_window.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/lib/drv/include/ops/pio_window.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_OPS_PIO_WINDOW_H_
+#define LIBDRV_OPS_PIO_WINDOW_H_
+
+#include <device/pio_window.h>
+#include <sys/types.h>
+#include "../ddf/driver.h"
+
+typedef struct {
+	pio_window_t *(* get_pio_window)(ddf_fun_t *);
+} pio_window_ops_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/remote_pio_window.h
===================================================================
--- uspace/lib/drv/include/remote_pio_window.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/lib/drv/include/remote_pio_window.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_PIO_WINDOW_H_
+#define LIBDRV_REMOTE_PIO_WINDOW_H_
+
+extern remote_iface_t remote_pio_window_iface;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/fs/libfs.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -942,8 +942,5 @@
 
 	fibril_mutex_lock(&instances_mutex);
-	list_foreach(instances_list, link) {
-		fs_instance_t *cur = list_get_instance(link, fs_instance_t,
-		    link);
-
+	list_foreach(instances_list, link, fs_instance_t, cur) {
 		if (cur->service_id == service_id) {
 			fibril_mutex_unlock(&instances_mutex);
@@ -968,8 +965,5 @@
 {
 	fibril_mutex_lock(&instances_mutex);
-	list_foreach(instances_list, link) {
-		fs_instance_t *inst = list_get_instance(link, fs_instance_t,
-		    link);
-
+	list_foreach(instances_list, link, fs_instance_t, inst) {
 		if (inst->service_id == service_id) {
 			*idp = inst->data;
@@ -985,8 +979,5 @@
 {
 	fibril_mutex_lock(&instances_mutex);
-	list_foreach(instances_list, link) {
-		fs_instance_t *inst = list_get_instance(link, fs_instance_t,
-		    link);
-
+	list_foreach(instances_list, link, fs_instance_t, inst) {
 		if (inst->service_id == service_id) {
 			list_remove(&inst->link);
Index: uspace/lib/graph/graph.c
===================================================================
--- uspace/lib/graph/graph.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/graph/graph.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -165,8 +165,7 @@
 
 	fibril_mutex_lock(&visualizer_list_mtx);
-	list_foreach(visualizer_list, link) {
-		visualizer_t *cur = list_get_instance(link, visualizer_t, link);
-		if (cur->reg_svc_handle == handle) {
-			vs = cur;
+	list_foreach(visualizer_list, link, visualizer_t, vcur) {
+		if (vcur->reg_svc_handle == handle) {
+			vs = vcur;
 			break;
 		}
@@ -182,8 +181,7 @@
 
 	fibril_mutex_lock(&renderer_list_mtx);
-	list_foreach(renderer_list, link) {
-		renderer_t *cur = list_get_instance(link, renderer_t, link);
-		if (cur->reg_svc_handle == handle) {
-			rnd = cur;
+	list_foreach(renderer_list, link, renderer_t, rcur) {
+		if (rcur->reg_svc_handle == handle) {
+			rnd = rcur;
 			break;
 		}
@@ -322,6 +320,5 @@
 	fibril_mutex_lock(&vs->mode_mtx);
 	vslmode_list_element_t *mode_elem = NULL;
-	list_foreach(vs->modes, link) {
-		vslmode_list_element_t *cur = list_get_instance(link, vslmode_list_element_t, link);
+	list_foreach(vs->modes, link, vslmode_list_element_t, cur) {
 		if (cur->mode.index == vs->def_mode_idx) {
 			mode_elem = cur;
@@ -382,6 +379,5 @@
 	fibril_mutex_lock(&vs->mode_mtx);
 	vslmode_list_element_t *mode_elem = NULL;
-	list_foreach(vs->modes, link) {
-		vslmode_list_element_t *cur = list_get_instance(link, vslmode_list_element_t, link);
+	list_foreach(vs->modes, link, vslmode_list_element_t, cur) {
 		if (cur->mode.index == mode_idx) {
 			mode_elem = cur;
@@ -425,6 +421,5 @@
 	fibril_mutex_lock(&vs->mode_mtx);
 	vslmode_list_element_t *mode_elem = NULL;
-	list_foreach(vs->modes, link) {
-		vslmode_list_element_t *cur = list_get_instance(link, vslmode_list_element_t, link);
+	list_foreach(vs->modes, link, vslmode_list_element_t, cur) {
 		if (cur->mode.index == mode_idx) {
 			mode_elem = cur;
Index: uspace/lib/gui/connection.c
===================================================================
--- uspace/lib/gui/connection.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/gui/connection.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -65,6 +65,5 @@
 
 	signal_node_t *sig_node = NULL;
-	list_foreach(connection_list, link) {
-		signal_node_t *cur = list_get_instance(link, signal_node_t, link);
+	list_foreach(connection_list, link, signal_node_t, cur) {
 		if (cur->signal == signal) {
 			sig_node = cur;
@@ -88,6 +87,5 @@
 
 	slot_node_t *slt_node = NULL;
-	list_foreach(sig_node->slots, link) {
-		slot_node_t *cur = list_get_instance(link, slot_node_t, link);
+	list_foreach(sig_node->slots, link, slot_node_t, cur) {
 		if (cur->widget == widget && cur->slot == slot) {
 			slt_node = cur;
@@ -121,6 +119,5 @@
 
 	signal_node_t *sig_node = NULL;
-	list_foreach(connection_list, link) {
-		signal_node_t *cur = list_get_instance(link, signal_node_t, link);
+	list_foreach(connection_list, link, signal_node_t, cur) {
 		if (cur->signal == signal) {
 			sig_node = cur;
@@ -135,6 +132,5 @@
 
 	slot_node_t *slt_node = NULL;
-	list_foreach(sig_node->slots, link) {
-		slot_node_t *cur = list_get_instance(link, slot_node_t, link);
+	list_foreach(sig_node->slots, link, slot_node_t, cur) {
 		if (cur->widget == widget && cur->slot == slot) {
 			slt_node = cur;
@@ -164,6 +160,5 @@
 
 	signal_node_t *sig_node = NULL;
-	list_foreach(connection_list, link) {
-		signal_node_t *cur = list_get_instance(link, signal_node_t, link);
+	list_foreach(connection_list, link, signal_node_t, cur) {
 		if (cur->signal == signal) {
 			sig_node = cur;
@@ -177,6 +172,5 @@
 	}
 
-	list_foreach(sig_node->slots, link) {
-		slot_node_t *cur = list_get_instance(link, slot_node_t, link);
+	list_foreach(sig_node->slots, link, slot_node_t, cur) {
 		cur->slot(cur->widget, data);
 	}
@@ -190,6 +184,5 @@
 
 	signal_node_t *sig_node = NULL;
-	list_foreach(connection_list, link) {
-		signal_node_t *cur = list_get_instance(link, signal_node_t, link);
+	list_foreach(connection_list, link, signal_node_t, cur) {
 		if (cur->signal == signal) {
 			sig_node = cur;
@@ -203,7 +196,5 @@
 	}
 
-	list_foreach(sig_node->slots, link) {
-		slot_node_t *cur = list_get_instance(link, slot_node_t, link);
-
+	list_foreach(sig_node->slots, link, slot_node_t, cur) {
 		void *data_copy = NULL;
 		if (data != NULL) {
Index: uspace/lib/gui/grid.c
===================================================================
--- uspace/lib/gui/grid.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/gui/grid.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -298,6 +298,5 @@
 	paint_internal(widget);
 	
-	list_foreach(widget->children, link) {
-		widget_t *child = list_get_instance(link, widget_t, link);
+	list_foreach(widget->children, link, widget_t, child) {
 		child->repaint(child);
 	}
Index: uspace/lib/gui/terminal.c
===================================================================
--- uspace/lib/gui/terminal.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/gui/terminal.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -685,7 +685,5 @@
 	terminal_t *term = NULL;
 	
-	list_foreach(terms, link) {
-		terminal_t *cur = list_get_instance(link, terminal_t, link);
-		
+	list_foreach(terms, link, terminal_t, cur) {
 		if (cur->dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
 			term = cur;
Index: uspace/lib/gui/window.c
===================================================================
--- uspace/lib/gui/window.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/gui/window.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -137,6 +137,5 @@
 {
 	if (widget->window->is_decorated) {
-		list_foreach(widget->children, link) {
-			widget_t *child = list_get_instance(link, widget_t, link);
+		list_foreach(widget->children, link, widget_t, child) {
 			child->rearrange(child, 
 			    widget->hpos + border_thickness,
@@ -146,6 +145,5 @@
 		}
 	} else {
-		list_foreach(widget->children, link) {
-			widget_t *child = list_get_instance(link, widget_t, link);
+		list_foreach(widget->children, link, widget_t, child) {
 			child->rearrange(child, widget->hpos, widget->vpos,
 			    widget->width, widget->height);
@@ -160,6 +158,5 @@
 	if (widget->window->is_decorated) {
 		paint_internal(widget);
-		list_foreach(widget->children, link) {
-			widget_t *child = list_get_instance(link, widget_t, link);
+		list_foreach(widget->children, link, widget_t, child) {
 			child->rearrange(child, 
 			    hpos + border_thickness,
@@ -169,6 +166,5 @@
 		}
 	} else {
-		list_foreach(widget->children, link) {
-			widget_t *child = list_get_instance(link, widget_t, link);
+		list_foreach(widget->children, link, widget_t, child) {
 			child->rearrange(child, hpos, vpos, width, height);
 		}
@@ -181,6 +177,5 @@
 		paint_internal(widget);
 	}
-	list_foreach(widget->children, link) {
-		widget_t *child = list_get_instance(link, widget_t, link);
+	list_foreach(widget->children, link, widget_t, child) {
 		child->repaint(child);
 	}
@@ -268,12 +263,10 @@
 			win_grab(widget->window->osess, event.pos_id, flags);
 		} else {
-			list_foreach(widget->children, link) {
-				widget_t *child = list_get_instance(link, widget_t, link);
+			list_foreach(widget->children, link, widget_t, child) {
 				child->handle_position_event(child, event);
 			}
 		}
 	} else {
-		list_foreach(widget->children, link) {
-			widget_t *child = list_get_instance(link, widget_t, link);
+		list_foreach(widget->children, link, widget_t, child) {
 			child->handle_position_event(child, event);
 		}
Index: uspace/lib/usbdev/src/recognise.c
===================================================================
--- uspace/lib/usbdev/src/recognise.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/usbdev/src/recognise.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -383,6 +383,5 @@
 		goto failure;
 	
-	list_foreach(match_ids.ids, id_link) {
-		match_id_t *match_id = list_get_instance(id_link, match_id_t, link);
+	list_foreach(match_ids.ids, link, match_id_t, match_id) {
 		rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
 		if (rc != EOK) {
Index: uspace/lib/usbhid/src/hiddescriptor.c
===================================================================
--- uspace/lib/usbhid/src/hiddescriptor.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/usbhid/src/hiddescriptor.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -333,10 +333,6 @@
 	}
 
-	usb_hid_report_description_t *report_des = NULL;
-	
-	list_foreach(report->reports, report_it) {
-		report_des = list_get_instance(report_it,
-				usb_hid_report_description_t, reports_link);
-
+	list_foreach(report->reports, reports_link,
+	    usb_hid_report_description_t, report_des) {
 		// if report id not set, return the first of the type
 		if(((report_des->report_id == report_id) || (report_id == 0)) && 
@@ -902,6 +898,4 @@
 void usb_hid_descriptor_print_list(list_t *list)
 {
-	usb_hid_report_field_t *report_item;
-
 	if(list == NULL || list_empty(list)) {
 	    usb_log_debug("\tempty\n");
@@ -909,8 +903,6 @@
 	}
 
-        list_foreach(*list, item) {
-		report_item = list_get_instance(item, usb_hid_report_field_t,
-				ritems_link);
-
+        list_foreach(*list, ritems_link, usb_hid_report_field_t,
+    	    report_item) {
 		usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
 		usb_log_debug("\t\tSIZE: %zu\n", report_item->size);
@@ -937,7 +929,5 @@
 
 		usb_log_debug("\n");
-
-	}
-
+	}
 }
 
@@ -951,13 +941,9 @@
 void usb_hid_descriptor_print(usb_hid_report_t *report)
 {
-	if(report == NULL) {
+	if (report == NULL)
 		return;
-	}
-
-	usb_hid_report_description_t *report_des;
-
-	list_foreach(report->reports, report_it) {
-		report_des = list_get_instance(report_it,
-			usb_hid_report_description_t, reports_link);
+
+	list_foreach(report->reports, reports_link,
+	    usb_hid_report_description_t, report_des) {
 		usb_log_debug("Report ID: %d\n", report_des->report_id);
 		usb_log_debug("\tType: %d\n", report_des->type);
Index: uspace/lib/usbhid/src/hidparser.c
===================================================================
--- uspace/lib/usbhid/src/hidparser.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/usbhid/src/hidparser.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -130,6 +130,4 @@
     size_t size, uint8_t *report_id)
 {
-	usb_hid_report_field_t *item;
-
 	usb_hid_report_description_t *report_des;
 	usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
@@ -153,7 +151,6 @@
 
 	/* read data */
-	list_foreach(report_des->report_items, list_item) {
-		item = list_get_instance(list_item, usb_hid_report_field_t, 
-		    ritems_link);
+	list_foreach(report_des->report_items, ritems_link,
+	    usb_hid_report_field_t, item) {
 
 		if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
@@ -163,5 +160,5 @@
 				item->value = 
 					usb_hid_translate_data(item, data);
-		
+				
 				item->usage = USB_HID_EXTENDED_USAGE(
 				    item->usages[item->value -
@@ -184,6 +181,6 @@
 				/* variable item */
 				item->value = usb_hid_translate_data(item, 
-				    data);				
-			}			
+				    data);
+			}
 		}
 	}
@@ -295,10 +292,9 @@
 	usb_hid_report_description_t *report_des = NULL;
 
-	list_foreach(report->reports, report_it) {
-		report_des = list_get_instance(report_it,
-		    usb_hid_report_description_t, reports_link);
-		
-		if ((report_des->report_id == report_id) &&
-		    (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)) {
+	list_foreach(report->reports, reports_link,
+	    usb_hid_report_description_t, rdes) {
+		if ((rdes->report_id == report_id) &&
+		    (rdes->type == USB_HID_REPORT_TYPE_OUTPUT)) {
+			report_des = rdes;
 			break;
 		}
@@ -351,5 +347,5 @@
 
 	if (report->use_report_ids != 0) {
-		buffer[0] = report_id;		
+		buffer[0] = report_id;
 	}
 
@@ -362,10 +358,6 @@
 	}
 
-	usb_hid_report_field_t *report_item;
-
-	list_foreach(report_des->report_items, item) {
-		report_item = list_get_instance(item, usb_hid_report_field_t,
-		    ritems_link);
-
+	list_foreach(report_des->report_items, ritems_link,
+	    usb_hid_report_field_t, report_item) {
 		value = usb_hid_translate_data_reverse(report_item, 
 		    report_item->value);
@@ -382,7 +374,7 @@
 			}
 			size_t shift = 8 - offset % 8 - length;
-			value = value << shift;							
+			value = value << shift;
 			value = value & (((1 << length) - 1) << shift);
-				
+			
 			uint8_t mask = 0;
 			mask = 0xff - (((1 << length) - 1) << shift);
@@ -400,5 +392,5 @@
 
 					tmp_value = tmp_value << (offset % 8);
-	
+					
 					mask = ~(((1 << (8 - (offset % 8))) - 1)
 					    << (offset % 8));
@@ -413,5 +405,5 @@
 					value = value & ((1 << (length - 
 					    ((offset + length) % 8))) - 1);
-				
+					
 					mask = (1 << (length - 
 					    ((offset + length) % 8))) - 1;
Index: uspace/lib/usbhid/src/hidpath.c
===================================================================
--- uspace/lib/usbhid/src/hidpath.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/usbhid/src/hidpath.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -176,9 +176,6 @@
 	usb_log_debug("\tLENGTH: %d\n", path->depth);
 
-	usb_hid_report_usage_path_t *path_item;
-
-	list_foreach(path->items, item) {
-		path_item = list_get_instance(item, usb_hid_report_usage_path_t,
-			rpath_items_link);
+	list_foreach(path->items, rpath_items_link,
+	    usb_hid_report_usage_path_t, path_item) {
 
 		usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
@@ -237,18 +234,14 @@
 			usb_hid_report_usage_path_t, rpath_items_link);
 
-		list_foreach(report_path->items, report_link) {
-			report_item = list_get_instance(report_link,
-				usb_hid_report_usage_path_t, rpath_items_link);
+		list_foreach(report_path->items, rpath_items_link,
+		    usb_hid_report_usage_path_t, report_item) {
+
+			if (USB_HID_SAME_USAGE_PAGE(report_item->usage_page,
+				path_item->usage_page)) {
 				
-			if(USB_HID_SAME_USAGE_PAGE(report_item->usage_page,
-				path_item->usage_page)){
-					
-				if(only_page == 0){
-					if(USB_HID_SAME_USAGE(
-						report_item->usage,
-						path_item->usage)) {
-							
+				if (only_page == 0) {
+					if (USB_HID_SAME_USAGE(report_item->usage,
+					    path_item->usage))
 						return EOK;
-					}
 				}
 				else {
@@ -266,44 +259,39 @@
 			return 1;
 		}
-		
+
 	/* path is prefix of the report_path */
 	case USB_HID_PATH_COMPARE_BEGIN:
-	
+
 		report_link = report_path->items.head.next;
 		path_link = path->items.head.next;
+		
+		while ((report_link != &report_path->items.head) &&
+		    (path_link != &path->items.head)) {
 			
-		while((report_link != &report_path->items.head) && 
-		      (path_link != &path->items.head)) {
-					  
 			report_item = list_get_instance(report_link, 
-				usb_hid_report_usage_path_t, rpath_items_link);
-					  
+			    usb_hid_report_usage_path_t, rpath_items_link);
+			
 			path_item = list_get_instance(path_link,
        				usb_hid_report_usage_path_t, rpath_items_link);
 
-			if(!USB_HID_SAME_USAGE_PAGE(report_item->usage_page, 
-				path_item->usage_page) || ((only_page == 0) && 
+			if (!USB_HID_SAME_USAGE_PAGE(report_item->usage_page, 
+			    path_item->usage_page) || ((only_page == 0) && 
 			    !USB_HID_SAME_USAGE(report_item->usage, 
-				path_item->usage))) {
-			
+			    path_item->usage))) {
 				return 1;
-			} 
-			else {
+			} else {
 				report_link = report_link->next;
-				path_link = path_link->next;			
+				path_link = path_link->next;
 			}
-			
-		}
-
-		if((((flags & USB_HID_PATH_COMPARE_BEGIN) != 0) && 
-			(path_link == &path->items.head)) || 
-		   ((report_link == &report_path->items.head) && 
-			(path_link == &path->items.head))) {
-				
+		}
+
+		if ((((flags & USB_HID_PATH_COMPARE_BEGIN) != 0) && 
+		    (path_link == &path->items.head)) || 
+		    ((report_link == &report_path->items.head) && 
+		    (path_link == &path->items.head))) {
 			return EOK;
-		}
-		else {
+		} else {
 			return 1;
-		}						
+		}
 		break;
 
@@ -405,5 +393,4 @@
 	usb_hid_report_path_t *usage_path)
 {
-	usb_hid_report_usage_path_t *path_item;
 	usb_hid_report_usage_path_t *new_path_item;
 	usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
@@ -419,7 +406,6 @@
 	}
 
-	list_foreach(usage_path->items, path_link) {
-		path_item = list_get_instance(path_link,
-			usb_hid_report_usage_path_t, rpath_items_link);
+	list_foreach(usage_path->items, rpath_items_link,
+	    usb_hid_report_usage_path_t, path_item) {
 
 		new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
Index: uspace/lib/usbhost/src/usb_endpoint_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -90,6 +90,5 @@
 	if (address < 0)
 		return NULL;
-	list_foreach(*get_list(instance, address), iterator) {
-		endpoint_t *ep = endpoint_get_instance(iterator);
+	list_foreach(*get_list(instance, address), link, endpoint_t, ep) {
 		if (ep_match(ep, address, endpoint, direction))
 			return ep;
@@ -196,6 +195,6 @@
 			fibril_mutex_lock(&instance->guard);
 			/* endpoint number is < 16, thus first byte is enough */
-			list_foreach(*get_list(instance, target.address), it) {
-				endpoint_t *ep = endpoint_get_instance(it);
+			list_foreach(*get_list(instance, target.address),
+			    link, endpoint_t, ep) {
 				if ((ep->address == target.address)
 				    && (ep->endpoint = data[4])) {
@@ -216,6 +215,6 @@
 		if ((data[0] & 0xf) == 0) {
 			fibril_mutex_lock(&instance->guard);
-			list_foreach(*get_list(instance, target.address), it) {
-				endpoint_t *ep = endpoint_get_instance(it);
+			list_foreach(*get_list(instance, target.address),
+			    link, endpoint_t, ep) {
 				if (ep->address == target.address) {
 					endpoint_toggle_set(ep,0);
@@ -408,11 +407,19 @@
     usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg)
 {
+	list_t *list;
+	link_t *link;
+	link_t *next;
+
 	assert(address >= 0);
 	assert(instance);
 	fibril_mutex_lock(&instance->guard);
-	list_foreach(*get_list(instance, address), iterator) {
-		endpoint_t *ep = endpoint_get_instance(iterator);
+
+	list = get_list(instance, address);
+	link = list_first(list);
+	while (link != NULL) {
+		endpoint_t *ep = list_get_instance(link, endpoint_t, link);
+		next = list_next(link, list);
+
 		if (ep->address == address) {
-			iterator = iterator->next;
 			list_remove(&ep->link);
 			if (callback)
@@ -420,4 +427,5 @@
 			endpoint_destroy(ep);
 		}
+		link = next;
 	}
 	fibril_mutex_unlock(&instance->guard);
Index: uspace/srv/audio/hound/audio_sink.c
===================================================================
--- uspace/srv/audio/hound/audio_sink.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/audio/hound/audio_sink.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -140,6 +140,5 @@
 
 	pcm_format_silence(dest, size, &sink->format);
-	list_foreach(sink->connections, it) {
-		connection_t * conn = connection_from_sink_list(it);
+	list_foreach(sink->connections, sink_link, connection_t, conn) {
 		const int ret = connection_add_source_data(
 		    conn, dest, size, sink->format);
Index: uspace/srv/audio/hound/audio_source.c
===================================================================
--- uspace/srv/audio/hound/audio_source.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/audio/hound/audio_source.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -106,6 +106,5 @@
 		return ENOMEM;
 
-	list_foreach(source->connections, it) {
-		connection_t *conn = connection_from_source_list(it);
+	list_foreach(source->connections, source_link, connection_t, conn) {
 		const int ret = connection_push_data(conn, adata);
 		if (ret != EOK) {
Index: uspace/srv/audio/hound/connection.h
===================================================================
--- uspace/srv/audio/hound/connection.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/audio/hound/connection.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -76,14 +76,4 @@
  * @return pointer to a connection structure, NULL on failure.
  */
-static inline connection_t * connection_from_sink_list(link_t *l)
-{
-	return l ? list_get_instance(l, connection_t, sink_link) : NULL;
-}
-
-/**
- * List instance helper.
- * @param l link
- * @return pointer to a connection structure, NULL on failure.
- */
 static inline connection_t * connection_from_hound_list(link_t *l)
 {
Index: uspace/srv/audio/hound/hound.c
===================================================================
--- uspace/srv/audio/hound/hound.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/audio/hound/hound.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -47,20 +47,4 @@
 #include "str_error.h"
 
-#define FIND_BY_NAME(type) \
-do { \
-	assert(list); \
-	assert(name); \
-	list_foreach(*list, it) { \
-		audio_ ## type ## _t *dev = \
-		    audio_ ## type ## _list_instance(it); \
-		if (str_cmp(name, dev->name) == 0) { \
-			log_debug("%s with name '%s' is in the list", \
-			    #type, name); \
-			return dev; \
-		} \
-	} \
-	return NULL; \
-} while (0)
-
 /**
  * Search devices by name.
@@ -68,7 +52,18 @@
  * @return Pointer to the found device, NULL on failure.
  */
-static audio_device_t * find_device_by_name(list_t *list, const char *name)
-{
-	FIND_BY_NAME(device);
+static audio_device_t *find_device_by_name(list_t *list, const char *name)
+{
+	assert(list);
+	assert(name);
+
+	list_foreach(*list, link, audio_device_t, dev) {
+		if (str_cmp(name, dev->name) == 0) {
+			log_debug("device with name '%s' is in the list",
+			    name);
+			return dev;
+		}
+	}
+
+	return NULL;
 }
 
@@ -78,7 +73,18 @@
  * @return Pointer to the found source, NULL on failure.
  */
-static audio_source_t * find_source_by_name(list_t *list, const char *name)
-{
-	FIND_BY_NAME(source);
+static audio_source_t *find_source_by_name(list_t *list, const char *name)
+{
+	assert(list);
+	assert(name);
+
+	list_foreach(*list, link, audio_source_t, dev) {
+		if (str_cmp(name, dev->name) == 0) {
+			log_debug("source with name '%s' is in the list",
+			    name);
+			return dev;
+		}
+	}
+
+	return NULL;
 }
 
@@ -88,7 +94,18 @@
  * @return Pointer to the found sink, NULL on failure.
  */
-static audio_sink_t * find_sink_by_name(list_t *list, const char *name)
-{
-	FIND_BY_NAME(sink);
+static audio_sink_t *find_sink_by_name(list_t *list, const char *name)
+{
+	assert(list);
+	assert(name);
+
+	list_foreach(*list, link, audio_sink_t, dev) {
+		if (str_cmp(name, dev->name) == 0) {
+			log_debug("sink with name '%s' is in the list",
+			    name);
+			return dev;
+		}
+	}
+
+	return NULL;
 }
 
@@ -111,6 +128,6 @@
 		log_warning("Removing sink '%s' while still connected.", sink->name);
 	while (!list_empty(&sink->connections)) {
-		connection_t *conn =
-		    connection_from_sink_list(list_first(&sink->connections));
+		connection_t *conn = list_get_instance(
+		    list_first(&sink->connections), connection_t, sink_link);
 		list_remove(&conn->hound_link);
 		connection_destroy(conn);
@@ -128,13 +145,10 @@
 static void hound_remove_source_internal(hound_t *hound, audio_source_t *source)
 {
-	assert(hound);
-	assert(source);
 	log_verbose("Removing source '%s'.", source->name);
 	if (!list_empty(&source->connections))
 		log_warning("Removing source '%s' while still connected.", source->name);
 	while (!list_empty(&source->connections)) {
-		connection_t *conn =
-		    connection_from_source_list(list_first(&source->connections));
-		assert(conn);
+		connection_t *conn = list_get_instance(
+		    list_first(&source->connections), connection_t, source_link);
 		list_remove(&conn->hound_link);
 		connection_destroy(conn);
@@ -223,6 +237,5 @@
 	fibril_mutex_lock(&hound->list_guard);
 	hound_ctx_t *res = NULL;
-	list_foreach(hound->contexts, it) {
-		hound_ctx_t *ctx = hound_ctx_from_link(it);
+	list_foreach(hound->contexts, link, hound_ctx_t, ctx) {
 		if (hound_ctx_get_id(ctx) == id) {
 			res = ctx;
@@ -251,6 +264,5 @@
 	}
 
-	list_foreach(hound->devices, it) {
-		audio_device_t *dev = audio_device_list_instance(it);
+	list_foreach(hound->devices, link, audio_device_t, dev) {
 		if (dev->id == id) {
 			log_debug("Device with id %zu is already present", id);
Index: uspace/srv/audio/hound/hound_ctx.c
===================================================================
--- uspace/srv/audio/hound/hound_ctx.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/audio/hound/hound_ctx.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -176,14 +176,4 @@
 
 /**
- * List instance helper.
- * @param l link
- * @return pointer to a hound context structure, NULL on failure.
- */
-static inline hound_ctx_stream_t *hound_ctx_stream_from_link(link_t *l)
-{
-	return l ? list_get_instance(l, hound_ctx_stream_t, link) : NULL;
-}
-
-/**
  * New stream append helper.
  * @param ctx hound context.
@@ -417,6 +407,5 @@
 	pcm_format_silence(buffer, size, &source->format);
 	fibril_mutex_lock(&ctx->guard);
-	list_foreach(ctx->streams, it) {
-		hound_ctx_stream_t *stream = hound_ctx_stream_from_link(it);
+	list_foreach(ctx->streams, link, hound_ctx_stream_t, stream) {
 		ssize_t copied = hound_ctx_stream_add_self(
 		    stream, buffer, size, &source->format);
@@ -426,6 +415,5 @@
 	log_verbose("CTX: %p. Pushing audio to %u connections", ctx,
 	    list_count(&source->connections));
-	list_foreach(source->connections, it) {
-		connection_t *conn = connection_from_source_list(it);
+	list_foreach(source->connections, source_link, connection_t, conn) {
 		connection_push_data(conn, adata);
 	}
@@ -444,6 +432,5 @@
 	/* count available data */
 	size_t available_frames = -1;  /* this is ugly.... */
-	list_foreach(sink->connections, it) {
-		connection_t *conn = connection_from_source_list(it);
+	list_foreach(sink->connections, source_link, connection_t, conn) {
 		available_frames = min(available_frames,
 		    audio_pipe_frames(&conn->fifo));
@@ -466,6 +453,5 @@
 	/* mix data */
 	pcm_format_silence(buffer, bsize, &sink->format);
-	list_foreach(sink->connections, it) {
-		connection_t *conn = connection_from_source_list(it);
+	list_foreach(sink->connections, source_link, connection_t, conn) {
 		/* This should not trigger data update on the source */
 		const size_t copied = connection_add_source_data(
@@ -476,6 +462,5 @@
 	}
 	/* push to all streams */
-	list_foreach(ctx->streams, it) {
-		hound_ctx_stream_t *stream = hound_ctx_stream_from_link(it);
+	list_foreach(ctx->streams, link, hound_ctx_stream_t, stream) {
 		const int ret = stream_push_data(stream, adata);
 		if (ret != EOK)
Index: uspace/srv/audio/hound/hound_ctx.h
===================================================================
--- uspace/srv/audio/hound/hound_ctx.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/audio/hound/hound_ctx.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -58,14 +58,4 @@
 } hound_ctx_t;
 
-/**
- * List instance helper.
- * @param l link
- * @return pointer to a hound context structure, NULL on failure.
- */
-static inline hound_ctx_t *hound_ctx_from_link(link_t *l)
-{
-	return l ? list_get_instance(l, hound_ctx_t, link) : NULL;
-}
-
 typedef struct hound_ctx_stream hound_ctx_stream_t;
 
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/bd/rd/rd.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -165,5 +165,5 @@
 	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
 	
-	ret = physmem_map((void *) addr_phys,
+	ret = physmem_map(addr_phys,
 	    ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags, &rd_addr);
 	if (ret != EOK) {
Index: uspace/srv/devman/Makefile
===================================================================
--- uspace/srv/devman/Makefile	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/devman/Makefile	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -33,6 +33,12 @@
 
 SOURCES = \
+	client_conn.c \
+	dev.c \
+	devtree.c \
+	drv_conn.c \
+	driver.c \
+	loc.c \
+	fun.c \
 	main.c \
-	devman.c \
 	match.c \
 	util.c
Index: uspace/srv/devman/client_conn.c
===================================================================
--- uspace/srv/devman/client_conn.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/client_conn.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,803 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2013 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.
+ */
+
+/**
+ * @defgroup devman Device manager.
+ * @brief HelenOS device manager.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <inttypes.h>
+#include <assert.h>
+#include <ns.h>
+#include <async.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <stdbool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ctype.h>
+#include <ipc/devman.h>
+
+#include "client_conn.h"
+#include "dev.h"
+#include "devman.h"
+#include "driver.h"
+#include "fun.h"
+#include "loc.h"
+#include "main.h"
+
+/** Find handle for the device instance identified by the device's path in the
+ * device tree. */
+static void devman_function_get_handle(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *pathname;
+	devman_handle_t handle;
+	
+	int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname);
+	
+	free(pathname);
+
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+
+	/* Check function state */
+	if (fun->state == FUN_REMOVED) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	handle = fun->handle;
+
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+
+	/* Delete reference created above by find_fun_node_by_path() */
+	fun_del_ref(fun);
+
+	async_answer_1(iid, EOK, handle);
+}
+
+/** Get device match ID. */
+static void devman_fun_get_match_id(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+	size_t index = IPC_GET_ARG2(*icall);
+	void *buffer = NULL;
+
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		fun_del_ref(fun);
+		return;
+	}
+
+	buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		fun_del_ref(fun);
+		return;
+	}
+
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+
+	/* Check function state */
+	if (fun->state == FUN_REMOVED)
+		goto error;
+
+	link_t *link = list_nth(&fun->match_ids.ids, index);
+	if (link == NULL)
+		goto error;
+
+	match_id_t *mid = list_get_instance(link, match_id_t, link);
+
+	size_t sent_length = str_size(mid->id);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, mid->id, sent_length);
+	async_answer_1(iid, EOK, mid->score);
+
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	fun_del_ref(fun);
+	free(buffer);
+
+	return;
+error:
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	free(buffer);
+
+	async_answer_0(data_callid, ENOENT);
+	async_answer_0(iid, ENOENT);
+	fun_del_ref(fun);
+}
+
+/** Get device name. */
+static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		fun_del_ref(fun);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		fun_del_ref(fun);
+		return;
+	}
+
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+
+	/* Check function state */
+	if (fun->state == FUN_REMOVED) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		free(buffer);
+
+		async_answer_0(data_callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		fun_del_ref(fun);
+		return;
+	}
+
+	size_t sent_length = str_size(fun->name);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, fun->name, sent_length);
+	async_answer_0(iid, EOK);
+
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	fun_del_ref(fun);
+	free(buffer);
+}
+
+/** Get function driver name. */
+static void devman_fun_get_driver_name(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		fun_del_ref(fun);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		fun_del_ref(fun);
+		return;
+	}
+
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+
+	/* Check function state */
+	if (fun->state == FUN_REMOVED) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		free(buffer);
+
+		async_answer_0(data_callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		fun_del_ref(fun);
+		return;
+	}
+
+	/* Check whether function has a driver */
+	if (fun->child == NULL || fun->child->drv == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		free(buffer);
+
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		fun_del_ref(fun);
+		return;
+	}
+
+	size_t sent_length = str_size(fun->child->drv->name);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, fun->child->drv->name,
+	    sent_length);
+	async_answer_0(iid, EOK);
+
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	fun_del_ref(fun);
+	free(buffer);
+}
+
+/** Get device path. */
+static void devman_fun_get_path(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		fun_del_ref(fun);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		fun_del_ref(fun);
+		return;
+	}
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	/* Check function state */
+	if (fun->state == FUN_REMOVED) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		free(buffer);
+
+		async_answer_0(data_callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		fun_del_ref(fun);
+		return;
+	}
+	
+	size_t sent_length = str_size(fun->pathname);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, fun->pathname, sent_length);
+	async_answer_0(iid, EOK);
+
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	fun_del_ref(fun);
+	free(buffer);
+}
+
+/** Get handle for parent function of a device. */
+static void devman_dev_get_parent(ipc_callid_t iid, ipc_call_t *icall)
+{
+	dev_node_t *dev;
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	dev = find_dev_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
+	if (dev == NULL || dev->state == DEVICE_REMOVED) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (dev->pfun == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, dev->pfun->handle);
+	
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+}
+
+static void devman_dev_get_functions(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	dev_node_t *dev = find_dev_node_no_lock(&device_tree,
+	    IPC_GET_ARG1(*icall));
+	if (dev == NULL || dev->state == DEVICE_REMOVED) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
+	if (hdl_buf == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size);
+	if (rc != EOK) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	
+	sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size);
+	free(hdl_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
+/** Get handle for child device of a function. */
+static void devman_fun_get_child(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fun_node_t *fun;
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
+	if (fun == NULL || fun->state == FUN_REMOVED) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (fun->child == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, fun->child->handle);
+	
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+}
+
+/** Online function.
+ *
+ * Send a request to online a function to the responsible driver.
+ * The driver may offline other functions if necessary (i.e. if the state
+ * of this function is linked to state of another function somehow).
+ */
+static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fun_node_t *fun;
+	int rc;
+
+	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	rc = driver_fun_online(&device_tree, fun);
+	fun_del_ref(fun);
+	
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+/** Offline function.
+ *
+ * Send a request to offline a function to the responsible driver. As
+ * a result the subtree rooted at that function should be cleanly
+ * detatched. The driver may offline other functions if necessary
+ * (i.e. if the state of this function is linked to state of another
+ * function somehow).
+ */
+static void devman_fun_offline(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fun_node_t *fun;
+	int rc;
+
+	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	rc = driver_fun_offline(&device_tree, fun);
+	fun_del_ref(fun);
+	
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+/** Find handle for the function instance identified by its service ID. */
+static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fun_node_t *fun;
+
+	fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall));
+	
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+
+	/* Check function state */
+	if (fun->state == FUN_REMOVED) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	async_answer_1(iid, EOK, fun->handle);
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	fun_del_ref(fun);
+}
+
+/** Get list of all registered drivers. */
+static void devman_get_drivers(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
+	if (hdl_buf == NULL) {
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	rc = driver_get_list(&drivers_list, hdl_buf, size, &act_size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size);
+	free(hdl_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
+static void devman_driver_get_devices(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	driver_t *drv = driver_find(&drivers_list, IPC_GET_ARG1(*icall));
+	if (drv == NULL) {
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
+	if (hdl_buf == NULL) {
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	rc = driver_get_devices(drv, hdl_buf, size, &act_size);
+	if (rc != EOK) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size);
+	free(hdl_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
+
+/** Find driver by name. */
+static void devman_driver_get_handle(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *drvname;
+	
+	int rc = async_data_write_accept((void **) &drvname, true, 0, 0, 0, 0);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	driver_t *driver = driver_find_by_name(&drivers_list, drvname);
+	
+	free(drvname);
+	
+	if (driver == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, driver->handle);
+}
+
+/** Get driver match ID. */
+static void devman_driver_get_match_id(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+	size_t index = IPC_GET_ARG2(*icall);
+
+	driver_t *drv = driver_find(&drivers_list, handle);
+	if (drv == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	fibril_mutex_lock(&drv->driver_mutex);
+	link_t *link = list_nth(&drv->match_ids.ids, index);
+	if (link == NULL) {
+		fibril_mutex_unlock(&drv->driver_mutex);
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	match_id_t *mid = list_get_instance(link, match_id_t, link);
+
+	size_t sent_length = str_size(mid->id);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, mid->id, sent_length);
+	async_answer_1(iid, EOK, mid->score);
+
+	fibril_mutex_unlock(&drv->driver_mutex);
+
+	free(buffer);
+}
+
+/** Get driver name. */
+static void devman_driver_get_name(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+
+	driver_t *drv = driver_find(&drivers_list, handle);
+	if (drv == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	fibril_mutex_lock(&drv->driver_mutex);
+
+	size_t sent_length = str_size(drv->name);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, drv->name, sent_length);
+	async_answer_0(iid, EOK);
+
+	fibril_mutex_unlock(&drv->driver_mutex);
+
+	free(buffer);
+}
+
+/** Get driver state. */
+static void devman_driver_get_state(ipc_callid_t iid, ipc_call_t *icall)
+{
+	driver_t *drv;
+	
+	drv = driver_find(&drivers_list, IPC_GET_ARG1(*icall));
+	if (drv == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, (sysarg_t) drv->state);
+}
+
+/** Forcibly load a driver. */
+static void devman_driver_load(ipc_callid_t iid, ipc_call_t *icall)
+{
+	driver_t *drv;
+	int rc;
+	
+	drv = driver_find(&drivers_list, IPC_GET_ARG1(*icall));
+	if (drv == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	fibril_mutex_lock(&drv->driver_mutex);
+	rc = start_driver(drv) ? EOK : EIO;
+	fibril_mutex_unlock(&drv->driver_mutex);
+
+	async_answer_0(iid, rc);
+}
+
+/** Function for handling connections from a client to the device manager. */
+void devman_connection_client(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* Accept connection. */
+	async_answer_0(iid, EOK);
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case DEVMAN_DEVICE_GET_HANDLE:
+			devman_function_get_handle(callid, &call);
+			break;
+		case DEVMAN_DEV_GET_PARENT:
+			devman_dev_get_parent(callid, &call);
+			break;
+		case DEVMAN_DEV_GET_FUNCTIONS:
+			devman_dev_get_functions(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_CHILD:
+			devman_fun_get_child(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_MATCH_ID:
+			devman_fun_get_match_id(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_NAME:
+			devman_fun_get_name(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_DRIVER_NAME:
+			devman_fun_get_driver_name(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_PATH:
+			devman_fun_get_path(callid, &call);
+			break;
+		case DEVMAN_FUN_ONLINE:
+			devman_fun_online(callid, &call);
+			break;
+		case DEVMAN_FUN_OFFLINE:
+			devman_fun_offline(callid, &call);
+			break;
+		case DEVMAN_FUN_SID_TO_HANDLE:
+			devman_fun_sid_to_handle(callid, &call);
+			break;
+		case DEVMAN_GET_DRIVERS:
+			devman_get_drivers(callid, &call);
+			break;
+		case DEVMAN_DRIVER_GET_DEVICES:
+			devman_driver_get_devices(callid, &call);
+			break;
+		case DEVMAN_DRIVER_GET_HANDLE:
+			devman_driver_get_handle(callid, &call);
+			break;
+		case DEVMAN_DRIVER_GET_MATCH_ID:
+			devman_driver_get_match_id(callid, &call);
+			break;
+		case DEVMAN_DRIVER_GET_NAME:
+			devman_driver_get_name(callid, &call);
+			break;
+		case DEVMAN_DRIVER_GET_STATE:
+			devman_driver_get_state(callid, &call);
+			break;
+		case DEVMAN_DRIVER_LOAD:
+			devman_driver_load(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOENT);
+		}
+	}
+}
+
+
+/** @}
+ */
Index: uspace/srv/devman/client_conn.h
===================================================================
--- uspace/srv/devman/client_conn.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/client_conn.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 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 devman
+ * @{
+ */
+
+#ifndef CLIENT_CONN_H_
+#define CLIENT_CONN_H_
+
+#include "devman.h"
+
+extern void devman_connection_client(ipc_callid_t, ipc_call_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/dev.c
===================================================================
--- uspace/srv/devman/dev.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/dev.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,158 @@
+/*
+ * 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 devman
+ * @{
+ */
+
+#include <errno.h>
+
+#include "dev.h"
+#include "devman.h"
+
+/** Create a new device node.
+ *
+ * @return		A device node structure.
+ */
+dev_node_t *create_dev_node(void)
+{
+	dev_node_t *dev;
+	
+	dev = calloc(1, sizeof(dev_node_t));
+	if (dev == NULL)
+		return NULL;
+	
+	atomic_set(&dev->refcnt, 0);
+	list_initialize(&dev->functions);
+	link_initialize(&dev->driver_devices);
+	
+	return dev;
+}
+
+/** Delete a device node.
+ *
+ * @param node		The device node structure.
+ */
+void delete_dev_node(dev_node_t *dev)
+{
+	assert(list_empty(&dev->functions));
+	assert(dev->pfun == NULL);
+	assert(dev->drv == NULL);
+	
+	free(dev);
+}
+
+/** Increase device node reference count.
+ *
+ * @param dev	Device node
+ */
+void dev_add_ref(dev_node_t *dev)
+{
+	atomic_inc(&dev->refcnt);
+}
+
+/** Decrease device node reference count.
+ *
+ * When the count drops to zero the device node is freed.
+ *
+ * @param dev	Device node
+ */
+void dev_del_ref(dev_node_t *dev)
+{
+	if (atomic_predec(&dev->refcnt) == 0)
+		delete_dev_node(dev);
+}
+
+/** Find the device node structure of the device witch has the specified handle.
+ *
+ * @param tree		The device tree where we look for the device node.
+ * @param handle	The handle of the device.
+ * @return		The device node.
+ */
+dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
+{
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+	
+	ht_link_t *link = hash_table_find(&tree->devman_devices, &handle);
+	if (link == NULL)
+		return NULL;
+	
+	return hash_table_get_inst(link, dev_node_t, devman_dev);
+}
+
+/** Find the device node structure of the device witch has the specified handle.
+ *
+ * @param tree		The device tree where we look for the device node.
+ * @param handle	The handle of the device.
+ * @return		The device node.
+ */
+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);
+	dev = find_dev_node_no_lock(tree, handle);
+	if (dev != NULL)
+		dev_add_ref(dev);
+	
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	return dev;
+}
+
+/** Get list of device functions. */
+int dev_get_functions(dev_tree_t *tree, dev_node_t *dev,
+    devman_handle_t *hdl_buf, size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+
+	buf_cnt = buf_size / sizeof(devman_handle_t);
+
+	act_cnt = list_count(&dev->functions);
+	*act_size = act_cnt * sizeof(devman_handle_t);
+
+	if (buf_size % sizeof(devman_handle_t) != 0)
+		return EINVAL;
+
+	size_t pos = 0;
+	list_foreach(dev->functions, dev_functions, fun_node_t, fun) {
+		if (pos < buf_cnt) {
+			hdl_buf[pos] = fun->handle;
+		}
+
+		pos++;
+	}
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/devman/dev.h
===================================================================
--- uspace/srv/devman/dev.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/dev.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2013 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 devman
+ * @{
+ */
+
+#ifndef DEV_H_
+#define DEV_H_
+
+#include "devman.h"
+
+extern dev_node_t *create_dev_node(void);
+extern void delete_dev_node(dev_node_t *node);
+extern void dev_add_ref(dev_node_t *);
+extern void dev_del_ref(dev_node_t *);
+
+extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree,
+    devman_handle_t handle);
+extern dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle);
+extern int dev_get_functions(dev_tree_t *tree, dev_node_t *, devman_handle_t *,
+    size_t, size_t *);
+
+#endif
+
+/** @}
+ */
Index: pace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ 	(revision )
@@ -1,1528 +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 devman
- * @{
- */
-/** @file Device Manager
- *
- * Locking order:
- *   (1) driver_t.driver_mutex
- *   (2) dev_tree_t.rwlock
- *
- * Synchronization:
- *    - device_tree.rwlock protects:
- *        - tree root, complete tree topology
- *        - complete contents of device and function nodes
- *    - dev_node_t.refcnt, fun_node_t.refcnt prevent nodes from
- *      being deallocated
- *    - find_xxx() functions increase reference count of returned object
- *    - find_xxx_no_lock() do not increase reference count
- *
- * TODO
- *    - Track all steady and transient device/function states
- *    - Check states, wait for steady state on certain operations
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <io/log.h>
-#include <ipc/driver.h>
-#include <ipc/devman.h>
-#include <loc.h>
-#include <str_error.h>
-#include <stdio.h>
-
-#include "devman.h"
-
-static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *);
-
-/* hash table operations */
-
-static inline size_t handle_key_hash(void *key)
-{
-	devman_handle_t handle = *(devman_handle_t*)key;
-	return handle;
-}
-
-static size_t devman_devices_hash(const ht_link_t *item)
-{
-	dev_node_t *dev = hash_table_get_inst(item, dev_node_t, devman_dev);
-	return handle_key_hash(&dev->handle);
-}
-
-static size_t devman_functions_hash(const ht_link_t *item)
-{
-	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, devman_fun);
-	return handle_key_hash(&fun->handle);
-}
-
-static bool devman_devices_key_equal(void *key, const ht_link_t *item)
-{
-	devman_handle_t handle = *(devman_handle_t*)key;
-	dev_node_t *dev = hash_table_get_inst(item, dev_node_t, devman_dev);
-	return dev->handle == handle;
-}
-
-static bool devman_functions_key_equal(void *key, const ht_link_t *item)
-{
-	devman_handle_t handle = *(devman_handle_t*)key;
-	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, devman_fun);
-	return fun->handle == handle;
-}
-
-static inline size_t service_id_key_hash(void *key)
-{
-	service_id_t service_id = *(service_id_t*)key;
-	return service_id;
-}
-
-static size_t loc_functions_hash(const ht_link_t *item)
-{
-	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, loc_fun);
-	return service_id_key_hash(&fun->service_id);
-}
-
-static bool loc_functions_key_equal(void *key, const ht_link_t *item)
-{
-	service_id_t service_id = *(service_id_t*)key;
-	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, loc_fun);
-	return fun->service_id == service_id;
-}
-
-
-static hash_table_ops_t devman_devices_ops = {
-	.hash = devman_devices_hash,
-	.key_hash = handle_key_hash,
-	.key_equal = devman_devices_key_equal,
-	.equal = NULL,
-	.remove_callback = NULL
-};
-
-static hash_table_ops_t devman_functions_ops = {
-	.hash = devman_functions_hash,
-	.key_hash = handle_key_hash,
-	.key_equal = devman_functions_key_equal,
-	.equal = NULL,
-	.remove_callback = NULL
-};
-
-static hash_table_ops_t loc_devices_ops = {
-	.hash = loc_functions_hash,
-	.key_hash = service_id_key_hash,
-	.key_equal = loc_functions_key_equal,
-	.equal = NULL,
-	.remove_callback = NULL
-};
-
-/**
- * Initialize the list of device driver's.
- *
- * @param drv_list the list of device driver's.
- *
- */
-void init_driver_list(driver_list_t *drv_list)
-{
-	assert(drv_list != NULL);
-	
-	list_initialize(&drv_list->drivers);
-	fibril_mutex_initialize(&drv_list->drivers_mutex);
-}
-
-/** Allocate and initialize a new driver structure.
- *
- * @return	Driver structure.
- */
-driver_t *create_driver(void)
-{
-	driver_t *res = malloc(sizeof(driver_t));
-	if (res != NULL)
-		init_driver(res);
-	return res;
-}
-
-/** Add a driver to the list of drivers.
- *
- * @param drivers_list	List of drivers.
- * @param drv		Driver structure.
- */
-void add_driver(driver_list_t *drivers_list, driver_t *drv)
-{
-	fibril_mutex_lock(&drivers_list->drivers_mutex);
-	list_prepend(&drv->drivers, &drivers_list->drivers);
-	fibril_mutex_unlock(&drivers_list->drivers_mutex);
-
-	log_msg(LOG_DEFAULT, LVL_NOTE, "Driver `%s' was added to the list of available "
-	    "drivers.", drv->name);
-}
-
-/** Read match id at the specified position of a string and set the position in
- * the string to the first character following the id.
- *
- * @param buf		The position in the input string.
- * @return		The match id.
- */
-char *read_match_id(char **buf)
-{
-	char *res = NULL;
-	size_t len = get_nonspace_len(*buf);
-	
-	if (len > 0) {
-		res = malloc(len + 1);
-		if (res != NULL) {
-			str_ncpy(res, len + 1, *buf, len);
-			*buf += len;
-		}
-	}
-	
-	return res;
-}
-
-/**
- * Read match ids and associated match scores from a string.
- *
- * Each match score in the string is followed by its match id.
- * The match ids and match scores are separated by whitespaces.
- * Neither match ids nor match scores can contain whitespaces.
- *
- * @param buf		The string from which the match ids are read.
- * @param ids		The list of match ids into which the match ids and
- *			scores are added.
- * @return		True if at least one match id and associated match score
- *			was successfully read, false otherwise.
- */
-bool parse_match_ids(char *buf, match_id_list_t *ids)
-{
-	int score = 0;
-	char *id = NULL;
-	int ids_read = 0;
-	
-	while (true) {
-		/* skip spaces */
-		if (!skip_spaces(&buf))
-			break;
-		
-		/* read score */
-		score = strtoul(buf, &buf, 10);
-		
-		/* skip spaces */
-		if (!skip_spaces(&buf))
-			break;
-		
-		/* read id */
-		id = read_match_id(&buf);
-		if (NULL == id)
-			break;
-		
-		/* create new match_id structure */
-		match_id_t *mid = create_match_id();
-		mid->id = id;
-		mid->score = score;
-		
-		/* add it to the list */
-		add_match_id(ids, mid);
-		
-		ids_read++;
-	}
-	
-	return ids_read > 0;
-}
-
-/**
- * Read match ids and associated match scores from a file.
- *
- * Each match score in the file is followed by its match id.
- * The match ids and match scores are separated by whitespaces.
- * Neither match ids nor match scores can contain whitespaces.
- *
- * @param buf		The path to the file from which the match ids are read.
- * @param ids		The list of match ids into which the match ids and
- *			scores are added.
- * @return		True if at least one match id and associated match score
- *			was successfully read, false otherwise.
- */
-bool read_match_ids(const char *conf_path, match_id_list_t *ids)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path);
-	
-	bool suc = false;
-	char *buf = NULL;
-	bool opened = false;
-	int fd;
-	size_t len = 0;
-	
-	fd = open(conf_path, O_RDONLY);
-	if (fd < 0) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to open `%s' for reading: %s.",
-		    conf_path, str_error(fd));
-		goto cleanup;
-	}
-	opened = true;
-	
-	len = lseek(fd, 0, SEEK_END);
-	lseek(fd, 0, SEEK_SET);
-	if (len == 0) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Configuration file '%s' is empty.",
-		    conf_path);
-		goto cleanup;
-	}
-	
-	buf = malloc(len + 1);
-	if (buf == NULL) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Memory allocation failed when parsing file "
-		    "'%s'.", conf_path);
-		goto cleanup;
-	}
-	
-	ssize_t read_bytes = read_all(fd, buf, len);
-	if (read_bytes <= 0) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to read file '%s' (%zd).", conf_path,
-		    read_bytes);
-		goto cleanup;
-	}
-	buf[read_bytes] = 0;
-	
-	suc = parse_match_ids(buf, ids);
-	
-cleanup:
-	free(buf);
-	
-	if (opened)
-		close(fd);
-	
-	return suc;
-}
-
-/**
- * Get information about a driver.
- *
- * Each driver has its own directory in the base directory.
- * The name of the driver's directory is the same as the name of the driver.
- * The driver's directory contains driver's binary (named as the driver without
- * extension) and the configuration file with match ids for device-to-driver
- *  matching (named as the driver with a special extension).
- *
- * This function searches for the driver's directory and containing
- * configuration files. If all the files needed are found, they are parsed and
- * the information about the driver is stored in the driver's structure.
- *
- * @param base_path	The base directory, in which we look for driver's
- *			subdirectory.
- * @param name		The name of the driver.
- * @param drv		The driver structure to fill information in.
- *
- * @return		True on success, false otherwise.
- */
-bool get_driver_info(const char *base_path, const char *name, driver_t *drv)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")",
-	    base_path, name);
-	
-	assert(base_path != NULL && name != NULL && drv != NULL);
-	
-	bool suc = false;
-	char *match_path = NULL;
-	size_t name_size = 0;
-	
-	/* Read the list of match ids from the driver's configuration file. */
-	match_path = get_abs_path(base_path, name, MATCH_EXT);
-	if (match_path == NULL)
-		goto cleanup;
-	
-	if (!read_match_ids(match_path, &drv->match_ids))
-		goto cleanup;
-	
-	/* Allocate and fill driver's name. */
-	name_size = str_size(name) + 1;
-	drv->name = malloc(name_size);
-	if (drv->name == NULL)
-		goto cleanup;
-	str_cpy(drv->name, name_size, name);
-	
-	/* Initialize path with driver's binary. */
-	drv->binary_path = get_abs_path(base_path, name, "");
-	if (drv->binary_path == NULL)
-		goto cleanup;
-	
-	/* Check whether the driver's binary exists. */
-	struct stat s;
-	if (stat(drv->binary_path, &s) == ENOENT) { /* FIXME!! */
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Driver not found at path `%s'.",
-		    drv->binary_path);
-		goto cleanup;
-	}
-	
-	suc = true;
-	
-cleanup:
-	if (!suc) {
-		free(drv->binary_path);
-		free(drv->name);
-		/* Set the driver structure to the default state. */
-		init_driver(drv);
-	}
-	
-	free(match_path);
-	
-	return suc;
-}
-
-/** Lookup drivers in the directory.
- *
- * @param drivers_list	The list of available drivers.
- * @param dir_path	The path to the directory where we search for drivers.
- * @return		Number of drivers which were found.
- */
-int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path);
-	
-	int drv_cnt = 0;
-	DIR *dir = NULL;
-	struct dirent *diren;
-
-	dir = opendir(dir_path);
-	
-	if (dir != NULL) {
-		driver_t *drv = create_driver();
-		while ((diren = readdir(dir))) {
-			if (get_driver_info(dir_path, diren->d_name, drv)) {
-				add_driver(drivers_list, drv);
-				drv_cnt++;
-				drv = create_driver();
-			}
-		}
-		delete_driver(drv);
-		closedir(dir);
-	}
-	
-	return drv_cnt;
-}
-
-/** Create root device and function node in the device tree.
- *
- * @param tree	The device tree.
- * @return	True on success, false otherwise.
- */
-bool create_root_nodes(dev_tree_t *tree)
-{
-	fun_node_t *fun;
-	dev_node_t *dev;
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "create_root_nodes()");
-	
-	fibril_rwlock_write_lock(&tree->rwlock);
-	
-	/*
-	 * 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;
-	}
-	
-	fun_add_ref(fun);
-	insert_fun_node(tree, fun, str_dup(""), NULL);
-	
-	match_id_t *id = create_match_id();
-	id->id = str_dup("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;
-	}
-	
-	dev_add_ref(dev);
-	insert_dev_node(tree, dev, fun);
-	
-	fibril_rwlock_write_unlock(&tree->rwlock);
-	
-	return dev != NULL;
-}
-
-/** Lookup the best matching driver for the specified device in the list of
- * drivers.
- *
- * A match between a device and a driver is found if one of the driver's match
- * ids match one of the device's match ids. The score of the match is the
- * product of the driver's and device's score associated with the matching id.
- * The best matching driver for a device is the driver with the highest score
- * of the match between the device and the driver.
- *
- * @param drivers_list	The list of drivers, where we look for the driver
- *			suitable for handling the device.
- * @param node		The device node structure of the device.
- * @return		The best matching driver or NULL if no matching driver
- *			is found.
- */
-driver_t *find_best_match_driver(driver_list_t *drivers_list, dev_node_t *node)
-{
-	driver_t *best_drv = NULL, *drv = NULL;
-	int best_score = 0, score = 0;
-	
-	fibril_mutex_lock(&drivers_list->drivers_mutex);
-	
-	list_foreach(drivers_list->drivers, link) {
-		drv = list_get_instance(link, driver_t, drivers);
-		score = get_match_score(drv, node);
-		if (score > best_score) {
-			best_score = score;
-			best_drv = drv;
-		}
-	}
-	
-	fibril_mutex_unlock(&drivers_list->drivers_mutex);
-	
-	return best_drv;
-}
-
-/** Assign a driver to a device.
- *
- * @param tree		Device tree
- * @param node		The device's node in the device tree.
- * @param drv		The driver.
- */
-void attach_driver(dev_tree_t *tree, dev_node_t *dev, driver_t *drv)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")",
-	    dev->pfun->pathname, drv->name);
-	
-	fibril_mutex_lock(&drv->driver_mutex);
-	fibril_rwlock_write_lock(&tree->rwlock);
-	
-	dev->drv = drv;
-	list_append(&dev->driver_devices, &drv->devices);
-	
-	fibril_rwlock_write_unlock(&tree->rwlock);
-	fibril_mutex_unlock(&drv->driver_mutex);
-}
-
-/** Detach driver from device.
- *
- * @param tree		Device tree
- * @param node		The device's node in the device tree.
- * @param drv		The driver.
- */
-void detach_driver(dev_tree_t *tree, dev_node_t *dev)
-{
-	driver_t *drv = dev->drv;
-	
-	assert(drv != NULL);
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")",
-	    dev->pfun->pathname, drv->name);
-	
-	fibril_mutex_lock(&drv->driver_mutex);
-	fibril_rwlock_write_lock(&tree->rwlock);
-	
-	dev->drv = NULL;
-	list_remove(&dev->driver_devices);
-	
-	fibril_rwlock_write_unlock(&tree->rwlock);
-	fibril_mutex_unlock(&drv->driver_mutex);
-}
-
-/** Start a driver
- *
- * @param drv		The driver's structure.
- * @return		True if the driver's task is successfully spawned, false
- *			otherwise.
- */
-bool start_driver(driver_t *drv)
-{
-	int rc;
-
-	assert(fibril_mutex_is_locked(&drv->driver_mutex));
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name);
-	
-	rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.",
-		    drv->name, drv->binary_path, str_error(rc));
-		return false;
-	}
-	
-	drv->state = DRIVER_STARTING;
-	return true;
-}
-
-/** Find device driver in the list of device drivers.
- *
- * @param drv_list	The list of device drivers.
- * @param drv_name	The name of the device driver which is searched.
- * @return		The device driver of the specified name, if it is in the
- *			list, NULL otherwise.
- */
-driver_t *find_driver(driver_list_t *drv_list, const char *drv_name)
-{
-	driver_t *res = NULL;
-	driver_t *drv = NULL;
-	
-	fibril_mutex_lock(&drv_list->drivers_mutex);
-	
-	list_foreach(drv_list->drivers, link) {
-		drv = list_get_instance(link, driver_t, drivers);
-		if (str_cmp(drv->name, drv_name) == 0) {
-			res = drv;
-			break;
-		}
-	}
-	
-	fibril_mutex_unlock(&drv_list->drivers_mutex);
-	
-	return res;
-}
-
-/** Notify driver about the devices to which it was assigned.
- *
- * @param driver	The driver to which the devices are passed.
- */
-static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree)
-{
-	dev_node_t *dev;
-	link_t *link;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "pass_devices_to_driver(driver=\"%s\")",
-	    driver->name);
-
-	fibril_mutex_lock(&driver->driver_mutex);
-
-	/*
-	 * Go through devices list as long as there is some device
-	 * that has not been passed to the driver.
-	 */
-	link = driver->devices.head.next;
-	while (link != &driver->devices.head) {
-		dev = list_get_instance(link, dev_node_t, driver_devices);
-		fibril_rwlock_write_lock(&tree->rwlock);
-		
-		if (dev->passed_to_driver) {
-			fibril_rwlock_write_unlock(&tree->rwlock);
-			link = link->next;
-			continue;
-		}
-
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "pass_devices_to_driver: dev->refcnt=%d\n",
-		    (int)atomic_get(&dev->refcnt));
-		dev_add_ref(dev);
-
-		/*
-		 * Unlock to avoid deadlock when adding device
-		 * handled by itself.
-		 */
-		fibril_mutex_unlock(&driver->driver_mutex);
-		fibril_rwlock_write_unlock(&tree->rwlock);
-
-		add_device(driver, dev, tree);
-
-		dev_del_ref(dev);
-
-		/*
-		 * Lock again as we will work with driver's
-		 * structure.
-		 */
-		fibril_mutex_lock(&driver->driver_mutex);
-
-		/*
-		 * Restart the cycle to go through all devices again.
-		 */
-		link = driver->devices.head.next;
-	}
-
-	/*
-	 * Once we passed all devices to the driver, we need to mark the
-	 * driver as running.
-	 * It is vital to do it here and inside critical section.
-	 *
-	 * If we would change the state earlier, other devices added to
-	 * the driver would be added to the device list and started
-	 * immediately and possibly started here as well.
-	 */
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Driver `%s' enters running state.", driver->name);
-	driver->state = DRIVER_RUNNING;
-
-	fibril_mutex_unlock(&driver->driver_mutex);
-}
-
-/** Finish the initialization of a driver after it has succesfully started
- * and after it has registered itself by the device manager.
- *
- * Pass devices formerly matched to the driver to the driver and remember the
- * driver is running and fully functional now.
- *
- * @param driver	The driver which registered itself as running by the
- *			device manager.
- */
-void initialize_running_driver(driver_t *driver, dev_tree_t *tree)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "initialize_running_driver(driver=\"%s\")",
-	    driver->name);
-	
-	/*
-	 * Pass devices which have been already assigned to the driver to the
-	 * driver.
-	 */
-	pass_devices_to_driver(driver, tree);
-}
-
-/** Initialize device driver structure.
- *
- * @param drv		The device driver structure.
- */
-void init_driver(driver_t *drv)
-{
-	assert(drv != NULL);
-
-	memset(drv, 0, sizeof(driver_t));
-	list_initialize(&drv->match_ids.ids);
-	list_initialize(&drv->devices);
-	fibril_mutex_initialize(&drv->driver_mutex);
-	drv->sess = NULL;
-}
-
-/** Device driver structure clean-up.
- *
- * @param drv		The device driver structure.
- */
-void clean_driver(driver_t *drv)
-{
-	assert(drv != NULL);
-
-	free_not_null(drv->name);
-	free_not_null(drv->binary_path);
-
-	clean_match_ids(&drv->match_ids);
-
-	init_driver(drv);
-}
-
-/** Delete device driver structure.
- *
- * @param drv		The device driver structure.
- */
-void delete_driver(driver_t *drv)
-{
-	assert(drv != NULL);
-	
-	clean_driver(drv);
-	free(drv);
-}
-
-/** Create loc path and name for the function. */
-void loc_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
-{
-	char *loc_pathname = NULL;
-	char *loc_name = NULL;
-	
-	assert(fibril_rwlock_is_locked(&tree->rwlock));
-	
-	asprintf(&loc_name, "%s", fun->pathname);
-	if (loc_name == NULL)
-		return;
-	
-	replace_char(loc_name, '/', LOC_SEPARATOR);
-	
-	asprintf(&loc_pathname, "%s/%s", LOC_DEVICE_NAMESPACE,
-	    loc_name);
-	if (loc_pathname == NULL) {
-		free(loc_name);
-		return;
-	}
-	
-	loc_service_register_with_iface(loc_pathname,
-	    &fun->service_id, DEVMAN_CONNECT_FROM_LOC);
-	
-	tree_add_loc_function(tree, fun);
-	
-	free(loc_name);
-	free(loc_pathname);
-}
-
-/** Pass a device to running driver.
- *
- * @param drv		The driver's structure.
- * @param node		The device's node in the device tree.
- */
-void add_device(driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
-{
-	/*
-	 * We do not expect to have driver's mutex locked as we do not
-	 * access any structures that would affect driver_t.
-	 */
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "add_device(drv=\"%s\", dev=\"%s\")",
-	    drv->name, dev->pfun->name);
-	
-	/* Send the device to the driver. */
-	devman_handle_t parent_handle;
-	if (dev->pfun) {
-		parent_handle = dev->pfun->handle;
-	} else {
-		parent_handle = 0;
-	}
-	
-	async_exch_t *exch = async_exchange_begin(drv->sess);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(exch, DRIVER_DEV_ADD, dev->handle,
-	    parent_handle, &answer);
-	
-	/* Send the device name to the driver. */
-	sysarg_t rc = async_data_write_start(exch, dev->pfun->name,
-	    str_size(dev->pfun->name) + 1);
-	
-	async_exchange_end(exch);
-	
-	if (rc != EOK) {
-		/* TODO handle error */
-	}
-
-	/* Wait for answer from the driver. */
-	async_wait_for(req, &rc);
-
-	switch(rc) {
-	case EOK:
-		dev->state = DEVICE_USABLE;
-		break;
-	case ENOENT:
-		dev->state = DEVICE_NOT_PRESENT;
-		break;
-	default:
-		dev->state = DEVICE_INVALID;
-		break;
-	}
-	
-	dev->passed_to_driver = true;
-
-	return;
-}
-
-/** Find suitable driver for a device and assign the driver to it.
- *
- * @param node		The device node of the device in the device tree.
- * @param drivers_list	The list of available drivers.
- * @return		True if the suitable driver is found and
- *			successfully assigned to the device, false otherwise.
- */
-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, dev);
-	if (drv == NULL) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "No driver found for device `%s'.",
-		    dev->pfun->pathname);
-		return false;
-	}
-	
-	/* Attach the driver to the device. */
-	attach_driver(tree, dev, drv);
-	
-	fibril_mutex_lock(&drv->driver_mutex);
-	if (drv->state == DRIVER_NOT_STARTED) {
-		/* Start the driver. */
-		start_driver(drv);
-	}
-	bool is_running = drv->state == DRIVER_RUNNING;
-	fibril_mutex_unlock(&drv->driver_mutex);
-
-	/* Notify the driver about the new device. */
-	if (is_running)
-		add_device(drv, dev, tree);
-	
-	fibril_mutex_lock(&drv->driver_mutex);
-	fibril_mutex_unlock(&drv->driver_mutex);
-
-	fibril_rwlock_write_lock(&tree->rwlock);
-	if (dev->pfun != NULL) {
-		dev->pfun->state = FUN_ON_LINE;
-	}
-	fibril_rwlock_write_unlock(&tree->rwlock);
-	return true;
-}
-
-int driver_dev_remove(dev_tree_t *tree, dev_node_t *dev)
-{
-	async_exch_t *exch;
-	sysarg_t retval;
-	driver_t *drv;
-	devman_handle_t handle;
-	
-	assert(dev != NULL);
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_dev_remove(%p)", dev);
-	
-	fibril_rwlock_read_lock(&tree->rwlock);
-	drv = dev->drv;
-	handle = dev->handle;
-	fibril_rwlock_read_unlock(&tree->rwlock);
-	
-	exch = async_exchange_begin(drv->sess);
-	retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, handle);
-	async_exchange_end(exch);
-	
-	return retval;
-}
-
-int driver_dev_gone(dev_tree_t *tree, dev_node_t *dev)
-{
-	async_exch_t *exch;
-	sysarg_t retval;
-	driver_t *drv;
-	devman_handle_t handle;
-	
-	assert(dev != NULL);
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_dev_gone(%p)", dev);
-	
-	fibril_rwlock_read_lock(&tree->rwlock);
-	drv = dev->drv;
-	handle = dev->handle;
-	fibril_rwlock_read_unlock(&tree->rwlock);
-	
-	exch = async_exchange_begin(drv->sess);
-	retval = async_req_1_0(exch, DRIVER_DEV_GONE, handle);
-	async_exchange_end(exch);
-	
-	return retval;
-}
-
-int driver_fun_online(dev_tree_t *tree, fun_node_t *fun)
-{
-	async_exch_t *exch;
-	sysarg_t retval;
-	driver_t *drv;
-	devman_handle_t handle;
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_fun_online(%p)", fun);
-
-	fibril_rwlock_read_lock(&tree->rwlock);
-	
-	if (fun->dev == NULL) {
-		/* XXX root function? */
-		fibril_rwlock_read_unlock(&tree->rwlock);
-		return EINVAL;
-	}
-	
-	drv = fun->dev->drv;
-	handle = fun->handle;
-	fibril_rwlock_read_unlock(&tree->rwlock);
-	
-	exch = async_exchange_begin(drv->sess);
-	retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, handle);
-	loc_exchange_end(exch);
-	
-	return retval;
-}
-
-int driver_fun_offline(dev_tree_t *tree, fun_node_t *fun)
-{
-	async_exch_t *exch;
-	sysarg_t retval;
-	driver_t *drv;
-	devman_handle_t handle;
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_fun_offline(%p)", fun);
-
-	fibril_rwlock_read_lock(&tree->rwlock);
-	if (fun->dev == NULL) {
-		/* XXX root function? */
-		fibril_rwlock_read_unlock(&tree->rwlock);
-		return EINVAL;
-	}
-	
-	drv = fun->dev->drv;
-	handle = fun->handle;
-	fibril_rwlock_read_unlock(&tree->rwlock);
-	
-	exch = async_exchange_begin(drv->sess);
-	retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, handle);
-	loc_exchange_end(exch);
-	
-	return retval;
-
-}
-
-/** Initialize the device tree.
- *
- * Create root device node of the tree and assign driver to it.
- *
- * @param tree		The device tree.
- * @param drivers_list	the list of available drivers.
- * @return		True on success, false otherwise.
- */
-bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "init_device_tree()");
-	
-	tree->current_handle = 0;
-	
-	hash_table_create(&tree->devman_devices, 0, 0, &devman_devices_ops);
-	hash_table_create(&tree->devman_functions, 0, 0, &devman_functions_ops);
-	hash_table_create(&tree->loc_functions, 0, 0, &loc_devices_ops);
-	
-	fibril_rwlock_initialize(&tree->rwlock);
-	
-	/* 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. */
-	dev_node_t *rdev = tree->root_node->child;
-	dev_add_ref(rdev);
-	int rc = assign_driver(rdev, drivers_list, tree);
-	dev_del_ref(rdev);
-	
-	return rc;
-}
-
-/* Device nodes */
-
-/** Create a new device node.
- *
- * @return		A device node structure.
- */
-dev_node_t *create_dev_node(void)
-{
-	dev_node_t *dev;
-	
-	dev = calloc(1, sizeof(dev_node_t));
-	if (dev == NULL)
-		return NULL;
-	
-	atomic_set(&dev->refcnt, 0);
-	list_initialize(&dev->functions);
-	link_initialize(&dev->driver_devices);
-	
-	return dev;
-}
-
-/** Delete a device node.
- *
- * @param node		The device node structure.
- */
-void delete_dev_node(dev_node_t *dev)
-{
-	assert(list_empty(&dev->functions));
-	assert(dev->pfun == NULL);
-	assert(dev->drv == NULL);
-	
-	free(dev);
-}
-
-/** Increase device node reference count.
- *
- * @param dev	Device node
- */
-void dev_add_ref(dev_node_t *dev)
-{
-	atomic_inc(&dev->refcnt);
-}
-
-/** Decrease device node reference count.
- *
- * When the count drops to zero the device node is freed.
- *
- * @param dev	Device node
- */
-void dev_del_ref(dev_node_t *dev)
-{
-	if (atomic_predec(&dev->refcnt) == 0)
-		delete_dev_node(dev);
-}
-
-/** Find the device node structure of the device witch has the specified handle.
- *
- * @param tree		The device tree where we look for the device node.
- * @param handle	The handle of the device.
- * @return		The device node.
- */
-dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
-{
-	assert(fibril_rwlock_is_locked(&tree->rwlock));
-	
-	ht_link_t *link = hash_table_find(&tree->devman_devices, &handle);
-	if (link == NULL)
-		return NULL;
-	
-	return hash_table_get_inst(link, dev_node_t, devman_dev);
-}
-
-/** Find the device node structure of the device witch has the specified handle.
- *
- * @param tree		The device tree where we look for the device node.
- * @param handle	The handle of the device.
- * @return		The device node.
- */
-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);
-	dev = find_dev_node_no_lock(tree, handle);
-	if (dev != NULL)
-		dev_add_ref(dev);
-	
-	fibril_rwlock_read_unlock(&tree->rwlock);
-	
-	return dev;
-}
-
-/** Get list of device functions. */
-int dev_get_functions(dev_tree_t *tree, dev_node_t *dev,
-    devman_handle_t *hdl_buf, size_t buf_size, size_t *act_size)
-{
-	size_t act_cnt;
-	size_t buf_cnt;
-
-	assert(fibril_rwlock_is_locked(&tree->rwlock));
-
-	buf_cnt = buf_size / sizeof(devman_handle_t);
-
-	act_cnt = list_count(&dev->functions);
-	*act_size = act_cnt * sizeof(devman_handle_t);
-
-	if (buf_size % sizeof(devman_handle_t) != 0)
-		return EINVAL;
-
-	size_t pos = 0;
-	list_foreach(dev->functions, item) {
-		fun_node_t *fun =
-		    list_get_instance(item, fun_node_t, dev_functions);
-
-		if (pos < buf_cnt) {
-			hdl_buf[pos] = fun->handle;
-		}
-
-		pos++;
-	}
-
-	return EOK;
-}
-
-
-/* Function nodes */
-
-/** Create a new function node.
- *
- * @return		A function node structure.
- */
-fun_node_t *create_fun_node(void)
-{
-	fun_node_t *fun;
-
-	fun = calloc(1, sizeof(fun_node_t));
-	if (fun == NULL)
-		return NULL;
-	
-	fun->state = FUN_INIT;
-	atomic_set(&fun->refcnt, 0);
-	fibril_mutex_initialize(&fun->busy_lock);
-	link_initialize(&fun->dev_functions);
-	list_initialize(&fun->match_ids.ids);
-	
-	return fun;
-}
-
-/** 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);
-}
-
-/** Increase function node reference count.
- *
- * @param fun	Function node
- */
-void fun_add_ref(fun_node_t *fun)
-{
-	atomic_inc(&fun->refcnt);
-}
-
-/** Decrease function node reference count.
- *
- * When the count drops to zero the function node is freed.
- *
- * @param fun	Function node
- */
-void fun_del_ref(fun_node_t *fun)
-{
-	if (atomic_predec(&fun->refcnt) == 0)
-		delete_fun_node(fun);
-}
-
-/** Make function busy for reconfiguration operations. */
-void fun_busy_lock(fun_node_t *fun)
-{
-	fibril_mutex_lock(&fun->busy_lock);
-}
-
-/** Mark end of reconfiguration operation. */
-void fun_busy_unlock(fun_node_t *fun)
-{
-	fibril_mutex_unlock(&fun->busy_lock);
-}
-
-/** 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)
-{
-	fun_node_t *fun;
-	
-	assert(fibril_rwlock_is_locked(&tree->rwlock));
-	
-	ht_link_t *link = hash_table_find(&tree->devman_functions, &handle);
-	if (link == NULL)
-		return NULL;
-	
-	fun = hash_table_get_inst(link, fun_node_t, devman_fun);
-	
-	return 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);
-	if (fun != NULL)
-		fun_add_ref(fun);
-	
-	fibril_rwlock_read_unlock(&tree->rwlock);
-	
-	return fun;
-}
-
-/** Create and set device's full path in device tree.
- *
- * @param tree		Device tree
- * @param node		The device's device node.
- * @param parent	The parent device node.
- * @return		True on success, false otherwise (insufficient
- *			resources etc.).
- */
-static bool set_fun_path(dev_tree_t *tree, fun_node_t *fun, fun_node_t *parent)
-{
-	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
-	assert(fun->name != NULL);
-	
-	size_t pathsize = (str_size(fun->name) + 1);
-	if (parent != NULL)
-		pathsize += str_size(parent->pathname) + 1;
-	
-	fun->pathname = (char *) malloc(pathsize);
-	if (fun->pathname == NULL) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to allocate device path.");
-		return false;
-	}
-	
-	if (parent != NULL) {
-		str_cpy(fun->pathname, pathsize, parent->pathname);
-		str_append(fun->pathname, pathsize, "/");
-		str_append(fun->pathname, pathsize, fun->name);
-	} else {
-		str_cpy(fun->pathname, pathsize, fun->name);
-	}
-	
-	return true;
-}
-
-/** Insert new device into device tree.
- *
- * @param tree		The device tree.
- * @param dev		The newly added device node.
- * @param pfun		The parent function node.
- *
- * @return		True on success, false otherwise (insufficient resources
- *			etc.).
- */
-bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun)
-{
-	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "insert_dev_node(dev=%p, pfun=%p [\"%s\"])",
-	    dev, pfun, pfun->pathname);
-
-	/* Add the node to the handle-to-node map. */
-	dev->handle = ++tree->current_handle;
-	hash_table_insert(&tree->devman_devices, &dev->devman_dev);
-
-	/* Add the node to the list of its parent's children. */
-	dev->pfun = pfun;
-	pfun->child = dev;
-	
-	return true;
-}
-
-/** Remove device from device tree.
- *
- * @param tree		Device tree
- * @param dev		Device node
- */
-void remove_dev_node(dev_tree_t *tree, dev_node_t *dev)
-{
-	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "remove_dev_node(dev=%p)", dev);
-	
-	/* Remove node from the handle-to-node map. */
-	hash_table_remove(&tree->devman_devices, &dev->handle);
-	
-	/* Unlink from parent function. */
-	dev->pfun->child = NULL;
-	dev->pfun = NULL;
-	
-	dev->state = DEVICE_REMOVED;
-}
-
-
-/** Insert new function into device tree.
- *
- * @param tree		The device tree.
- * @param fun		The newly added function node. 
- * @param fun_name	The name of the newly added function.
- * @param dev		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_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(tree, fun, pfun)) {
-		return false;
-	}
-	
-	/* Add the node to the handle-to-node map. */
-	fun->handle = ++tree->current_handle;
-	hash_table_insert(&tree->devman_functions, &fun->devman_fun);
-
-	/* Add the node to the list of its parent's children. */
-	fun->dev = dev;
-	if (dev != NULL)
-		list_append(&fun->dev_functions, &dev->functions);
-	
-	return true;
-}
-
-/** Remove function from device tree.
- *
- * @param tree		Device tree
- * @param node		Function node to remove
- */
-void remove_fun_node(dev_tree_t *tree, fun_node_t *fun)
-{
-	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
-	
-	/* Remove the node from the handle-to-node map. */
-	hash_table_remove(&tree->devman_functions, &fun->handle);
-	
-	/* Remove the node from the list of its parent's children. */
-	if (fun->dev != NULL)
-		list_remove(&fun->dev_functions);
-	
-	fun->dev = NULL;
-	fun->state = FUN_REMOVED;
-}
-
-/** Find function node with a specified path in the device tree.
- * 
- * @param path		The path of the function node in the device tree.
- * @param tree		The device tree.
- * @return		The function node if it is present in the tree, NULL
- *			otherwise.
- */
-fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path)
-{
-	assert(path != NULL);
-
-	bool is_absolute = path[0] == '/';
-	if (!is_absolute) {
-		return NULL;
-	}
-
-	fibril_rwlock_read_lock(&tree->rwlock);
-	
-	fun_node_t *fun = tree->root_node;
-	fun_add_ref(fun);
-	/*
-	 * Relative path to the function from its parent (but with '/' at the
-	 * beginning)
-	 */
-	char *rel_path = path;
-	char *next_path_elem = NULL;
-	bool cont = (rel_path[1] != '\0');
-	
-	while (cont && fun != NULL) {
-		next_path_elem  = get_path_elem_end(rel_path + 1);
-		if (next_path_elem[0] == '/') {
-			cont = true;
-			next_path_elem[0] = 0;
-		} else {
-			cont = false;
-		}
-		
-		fun_node_t *cfun = find_node_child(tree, fun, rel_path + 1);
-		fun_del_ref(fun);
-		fun = cfun;
-		
-		if (cont) {
-			/* Restore the original path. */
-			next_path_elem[0] = '/';
-		}
-		rel_path = next_path_elem;
-	}
-	
-	fibril_rwlock_read_unlock(&tree->rwlock);
-	
-	return fun;
-}
-
-/** Find function with a specified name belonging to given device.
- *
- * Device tree rwlock should be held at least for reading.
- *
- * @param tree Device tree
- * @param dev Device the function belongs to.
- * @param name Function name (not path).
- * @return Function node.
- * @retval NULL No function with given name.
- */
-fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *dev,
-    const char *name)
-{
-	assert(name != NULL);
-	assert(fibril_rwlock_is_locked(&tree->rwlock));
-
-	fun_node_t *fun;
-
-	list_foreach(dev->functions, link) {
-		fun = list_get_instance(link, fun_node_t, dev_functions);
-
-		if (str_cmp(name, fun->name) == 0) {
-			fun_add_ref(fun);
-			return fun;
-		}
-	}
-
-	return NULL;
-}
-
-/** Find child function node with a specified name.
- *
- * Device tree rwlock should be held at least for reading.
- *
- * @param tree		Device tree
- * @param parent	The parent function node.
- * @param name		The name of the child function.
- * @return		The child function node.
- */
-static fun_node_t *find_node_child(dev_tree_t *tree, fun_node_t *pfun,
-    const char *name)
-{
-	return find_fun_node_in_device(tree, pfun->child, name);
-}
-
-/* loc devices */
-
-fun_node_t *find_loc_tree_function(dev_tree_t *tree, service_id_t service_id)
-{
-	fun_node_t *fun = NULL;
-	
-	fibril_rwlock_read_lock(&tree->rwlock);
-	ht_link_t *link = hash_table_find(&tree->loc_functions, &service_id);
-	if (link != NULL) {
-		fun = hash_table_get_inst(link, fun_node_t, loc_fun);
-		fun_add_ref(fun);
-	}
-	fibril_rwlock_read_unlock(&tree->rwlock);
-	
-	return fun;
-}
-
-void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun)
-{
-	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
-	
-	hash_table_insert(&tree->loc_functions, &fun->loc_fun);
-}
-
-/** @}
- */
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/devman/devman.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -35,8 +35,5 @@
 #define DEVMAN_H_
 
-#include <assert.h>
 #include <stdbool.h>
-#include <dirent.h>
-#include <str.h>
 #include <adt/list.h>
 #include <adt/hash_table.h>
@@ -51,6 +48,4 @@
 #define NAME "devman"
 
-#define MATCH_EXT ".ma"
-
 #define LOC_DEVICE_NAMESPACE "devices"
 #define LOC_SEPARATOR '\\'
@@ -67,22 +62,10 @@
 } client_t;
 
-typedef enum {
-	/** Driver has not been started. */
-	DRIVER_NOT_STARTED = 0,
-	
-	/**
-	 * Driver has been started, but has not registered as running and ready
-	 * to receive requests.
-	 */
-	DRIVER_STARTING,
-	
-	/** Driver is running and prepared to serve incomming requests. */
-	DRIVER_RUNNING
-} driver_state_t;
-
 /** Representation of device driver. */
 typedef struct driver {
 	/** Pointers to previous and next drivers in a linked list. */
 	link_t drivers;
+	/** Handle */
+	devman_handle_t handle;
 	
 	/**
@@ -90,5 +73,5 @@
 	 * and prepared to receive requests.
 	 */
-	int state;
+	driver_state_t state;
 	
 	/** Session asociated with this driver. */
@@ -115,4 +98,6 @@
 	/** Fibril mutex for list of drivers. */
 	fibril_mutex_t drivers_mutex;
+	/** Next free handle */
+	devman_handle_t next_handle;
 } driver_list_t;
 
@@ -238,84 +223,4 @@
 } dev_tree_t;
 
-/* Match ids and scores */
-
-extern int get_match_score(driver_t *, dev_node_t *);
-
-extern bool parse_match_ids(char *, match_id_list_t *);
-extern bool read_match_ids(const char *, match_id_list_t *);
-extern char *read_match_id(char **);
-extern char *read_id(const char **);
-
-/* Drivers */
-
-extern void init_driver_list(driver_list_t *);
-extern driver_t *create_driver(void);
-extern bool get_driver_info(const char *, const char *, driver_t *);
-extern int lookup_available_drivers(driver_list_t *, const char *);
-
-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(dev_tree_t *, dev_node_t *, driver_t *);
-extern void detach_driver(dev_tree_t *, dev_node_t *);
-extern void add_device(driver_t *, dev_node_t *, dev_tree_t *);
-extern bool start_driver(driver_t *);
-extern int driver_dev_remove(dev_tree_t *, dev_node_t *);
-extern int driver_dev_gone(dev_tree_t *, dev_node_t *);
-extern int driver_fun_online(dev_tree_t *, fun_node_t *);
-extern int driver_fun_offline(dev_tree_t *, fun_node_t *);
-
-extern driver_t *find_driver(driver_list_t *, const char *);
-extern void initialize_running_driver(driver_t *, dev_tree_t *);
-
-extern void init_driver(driver_t *);
-extern void clean_driver(driver_t *);
-extern void delete_driver(driver_t *);
-
-/* Device nodes */
-
-extern dev_node_t *create_dev_node(void);
-extern void delete_dev_node(dev_node_t *node);
-extern void dev_add_ref(dev_node_t *);
-extern void dev_del_ref(dev_node_t *);
-
-extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree,
-    devman_handle_t handle);
-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 int dev_get_functions(dev_tree_t *tree, dev_node_t *, devman_handle_t *,
-    size_t, size_t *);
-
-extern fun_node_t *create_fun_node(void);
-extern void delete_fun_node(fun_node_t *);
-extern void fun_add_ref(fun_node_t *);
-extern void fun_del_ref(fun_node_t *);
-extern void fun_busy_lock(fun_node_t *);
-extern void fun_busy_unlock(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 *);
-extern fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *,
-    const char *);
-
-/* Device tree */
-
-extern bool init_device_tree(dev_tree_t *, driver_list_t *);
-extern bool create_root_nodes(dev_tree_t *);
-extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *);
-extern void remove_dev_node(dev_tree_t *, dev_node_t *);
-extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *);
-extern void remove_fun_node(dev_tree_t *, fun_node_t *);
-
-/* Loc services */
-
-extern void loc_register_tree_function(fun_node_t *, dev_tree_t *);
-
-extern fun_node_t *find_loc_tree_function(dev_tree_t *, service_id_t);
-
-extern void tree_add_loc_function(dev_tree_t *, fun_node_t *);
-
 #endif
 
Index: uspace/srv/devman/devtree.c
===================================================================
--- uspace/srv/devman/devtree.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/devtree.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,317 @@
+/*
+ * 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 devman
+ * @{
+ */
+
+#include <errno.h>
+#include <io/log.h>
+
+#include "dev.h"
+#include "devtree.h"
+#include "devman.h"
+#include "driver.h"
+#include "fun.h"
+
+/* hash table operations */
+
+static inline size_t handle_key_hash(void *key)
+{
+	devman_handle_t handle = *(devman_handle_t*)key;
+	return handle;
+}
+
+static size_t devman_devices_hash(const ht_link_t *item)
+{
+	dev_node_t *dev = hash_table_get_inst(item, dev_node_t, devman_dev);
+	return handle_key_hash(&dev->handle);
+}
+
+static size_t devman_functions_hash(const ht_link_t *item)
+{
+	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, devman_fun);
+	return handle_key_hash(&fun->handle);
+}
+
+static bool devman_devices_key_equal(void *key, const ht_link_t *item)
+{
+	devman_handle_t handle = *(devman_handle_t*)key;
+	dev_node_t *dev = hash_table_get_inst(item, dev_node_t, devman_dev);
+	return dev->handle == handle;
+}
+
+static bool devman_functions_key_equal(void *key, const ht_link_t *item)
+{
+	devman_handle_t handle = *(devman_handle_t*)key;
+	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, devman_fun);
+	return fun->handle == handle;
+}
+
+static inline size_t service_id_key_hash(void *key)
+{
+	service_id_t service_id = *(service_id_t*)key;
+	return service_id;
+}
+
+static size_t loc_functions_hash(const ht_link_t *item)
+{
+	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, loc_fun);
+	return service_id_key_hash(&fun->service_id);
+}
+
+static bool loc_functions_key_equal(void *key, const ht_link_t *item)
+{
+	service_id_t service_id = *(service_id_t*)key;
+	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, loc_fun);
+	return fun->service_id == service_id;
+}
+
+
+static hash_table_ops_t devman_devices_ops = {
+	.hash = devman_devices_hash,
+	.key_hash = handle_key_hash,
+	.key_equal = devman_devices_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
+};
+
+static hash_table_ops_t devman_functions_ops = {
+	.hash = devman_functions_hash,
+	.key_hash = handle_key_hash,
+	.key_equal = devman_functions_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
+};
+
+static hash_table_ops_t loc_devices_ops = {
+	.hash = loc_functions_hash,
+	.key_hash = service_id_key_hash,
+	.key_equal = loc_functions_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
+};
+
+/** Create root device and function node in the device tree.
+ *
+ * @param tree	The device tree.
+ * @return	True on success, false otherwise.
+ */
+bool create_root_nodes(dev_tree_t *tree)
+{
+	fun_node_t *fun;
+	dev_node_t *dev;
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "create_root_nodes()");
+	
+	fibril_rwlock_write_lock(&tree->rwlock);
+	
+	/*
+	 * 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;
+	}
+	
+	fun_add_ref(fun);
+	insert_fun_node(tree, fun, str_dup(""), NULL);
+	
+	match_id_t *id = create_match_id();
+	id->id = str_dup("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;
+	}
+	
+	dev_add_ref(dev);
+	insert_dev_node(tree, dev, fun);
+	
+	fibril_rwlock_write_unlock(&tree->rwlock);
+	
+	return dev != NULL;
+}
+
+/** Initialize the device tree.
+ *
+ * Create root device node of the tree and assign driver to it.
+ *
+ * @param tree		The device tree.
+ * @param drivers_list	the list of available drivers.
+ * @return		True on success, false otherwise.
+ */
+bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "init_device_tree()");
+	
+	tree->current_handle = 0;
+	
+	hash_table_create(&tree->devman_devices, 0, 0, &devman_devices_ops);
+	hash_table_create(&tree->devman_functions, 0, 0, &devman_functions_ops);
+	hash_table_create(&tree->loc_functions, 0, 0, &loc_devices_ops);
+	
+	fibril_rwlock_initialize(&tree->rwlock);
+	
+	/* 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. */
+	dev_node_t *rdev = tree->root_node->child;
+	dev_add_ref(rdev);
+	int rc = assign_driver(rdev, drivers_list, tree);
+	dev_del_ref(rdev);
+	
+	return rc;
+}
+
+/** Insert new device into device tree.
+ *
+ * @param tree		The device tree.
+ * @param dev		The newly added device node.
+ * @param pfun		The parent function node.
+ *
+ * @return		True on success, false otherwise (insufficient resources
+ *			etc.).
+ */
+bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun)
+{
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "insert_dev_node(dev=%p, pfun=%p [\"%s\"])",
+	    dev, pfun, pfun->pathname);
+
+	/* Add the node to the handle-to-node map. */
+	dev->handle = ++tree->current_handle;
+	hash_table_insert(&tree->devman_devices, &dev->devman_dev);
+
+	/* Add the node to the list of its parent's children. */
+	dev->pfun = pfun;
+	pfun->child = dev;
+	
+	return true;
+}
+
+/** Remove device from device tree.
+ *
+ * @param tree		Device tree
+ * @param dev		Device node
+ */
+void remove_dev_node(dev_tree_t *tree, dev_node_t *dev)
+{
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "remove_dev_node(dev=%p)", dev);
+	
+	/* Remove node from the handle-to-node map. */
+	hash_table_remove(&tree->devman_devices, &dev->handle);
+	
+	/* Unlink from parent function. */
+	dev->pfun->child = NULL;
+	dev->pfun = NULL;
+	
+	dev->state = DEVICE_REMOVED;
+}
+
+
+/** Insert new function into device tree.
+ *
+ * @param tree		The device tree.
+ * @param fun		The newly added function node. 
+ * @param fun_name	The name of the newly added function.
+ * @param dev		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_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(tree, fun, pfun)) {
+		return false;
+	}
+	
+	/* Add the node to the handle-to-node map. */
+	fun->handle = ++tree->current_handle;
+	hash_table_insert(&tree->devman_functions, &fun->devman_fun);
+
+	/* Add the node to the list of its parent's children. */
+	fun->dev = dev;
+	if (dev != NULL)
+		list_append(&fun->dev_functions, &dev->functions);
+	
+	return true;
+}
+
+/** Remove function from device tree.
+ *
+ * @param tree		Device tree
+ * @param node		Function node to remove
+ */
+void remove_fun_node(dev_tree_t *tree, fun_node_t *fun)
+{
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
+	
+	/* Remove the node from the handle-to-node map. */
+	hash_table_remove(&tree->devman_functions, &fun->handle);
+	
+	/* Remove the node from the list of its parent's children. */
+	if (fun->dev != NULL)
+		list_remove(&fun->dev_functions);
+	
+	fun->dev = NULL;
+	fun->state = FUN_REMOVED;
+}
+
+/** @}
+ */
Index: uspace/srv/devman/devtree.h
===================================================================
--- uspace/srv/devman/devtree.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/devtree.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2013 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 devman
+ * @{
+ */
+
+#ifndef DEVTREE_H_
+#define DEVTREE_H_
+
+#include <stdbool.h>
+
+#include "devman.h"
+
+extern bool init_device_tree(dev_tree_t *, driver_list_t *);
+extern bool create_root_nodes(dev_tree_t *);
+extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *);
+extern void remove_dev_node(dev_tree_t *, dev_node_t *);
+extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *);
+extern void remove_fun_node(dev_tree_t *, fun_node_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/driver.c
===================================================================
--- uspace/srv/devman/driver.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/driver.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,764 @@
+/*
+ * 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 devman
+ * @{
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <io/log.h>
+#include <ipc/driver.h>
+#include <loc.h>
+#include <str_error.h>
+#include <stdio.h>
+
+#include "dev.h"
+#include "devman.h"
+#include "driver.h"
+#include "match.h"
+
+/**
+ * Initialize the list of device driver's.
+ *
+ * @param drv_list the list of device driver's.
+ *
+ */
+void init_driver_list(driver_list_t *drv_list)
+{
+	assert(drv_list != NULL);
+	
+	list_initialize(&drv_list->drivers);
+	fibril_mutex_initialize(&drv_list->drivers_mutex);
+	drv_list->next_handle = 1;
+}
+
+/** Allocate and initialize a new driver structure.
+ *
+ * @return	Driver structure.
+ */
+driver_t *create_driver(void)
+{
+	driver_t *res = malloc(sizeof(driver_t));
+	if (res != NULL)
+		init_driver(res);
+	return res;
+}
+
+/** Add a driver to the list of drivers.
+ *
+ * @param drivers_list	List of drivers.
+ * @param drv		Driver structure.
+ */
+void add_driver(driver_list_t *drivers_list, driver_t *drv)
+{
+	fibril_mutex_lock(&drivers_list->drivers_mutex);
+	list_append(&drv->drivers, &drivers_list->drivers);
+	drv->handle = drivers_list->next_handle++;
+	fibril_mutex_unlock(&drivers_list->drivers_mutex);
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Driver `%s' was added to the list of available "
+	    "drivers.", drv->name);
+}
+
+/**
+ * Get information about a driver.
+ *
+ * Each driver has its own directory in the base directory.
+ * The name of the driver's directory is the same as the name of the driver.
+ * The driver's directory contains driver's binary (named as the driver without
+ * extension) and the configuration file with match ids for device-to-driver
+ *  matching (named as the driver with a special extension).
+ *
+ * This function searches for the driver's directory and containing
+ * configuration files. If all the files needed are found, they are parsed and
+ * the information about the driver is stored in the driver's structure.
+ *
+ * @param base_path	The base directory, in which we look for driver's
+ *			subdirectory.
+ * @param name		The name of the driver.
+ * @param drv		The driver structure to fill information in.
+ *
+ * @return		True on success, false otherwise.
+ */
+bool get_driver_info(const char *base_path, const char *name, driver_t *drv)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")",
+	    base_path, name);
+	
+	assert(base_path != NULL && name != NULL && drv != NULL);
+	
+	bool suc = false;
+	char *match_path = NULL;
+	size_t name_size = 0;
+	
+	/* Read the list of match ids from the driver's configuration file. */
+	match_path = get_abs_path(base_path, name, MATCH_EXT);
+	if (match_path == NULL)
+		goto cleanup;
+	
+	if (!read_match_ids(match_path, &drv->match_ids))
+		goto cleanup;
+	
+	/* Allocate and fill driver's name. */
+	name_size = str_size(name) + 1;
+	drv->name = malloc(name_size);
+	if (drv->name == NULL)
+		goto cleanup;
+	str_cpy(drv->name, name_size, name);
+	
+	/* Initialize path with driver's binary. */
+	drv->binary_path = get_abs_path(base_path, name, "");
+	if (drv->binary_path == NULL)
+		goto cleanup;
+	
+	/* Check whether the driver's binary exists. */
+	struct stat s;
+	if (stat(drv->binary_path, &s) == ENOENT) { /* FIXME!! */
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Driver not found at path `%s'.",
+		    drv->binary_path);
+		goto cleanup;
+	}
+	
+	suc = true;
+	
+cleanup:
+	if (!suc) {
+		free(drv->binary_path);
+		free(drv->name);
+		/* Set the driver structure to the default state. */
+		init_driver(drv);
+	}
+	
+	free(match_path);
+	
+	return suc;
+}
+
+/** Lookup drivers in the directory.
+ *
+ * @param drivers_list	The list of available drivers.
+ * @param dir_path	The path to the directory where we search for drivers.
+ * @return		Number of drivers which were found.
+ */
+int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path);
+	
+	int drv_cnt = 0;
+	DIR *dir = NULL;
+	struct dirent *diren;
+
+	dir = opendir(dir_path);
+	
+	if (dir != NULL) {
+		driver_t *drv = create_driver();
+		while ((diren = readdir(dir))) {
+			if (get_driver_info(dir_path, diren->d_name, drv)) {
+				add_driver(drivers_list, drv);
+				drv_cnt++;
+				drv = create_driver();
+			}
+		}
+		delete_driver(drv);
+		closedir(dir);
+	}
+	
+	return drv_cnt;
+}
+
+/** Lookup the best matching driver for the specified device in the list of
+ * drivers.
+ *
+ * A match between a device and a driver is found if one of the driver's match
+ * ids match one of the device's match ids. The score of the match is the
+ * product of the driver's and device's score associated with the matching id.
+ * The best matching driver for a device is the driver with the highest score
+ * of the match between the device and the driver.
+ *
+ * @param drivers_list	The list of drivers, where we look for the driver
+ *			suitable for handling the device.
+ * @param node		The device node structure of the device.
+ * @return		The best matching driver or NULL if no matching driver
+ *			is found.
+ */
+driver_t *find_best_match_driver(driver_list_t *drivers_list, dev_node_t *node)
+{
+	driver_t *best_drv = NULL;
+	int best_score = 0, score = 0;
+	
+	fibril_mutex_lock(&drivers_list->drivers_mutex);
+	
+	list_foreach(drivers_list->drivers, drivers, driver_t, drv) {
+		score = get_match_score(drv, node);
+		if (score > best_score) {
+			best_score = score;
+			best_drv = drv;
+		}
+	}
+	
+	fibril_mutex_unlock(&drivers_list->drivers_mutex);
+	
+	return best_drv;
+}
+
+/** Assign a driver to a device.
+ *
+ * @param tree		Device tree
+ * @param node		The device's node in the device tree.
+ * @param drv		The driver.
+ */
+void attach_driver(dev_tree_t *tree, dev_node_t *dev, driver_t *drv)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")",
+	    dev->pfun->pathname, drv->name);
+	
+	fibril_mutex_lock(&drv->driver_mutex);
+	fibril_rwlock_write_lock(&tree->rwlock);
+	
+	dev->drv = drv;
+	list_append(&dev->driver_devices, &drv->devices);
+	
+	fibril_rwlock_write_unlock(&tree->rwlock);
+	fibril_mutex_unlock(&drv->driver_mutex);
+}
+
+/** Detach driver from device.
+ *
+ * @param tree		Device tree
+ * @param node		The device's node in the device tree.
+ * @param drv		The driver.
+ */
+void detach_driver(dev_tree_t *tree, dev_node_t *dev)
+{
+	driver_t *drv = dev->drv;
+	
+	assert(drv != NULL);
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")",
+	    dev->pfun->pathname, drv->name);
+	
+	fibril_mutex_lock(&drv->driver_mutex);
+	fibril_rwlock_write_lock(&tree->rwlock);
+	
+	dev->drv = NULL;
+	list_remove(&dev->driver_devices);
+	
+	fibril_rwlock_write_unlock(&tree->rwlock);
+	fibril_mutex_unlock(&drv->driver_mutex);
+}
+
+/** Start a driver
+ *
+ * @param drv		The driver's structure.
+ * @return		True if the driver's task is successfully spawned, false
+ *			otherwise.
+ */
+bool start_driver(driver_t *drv)
+{
+	int rc;
+
+	assert(fibril_mutex_is_locked(&drv->driver_mutex));
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name);
+	
+	rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.",
+		    drv->name, drv->binary_path, str_error(rc));
+		return false;
+	}
+	
+	drv->state = DRIVER_STARTING;
+	return true;
+}
+
+/** Find device driver by handle.
+ *
+ * @param drv_list	The list of device drivers
+ * @param handle	Driver handle
+ * @return		The device driver, if it is in the list,
+ *			NULL otherwise.
+ */
+driver_t *driver_find(driver_list_t *drv_list, devman_handle_t handle)
+{
+	driver_t *res = NULL;
+	
+	fibril_mutex_lock(&drv_list->drivers_mutex);
+	
+	list_foreach(drv_list->drivers, drivers, driver_t, drv) {
+		if (drv->handle == handle) {
+			res = drv;
+			break;
+		}
+	}
+	
+	fibril_mutex_unlock(&drv_list->drivers_mutex);
+	
+	return res;
+}
+
+
+/** Find device driver by name.
+ *
+ * @param drv_list	The list of device drivers.
+ * @param drv_name	The name of the device driver which is searched.
+ * @return		The device driver of the specified name, if it is in the
+ *			list, NULL otherwise.
+ */
+driver_t *driver_find_by_name(driver_list_t *drv_list, const char *drv_name)
+{
+	driver_t *res = NULL;
+	
+	fibril_mutex_lock(&drv_list->drivers_mutex);
+	
+	list_foreach(drv_list->drivers, drivers, driver_t, drv) {
+		if (str_cmp(drv->name, drv_name) == 0) {
+			res = drv;
+			break;
+		}
+	}
+	
+	fibril_mutex_unlock(&drv_list->drivers_mutex);
+	
+	return res;
+}
+
+/** Notify driver about the devices to which it was assigned.
+ *
+ * @param driver	The driver to which the devices are passed.
+ */
+static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree)
+{
+	dev_node_t *dev;
+	link_t *link;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "pass_devices_to_driver(driver=\"%s\")",
+	    driver->name);
+
+	fibril_mutex_lock(&driver->driver_mutex);
+
+	/*
+	 * Go through devices list as long as there is some device
+	 * that has not been passed to the driver.
+	 */
+	link = driver->devices.head.next;
+	while (link != &driver->devices.head) {
+		dev = list_get_instance(link, dev_node_t, driver_devices);
+		fibril_rwlock_write_lock(&tree->rwlock);
+		
+		if (dev->passed_to_driver) {
+			fibril_rwlock_write_unlock(&tree->rwlock);
+			link = link->next;
+			continue;
+		}
+
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "pass_devices_to_driver: dev->refcnt=%d\n",
+		    (int)atomic_get(&dev->refcnt));
+		dev_add_ref(dev);
+
+		/*
+		 * Unlock to avoid deadlock when adding device
+		 * handled by itself.
+		 */
+		fibril_mutex_unlock(&driver->driver_mutex);
+		fibril_rwlock_write_unlock(&tree->rwlock);
+
+		add_device(driver, dev, tree);
+
+		dev_del_ref(dev);
+
+		/*
+		 * Lock again as we will work with driver's
+		 * structure.
+		 */
+		fibril_mutex_lock(&driver->driver_mutex);
+
+		/*
+		 * Restart the cycle to go through all devices again.
+		 */
+		link = driver->devices.head.next;
+	}
+
+	/*
+	 * Once we passed all devices to the driver, we need to mark the
+	 * driver as running.
+	 * It is vital to do it here and inside critical section.
+	 *
+	 * If we would change the state earlier, other devices added to
+	 * the driver would be added to the device list and started
+	 * immediately and possibly started here as well.
+	 */
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Driver `%s' enters running state.", driver->name);
+	driver->state = DRIVER_RUNNING;
+
+	fibril_mutex_unlock(&driver->driver_mutex);
+}
+
+/** Finish the initialization of a driver after it has succesfully started
+ * and after it has registered itself by the device manager.
+ *
+ * Pass devices formerly matched to the driver to the driver and remember the
+ * driver is running and fully functional now.
+ *
+ * @param driver	The driver which registered itself as running by the
+ *			device manager.
+ */
+void initialize_running_driver(driver_t *driver, dev_tree_t *tree)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "initialize_running_driver(driver=\"%s\")",
+	    driver->name);
+	
+	/*
+	 * Pass devices which have been already assigned to the driver to the
+	 * driver.
+	 */
+	pass_devices_to_driver(driver, tree);
+}
+
+/** Initialize device driver structure.
+ *
+ * @param drv		The device driver structure.
+ */
+void init_driver(driver_t *drv)
+{
+	assert(drv != NULL);
+
+	memset(drv, 0, sizeof(driver_t));
+	list_initialize(&drv->match_ids.ids);
+	list_initialize(&drv->devices);
+	fibril_mutex_initialize(&drv->driver_mutex);
+	drv->sess = NULL;
+}
+
+/** Device driver structure clean-up.
+ *
+ * @param drv		The device driver structure.
+ */
+void clean_driver(driver_t *drv)
+{
+	assert(drv != NULL);
+
+	free(drv->name);
+	free(drv->binary_path);
+
+	clean_match_ids(&drv->match_ids);
+
+	init_driver(drv);
+}
+
+/** Delete device driver structure.
+ *
+ * @param drv		The device driver structure.
+ */
+void delete_driver(driver_t *drv)
+{
+	assert(drv != NULL);
+	
+	clean_driver(drv);
+	free(drv);
+}
+
+/** Find suitable driver for a device and assign the driver to it.
+ *
+ * @param node		The device node of the device in the device tree.
+ * @param drivers_list	The list of available drivers.
+ * @return		True if the suitable driver is found and
+ *			successfully assigned to the device, false otherwise.
+ */
+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, dev);
+	if (drv == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "No driver found for device `%s'.",
+		    dev->pfun->pathname);
+		return false;
+	}
+	
+	/* Attach the driver to the device. */
+	attach_driver(tree, dev, drv);
+	
+	fibril_mutex_lock(&drv->driver_mutex);
+	if (drv->state == DRIVER_NOT_STARTED) {
+		/* Start the driver. */
+		start_driver(drv);
+	}
+	bool is_running = drv->state == DRIVER_RUNNING;
+	fibril_mutex_unlock(&drv->driver_mutex);
+
+	/* Notify the driver about the new device. */
+	if (is_running)
+		add_device(drv, dev, tree);
+	
+	fibril_mutex_lock(&drv->driver_mutex);
+	fibril_mutex_unlock(&drv->driver_mutex);
+
+	fibril_rwlock_write_lock(&tree->rwlock);
+	if (dev->pfun != NULL) {
+		dev->pfun->state = FUN_ON_LINE;
+	}
+	fibril_rwlock_write_unlock(&tree->rwlock);
+	return true;
+}
+
+/** Pass a device to running driver.
+ *
+ * @param drv		The driver's structure.
+ * @param node		The device's node in the device tree.
+ */
+void add_device(driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
+{
+	/*
+	 * We do not expect to have driver's mutex locked as we do not
+	 * access any structures that would affect driver_t.
+	 */
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "add_device(drv=\"%s\", dev=\"%s\")",
+	    drv->name, dev->pfun->name);
+	
+	/* Send the device to the driver. */
+	devman_handle_t parent_handle;
+	if (dev->pfun) {
+		parent_handle = dev->pfun->handle;
+	} else {
+		parent_handle = 0;
+	}
+	
+	async_exch_t *exch = async_exchange_begin(drv->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, DRIVER_DEV_ADD, dev->handle,
+	    parent_handle, &answer);
+	
+	/* Send the device name to the driver. */
+	sysarg_t rc = async_data_write_start(exch, dev->pfun->name,
+	    str_size(dev->pfun->name) + 1);
+	
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		/* TODO handle error */
+	}
+
+	/* Wait for answer from the driver. */
+	async_wait_for(req, &rc);
+
+	switch(rc) {
+	case EOK:
+		dev->state = DEVICE_USABLE;
+		break;
+	case ENOENT:
+		dev->state = DEVICE_NOT_PRESENT;
+		break;
+	default:
+		dev->state = DEVICE_INVALID;
+		break;
+	}
+	
+	dev->passed_to_driver = true;
+
+	return;
+}
+
+int driver_dev_remove(dev_tree_t *tree, dev_node_t *dev)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	driver_t *drv;
+	devman_handle_t handle;
+	
+	assert(dev != NULL);
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_dev_remove(%p)", dev);
+	
+	fibril_rwlock_read_lock(&tree->rwlock);
+	drv = dev->drv;
+	handle = dev->handle;
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	exch = async_exchange_begin(drv->sess);
+	retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, handle);
+	async_exchange_end(exch);
+	
+	return retval;
+}
+
+int driver_dev_gone(dev_tree_t *tree, dev_node_t *dev)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	driver_t *drv;
+	devman_handle_t handle;
+	
+	assert(dev != NULL);
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_dev_gone(%p)", dev);
+	
+	fibril_rwlock_read_lock(&tree->rwlock);
+	drv = dev->drv;
+	handle = dev->handle;
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	exch = async_exchange_begin(drv->sess);
+	retval = async_req_1_0(exch, DRIVER_DEV_GONE, handle);
+	async_exchange_end(exch);
+	
+	return retval;
+}
+
+int driver_fun_online(dev_tree_t *tree, fun_node_t *fun)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	driver_t *drv;
+	devman_handle_t handle;
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_fun_online(%p)", fun);
+
+	fibril_rwlock_read_lock(&tree->rwlock);
+	
+	if (fun->dev == NULL) {
+		/* XXX root function? */
+		fibril_rwlock_read_unlock(&tree->rwlock);
+		return EINVAL;
+	}
+	
+	drv = fun->dev->drv;
+	handle = fun->handle;
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	exch = async_exchange_begin(drv->sess);
+	retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, handle);
+	loc_exchange_end(exch);
+	
+	return retval;
+}
+
+int driver_fun_offline(dev_tree_t *tree, fun_node_t *fun)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	driver_t *drv;
+	devman_handle_t handle;
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_fun_offline(%p)", fun);
+
+	fibril_rwlock_read_lock(&tree->rwlock);
+	if (fun->dev == NULL) {
+		/* XXX root function? */
+		fibril_rwlock_read_unlock(&tree->rwlock);
+		return EINVAL;
+	}
+	
+	drv = fun->dev->drv;
+	handle = fun->handle;
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	exch = async_exchange_begin(drv->sess);
+	retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, handle);
+	loc_exchange_end(exch);
+	
+	return retval;
+
+}
+
+/** Get list of registered drivers. */
+int driver_get_list(driver_list_t *driver_list, devman_handle_t *hdl_buf,
+    size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	fibril_mutex_lock(&driver_list->drivers_mutex);
+
+	buf_cnt = buf_size / sizeof(devman_handle_t);
+
+	act_cnt = list_count(&driver_list->drivers);
+	*act_size = act_cnt * sizeof(devman_handle_t);
+
+	if (buf_size % sizeof(devman_handle_t) != 0) {
+		fibril_mutex_unlock(&driver_list->drivers_mutex);
+		return EINVAL;
+	}
+
+	size_t pos = 0;
+	list_foreach(driver_list->drivers, drivers, driver_t, drv) {
+		if (pos < buf_cnt) {
+			hdl_buf[pos] = drv->handle;
+		}
+
+		pos++;
+	}
+
+	fibril_mutex_unlock(&driver_list->drivers_mutex);
+	return EOK;
+}
+
+/** Get list of device functions. */
+int driver_get_devices(driver_t *driver, devman_handle_t *hdl_buf,
+    size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	fibril_mutex_lock(&driver->driver_mutex);
+
+	buf_cnt = buf_size / sizeof(devman_handle_t);
+
+	act_cnt = list_count(&driver->devices);
+	*act_size = act_cnt * sizeof(devman_handle_t);
+
+	if (buf_size % sizeof(devman_handle_t) != 0) {
+		fibril_mutex_unlock(&driver->driver_mutex);
+		return EINVAL;
+	}
+
+	size_t pos = 0;
+	list_foreach(driver->devices, driver_devices, dev_node_t, dev) {
+		if (pos < buf_cnt) {
+			hdl_buf[pos] = dev->handle;
+		}
+
+		pos++;
+	}
+
+	fibril_mutex_unlock(&driver->driver_mutex);
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/devman/driver.h
===================================================================
--- uspace/srv/devman/driver.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/driver.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2013 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 devman
+ * @{
+ */
+
+#ifndef DRIVER_H_
+#define DRIVER_H_
+
+#include <stdbool.h>
+#include "devman.h"
+
+extern void init_driver_list(driver_list_t *);
+extern driver_t *create_driver(void);
+extern bool get_driver_info(const char *, const char *, driver_t *);
+extern int lookup_available_drivers(driver_list_t *, const char *);
+
+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(dev_tree_t *, dev_node_t *, driver_t *);
+extern void detach_driver(dev_tree_t *, dev_node_t *);
+extern bool start_driver(driver_t *);
+extern void add_device(driver_t *, dev_node_t *, dev_tree_t *);
+extern int driver_dev_remove(dev_tree_t *, dev_node_t *);
+extern int driver_dev_gone(dev_tree_t *, dev_node_t *);
+extern int driver_fun_online(dev_tree_t *, fun_node_t *);
+extern int driver_fun_offline(dev_tree_t *, fun_node_t *);
+
+extern driver_t *driver_find(driver_list_t *, devman_handle_t);
+extern driver_t *driver_find_by_name(driver_list_t *, const char *);
+extern void initialize_running_driver(driver_t *, dev_tree_t *);
+
+extern void init_driver(driver_t *);
+extern void clean_driver(driver_t *);
+extern void delete_driver(driver_t *);
+extern int driver_get_list(driver_list_t *, devman_handle_t *, size_t, size_t *);
+extern int driver_get_devices(driver_t *, devman_handle_t *, size_t, size_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/drv_conn.c
===================================================================
--- uspace/srv/devman/drv_conn.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/drv_conn.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,655 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup devman Device manager.
+ * @brief HelenOS device manager.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <ipc/services.h>
+#include <ns.h>
+#include <async.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <stdbool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <io/log.h>
+#include <ipc/devman.h>
+#include <ipc/driver.h>
+#include <loc.h>
+
+#include "client_conn.h"
+#include "dev.h"
+#include "devman.h"
+#include "devtree.h"
+#include "driver.h"
+#include "drv_conn.h"
+#include "fun.h"
+#include "loc.h"
+#include "main.h"
+
+static int init_running_drv(void *drv);
+
+/** Register running driver. */
+static driver_t *devman_driver_register(ipc_callid_t callid, ipc_call_t *call)
+{
+	driver_t *driver = NULL;
+	char *drv_name = NULL;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_driver_register");
+	
+	/* Get driver name. */
+	int rc = async_data_write_accept((void **) &drv_name, true, 0, 0, 0, 0);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return NULL;
+	}
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "The `%s' driver is trying to register.",
+	    drv_name);
+	
+	/* Find driver structure. */
+	driver = driver_find_by_name(&drivers_list, drv_name);
+	if (driver == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "No driver named `%s' was found.", drv_name);
+		free(drv_name);
+		drv_name = NULL;
+		async_answer_0(callid, ENOENT);
+		return NULL;
+	}
+	
+	free(drv_name);
+	drv_name = NULL;
+	
+	fibril_mutex_lock(&driver->driver_mutex);
+	
+	if (driver->sess) {
+		/* We already have a connection to the driver. */
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Driver '%s' already started.\n",
+		    driver->name);
+		fibril_mutex_unlock(&driver->driver_mutex);
+		async_answer_0(callid, EEXISTS);
+		return NULL;
+	}
+	
+	switch (driver->state) {
+	case DRIVER_NOT_STARTED:
+		/* Somebody started the driver manually. */
+		log_msg(LOG_DEFAULT, LVL_NOTE, "Driver '%s' started manually.\n",
+		    driver->name);
+		driver->state = DRIVER_STARTING;
+		break;
+	case DRIVER_STARTING:
+		/* The expected case */
+		break;
+	case DRIVER_RUNNING:
+		/* Should not happen since we do not have a connected session */
+		assert(false);
+	}
+	
+	/* Create connection to the driver. */
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Creating connection to the `%s' driver.",
+	    driver->name);
+	driver->sess = async_callback_receive(EXCHANGE_PARALLEL);
+	if (!driver->sess) {
+		fibril_mutex_unlock(&driver->driver_mutex);
+		async_answer_0(callid, ENOTSUP);
+		return NULL;
+	}
+	/* FIXME: Work around problem with callback sessions */
+	async_sess_args_set(driver->sess, DRIVER_DEVMAN, 0, 0);
+	
+	log_msg(LOG_DEFAULT, LVL_NOTE,
+	    "The `%s' driver was successfully registered as running.",
+	    driver->name);
+	
+	/*
+	 * Initialize the driver as running (e.g. pass assigned devices to it)
+	 * in a separate fibril; the separate fibril is used to enable the
+	 * driver to use devman service during the driver's initialization.
+	 */
+	fid_t fid = fibril_create(init_running_drv, driver);
+	if (fid == 0) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to create initialization fibril " \
+		    "for driver `%s'.", driver->name);
+		fibril_mutex_unlock(&driver->driver_mutex);
+		async_answer_0(callid, ENOMEM);
+		return NULL;
+	}
+	
+	fibril_add_ready(fid);
+	fibril_mutex_unlock(&driver->driver_mutex);
+	
+	async_answer_0(callid, EOK);
+	return driver;
+}
+
+/** Receive device match ID from the device's parent driver and add it to the
+ * list of devices match ids.
+ *
+ * @param match_ids	The list of the device's match ids.
+ * @return		Zero on success, negative error code otherwise.
+ */
+static int devman_receive_match_id(match_id_list_t *match_ids)
+{
+	match_id_t *match_id = create_match_id();
+	ipc_callid_t callid;
+	ipc_call_t call;
+	int rc = 0;
+	
+	callid = async_get_call(&call);
+	if (DEVMAN_ADD_MATCH_ID != IPC_GET_IMETHOD(call)) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, 
+		    "Invalid protocol when trying to receive match id.");
+		async_answer_0(callid, EINVAL); 
+		delete_match_id(match_id);
+		return EINVAL;
+	}
+	
+	if (match_id == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to allocate match id.");
+		async_answer_0(callid, ENOMEM);
+		return ENOMEM;
+	}
+	
+	async_answer_0(callid, EOK);
+	
+	match_id->score = IPC_GET_ARG1(call);
+	
+	char *match_id_str;
+	rc = async_data_write_accept((void **) &match_id_str, true, 0, 0, 0, 0);
+	match_id->id = match_id_str;
+	if (rc != EOK) {
+		delete_match_id(match_id);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to receive match id string: %s.",
+		    str_error(rc));
+		return rc;
+	}
+	
+	list_append(&match_id->link, &match_ids->ids);
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Received match id `%s', score %d.",
+	    match_id->id, match_id->score);
+	return rc;
+}
+
+/** Receive device match IDs from the device's parent driver and add them to the
+ * list of devices match ids.
+ *
+ * @param match_count	The number of device's match ids to be received.
+ * @param match_ids	The list of the device's match ids.
+ * @return		Zero on success, negative error code otherwise.
+ */
+static int devman_receive_match_ids(sysarg_t match_count,
+    match_id_list_t *match_ids)
+{
+	int ret = EOK;
+	size_t i;
+	
+	for (i = 0; i < match_count; i++) {
+		if (EOK != (ret = devman_receive_match_id(match_ids)))
+			return ret;
+	}
+	return ret;
+}
+
+/** Handle function registration.
+ *
+ * Child devices are registered by their parent's device driver.
+ */
+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;
+	
+	dev_node_t *pdev = find_dev_node(&device_tree, dev_handle);
+	if (pdev == NULL) {
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	if (ftype != fun_inner && ftype != fun_exposed) {
+		/* Unknown function type */
+		log_msg(LOG_DEFAULT, LVL_ERROR, 
+		    "Unknown function type %d provided by driver.",
+		    (int) ftype);
+
+		dev_del_ref(pdev);
+		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) {
+		dev_del_ref(pdev);
+		async_answer_0(callid, rc);
+		return;
+	}
+	
+	fibril_rwlock_write_lock(&tree->rwlock);
+	
+	/* Check device state */
+	if (pdev->state == DEVICE_REMOVED) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		dev_del_ref(pdev);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	/* Check that function with same name is not there already. */
+	fun_node_t *tfun = find_fun_node_in_device(tree, pdev, fun_name);
+	if (tfun) {
+		fun_del_ref(tfun);	/* drop the new unwanted reference */
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		dev_del_ref(pdev);
+		async_answer_0(callid, EEXISTS);
+		printf(NAME ": Warning, driver tried to register `%s' twice.\n",
+		    fun_name);
+		free(fun_name);
+		return;
+	}
+	
+	fun_node_t *fun = create_fun_node();
+	/* One reference for creation, one for us */
+	fun_add_ref(fun);
+	fun_add_ref(fun);
+	fun->ftype = ftype;
+	
+	/*
+	 * We can lock the function here even when holding the tree because
+	 * we know it cannot be held by anyone else yet.
+	 */
+	fun_busy_lock(fun);
+	
+	if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		dev_del_ref(pdev);
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
+		delete_fun_node(fun);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+	
+	fibril_rwlock_write_unlock(&tree->rwlock);
+	dev_del_ref(pdev);
+	
+	devman_receive_match_ids(match_count, &fun->match_ids);
+	
+	rc = fun_online(fun);
+	if (rc != EOK) {
+		/* XXX Set some failed state? */
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
+		async_answer_0(callid, rc);
+		return;
+	}
+	
+	fun_busy_unlock(fun);
+	fun_del_ref(fun);
+	
+	/* Return device handle to parent's driver. */
+	async_answer_1(callid, EOK, fun->handle);
+}
+
+static void devman_add_function_to_cat(ipc_callid_t callid, ipc_call_t *call)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*call);
+	category_id_t cat_id;
+	int rc;
+	
+	/* Get category name. */
+	char *cat_name;
+	rc = async_data_write_accept((void **) &cat_name, true,
+	    0, 0, 0, 0);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+	
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	/* Check function state */
+	if (fun->state == FUN_REMOVED) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING);
+	if (rc == EOK) {
+		loc_service_add_to_cat(fun->service_id, cat_id);
+		log_msg(LOG_DEFAULT, LVL_NOTE, "Function `%s' added to category `%s'.",
+		    fun->pathname, cat_name);
+	} else {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding function `%s' to category "
+		    "`%s'.", fun->pathname, cat_name);
+	}
+	
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	fun_del_ref(fun);
+	
+	async_answer_0(callid, rc);
+}
+
+/** Online function by driver request.
+ *
+ */
+static void devman_drv_fun_online(ipc_callid_t iid, ipc_call_t *icall,
+    driver_t *drv)
+{
+	fun_node_t *fun;
+	int rc;
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_drv_fun_online()");
+	
+	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	fun_busy_lock(fun);
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	if (fun->dev == NULL || fun->dev->drv != drv) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	
+	rc = fun_offline(fun);
+	if (rc != EOK) {
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
+		async_answer_0(iid, (sysarg_t) rc);
+		return;
+	}
+	
+	fun_busy_unlock(fun);
+	fun_del_ref(fun);
+	
+	async_answer_0(iid, (sysarg_t) EOK);
+}
+
+
+/** Offline function by driver request.
+ *
+ */
+static void devman_drv_fun_offline(ipc_callid_t iid, ipc_call_t *icall,
+    driver_t *drv)
+{
+	fun_node_t *fun;
+	int rc;
+
+	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	fun_busy_lock(fun);
+	
+	fibril_rwlock_write_lock(&device_tree.rwlock);
+	if (fun->dev == NULL || fun->dev->drv != drv) {
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	fibril_rwlock_write_unlock(&device_tree.rwlock);
+	
+	rc = fun_offline(fun);
+	if (rc != EOK) {
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
+		async_answer_0(iid, (sysarg_t) rc);
+		return;
+	}
+	
+	fun_busy_unlock(fun);
+	fun_del_ref(fun);
+	async_answer_0(iid, (sysarg_t) EOK);
+}
+
+/** Remove function. */
+static void devman_remove_function(ipc_callid_t callid, ipc_call_t *call)
+{
+	devman_handle_t fun_handle = IPC_GET_ARG1(*call);
+	dev_tree_t *tree = &device_tree;
+	int rc;
+	
+	fun_node_t *fun = find_fun_node(&device_tree, fun_handle);
+	if (fun == NULL) {
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	fun_busy_lock(fun);
+	
+	fibril_rwlock_write_lock(&tree->rwlock);
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
+	
+	/* Check function state */
+	if (fun->state == FUN_REMOVED) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	if (fun->ftype == fun_inner) {
+		/* This is a surprise removal. Handle possible descendants */
+		if (fun->child != NULL) {
+			dev_node_t *dev = fun->child;
+			device_state_t dev_state;
+			int gone_rc;
+			
+			dev_add_ref(dev);
+			dev_state = dev->state;
+			
+			fibril_rwlock_write_unlock(&device_tree.rwlock);
+			
+			/* If device is owned by driver, inform driver it is gone. */
+			if (dev_state == DEVICE_USABLE)
+				gone_rc = driver_dev_gone(&device_tree, dev);
+			else
+				gone_rc = EOK;
+			
+			fibril_rwlock_read_lock(&device_tree.rwlock);
+			
+			/* Verify that driver succeeded and removed all functions */
+			if (gone_rc != EOK || !list_empty(&dev->functions)) {
+				log_msg(LOG_DEFAULT, LVL_ERROR, "Driver did not remove "
+				    "functions for device that is gone. "
+				    "Device node is now defunct.");
+				
+				/*
+				 * Not much we can do but mark the device
+				 * node as having invalid state. This
+				 * is a driver bug.
+				 */
+				dev->state = DEVICE_INVALID;
+				fibril_rwlock_read_unlock(&device_tree.rwlock);
+				dev_del_ref(dev);
+				if (gone_rc == EOK)
+					gone_rc = ENOTSUP;
+				fun_busy_unlock(fun);
+				fun_del_ref(fun);
+				async_answer_0(callid, gone_rc);
+				return;
+			}
+			
+			driver_t *driver = dev->drv;
+			fibril_rwlock_read_unlock(&device_tree.rwlock);
+			
+			if (driver)
+				detach_driver(&device_tree, dev);
+			
+			fibril_rwlock_write_lock(&device_tree.rwlock);
+			remove_dev_node(&device_tree, dev);
+			
+			/* Delete ref created when node was inserted */
+			dev_del_ref(dev);
+			/* Delete ref created by dev_add_ref(dev) above */
+			dev_del_ref(dev);
+		}
+	} else {
+		if (fun->service_id != 0) {
+			/* Unregister from location service */
+			rc = loc_service_unregister(fun->service_id);
+			if (rc != EOK) {
+				log_msg(LOG_DEFAULT, LVL_ERROR, "Failed unregistering tree "
+				    "service.");
+				fibril_rwlock_write_unlock(&tree->rwlock);
+				fun_busy_unlock(fun);
+				fun_del_ref(fun);
+				async_answer_0(callid, EIO);
+				return;
+			}
+		}
+	}
+	
+	remove_fun_node(&device_tree, fun);
+	fibril_rwlock_write_unlock(&tree->rwlock);
+	fun_busy_unlock(fun);
+	
+	/* Delete ref added when inserting function into tree */
+	fun_del_ref(fun);
+	/* Delete ref added above when looking up function */
+	fun_del_ref(fun);
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_remove_function() succeeded.");
+	async_answer_0(callid, EOK);
+}
+
+/** Initialize driver which has registered itself as running and ready.
+ *
+ * The initialization is done in a separate fibril to avoid deadlocks (if the
+ * driver needed to be served by devman during the driver's initialization).
+ */
+static int init_running_drv(void *drv)
+{
+	driver_t *driver = (driver_t *) drv;
+	
+	initialize_running_driver(driver, &device_tree);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "The `%s` driver was successfully initialized.",
+	    driver->name);
+	return 0;
+}
+
+/** Function for handling connections from a driver to the device manager. */
+void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
+{
+	client_t *client;
+	driver_t *driver = NULL;
+	
+	/* Accept the connection. */
+	async_answer_0(iid, EOK);
+	
+	client = async_get_client_data();
+	if (client == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to allocate client data.");
+		return;
+	}
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
+		if (IPC_GET_IMETHOD(call) != DEVMAN_DRIVER_REGISTER) {
+			fibril_mutex_lock(&client->mutex);
+			driver = client->driver;
+			fibril_mutex_unlock(&client->mutex);
+			if (driver == NULL) {
+				/* First call must be to DEVMAN_DRIVER_REGISTER */
+				async_answer_0(callid, ENOTSUP);
+				continue;
+			}
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case DEVMAN_DRIVER_REGISTER:
+			fibril_mutex_lock(&client->mutex);
+			if (client->driver != NULL) {
+				fibril_mutex_unlock(&client->mutex);
+				async_answer_0(callid, EINVAL);
+				continue;
+			}
+			client->driver = devman_driver_register(callid, &call);
+			fibril_mutex_unlock(&client->mutex);
+			break;
+		case DEVMAN_ADD_FUNCTION:
+			devman_add_function(callid, &call);
+			break;
+		case DEVMAN_ADD_DEVICE_TO_CATEGORY:
+			devman_add_function_to_cat(callid, &call);
+			break;
+		case DEVMAN_DRV_FUN_ONLINE:
+			devman_drv_fun_online(callid, &call, driver);
+			break;
+		case DEVMAN_DRV_FUN_OFFLINE:
+			devman_drv_fun_offline(callid, &call, driver);
+			break;
+		case DEVMAN_REMOVE_FUNCTION:
+			devman_remove_function(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+			break;
+		}
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/devman/drv_conn.h
===================================================================
--- uspace/srv/devman/drv_conn.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/drv_conn.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 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 devman
+ * @{
+ */
+
+#ifndef DRV_CONN_H_
+#define DRV_CONN_H_
+
+#include <async.h>
+#include "devman.h"
+
+extern void devman_connection_driver(ipc_callid_t, ipc_call_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/fun.c
===================================================================
--- uspace/srv/devman/fun.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/fun.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,431 @@
+/*
+ * 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 devman
+ * @{
+ */
+
+#include <errno.h>
+#include <io/log.h>
+#include <loc.h>
+
+#include "dev.h"
+#include "devman.h"
+#include "devtree.h"
+#include "driver.h"
+#include "fun.h"
+#include "main.h"
+#include "loc.h"
+
+static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *);
+
+/* Function nodes */
+
+/** Create a new function node.
+ *
+ * @return		A function node structure.
+ */
+fun_node_t *create_fun_node(void)
+{
+	fun_node_t *fun;
+
+	fun = calloc(1, sizeof(fun_node_t));
+	if (fun == NULL)
+		return NULL;
+	
+	fun->state = FUN_INIT;
+	atomic_set(&fun->refcnt, 0);
+	fibril_mutex_initialize(&fun->busy_lock);
+	link_initialize(&fun->dev_functions);
+	list_initialize(&fun->match_ids.ids);
+	
+	return fun;
+}
+
+/** 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(fun->name);
+	free(fun->pathname);
+	free(fun);
+}
+
+/** Increase function node reference count.
+ *
+ * @param fun	Function node
+ */
+void fun_add_ref(fun_node_t *fun)
+{
+	atomic_inc(&fun->refcnt);
+}
+
+/** Decrease function node reference count.
+ *
+ * When the count drops to zero the function node is freed.
+ *
+ * @param fun	Function node
+ */
+void fun_del_ref(fun_node_t *fun)
+{
+	if (atomic_predec(&fun->refcnt) == 0)
+		delete_fun_node(fun);
+}
+
+/** Make function busy for reconfiguration operations. */
+void fun_busy_lock(fun_node_t *fun)
+{
+	fibril_mutex_lock(&fun->busy_lock);
+}
+
+/** Mark end of reconfiguration operation. */
+void fun_busy_unlock(fun_node_t *fun)
+{
+	fibril_mutex_unlock(&fun->busy_lock);
+}
+
+/** 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)
+{
+	fun_node_t *fun;
+	
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+	
+	ht_link_t *link = hash_table_find(&tree->devman_functions, &handle);
+	if (link == NULL)
+		return NULL;
+	
+	fun = hash_table_get_inst(link, fun_node_t, devman_fun);
+	
+	return 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);
+	if (fun != NULL)
+		fun_add_ref(fun);
+	
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	return fun;
+}
+
+/** Create and set device's full path in device tree.
+ *
+ * @param tree		Device tree
+ * @param node		The device's device node.
+ * @param parent	The parent device node.
+ * @return		True on success, false otherwise (insufficient
+ *			resources etc.).
+ */
+bool set_fun_path(dev_tree_t *tree, fun_node_t *fun, fun_node_t *parent)
+{
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
+	assert(fun->name != NULL);
+	
+	size_t pathsize = (str_size(fun->name) + 1);
+	if (parent != NULL)
+		pathsize += str_size(parent->pathname) + 1;
+	
+	fun->pathname = (char *) malloc(pathsize);
+	if (fun->pathname == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to allocate device path.");
+		return false;
+	}
+	
+	if (parent != NULL) {
+		str_cpy(fun->pathname, pathsize, parent->pathname);
+		str_append(fun->pathname, pathsize, "/");
+		str_append(fun->pathname, pathsize, fun->name);
+	} else {
+		str_cpy(fun->pathname, pathsize, fun->name);
+	}
+	
+	return true;
+}
+
+/** Find function node with a specified path in the device tree.
+ * 
+ * @param path		The path of the function node in the device tree.
+ * @param tree		The device tree.
+ * @return		The function node if it is present in the tree, NULL
+ *			otherwise.
+ */
+fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path)
+{
+	assert(path != NULL);
+
+	bool is_absolute = path[0] == '/';
+	if (!is_absolute) {
+		return NULL;
+	}
+
+	fibril_rwlock_read_lock(&tree->rwlock);
+	
+	fun_node_t *fun = tree->root_node;
+	fun_add_ref(fun);
+	/*
+	 * Relative path to the function from its parent (but with '/' at the
+	 * beginning)
+	 */
+	char *rel_path = path;
+	char *next_path_elem = NULL;
+	bool cont = (rel_path[1] != '\0');
+	
+	while (cont && fun != NULL) {
+		next_path_elem  = get_path_elem_end(rel_path + 1);
+		if (next_path_elem[0] == '/') {
+			cont = true;
+			next_path_elem[0] = 0;
+		} else {
+			cont = false;
+		}
+		
+		fun_node_t *cfun = find_node_child(tree, fun, rel_path + 1);
+		fun_del_ref(fun);
+		fun = cfun;
+		
+		if (cont) {
+			/* Restore the original path. */
+			next_path_elem[0] = '/';
+		}
+		rel_path = next_path_elem;
+	}
+	
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	return fun;
+}
+
+/** Find function with a specified name belonging to given device.
+ *
+ * Device tree rwlock should be held at least for reading.
+ *
+ * @param tree Device tree
+ * @param dev Device the function belongs to.
+ * @param name Function name (not path).
+ * @return Function node.
+ * @retval NULL No function with given name.
+ */
+fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *dev,
+    const char *name)
+{
+	assert(name != NULL);
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+
+	list_foreach(dev->functions, dev_functions, fun_node_t, fun) {
+		if (str_cmp(name, fun->name) == 0) {
+			fun_add_ref(fun);
+			return fun;
+		}
+	}
+
+	return NULL;
+}
+
+/** Find child function node with a specified name.
+ *
+ * Device tree rwlock should be held at least for reading.
+ *
+ * @param tree		Device tree
+ * @param parent	The parent function node.
+ * @param name		The name of the child function.
+ * @return		The child function node.
+ */
+static fun_node_t *find_node_child(dev_tree_t *tree, fun_node_t *pfun,
+    const char *name)
+{
+	return find_fun_node_in_device(tree, pfun->child, name);
+}
+
+static int assign_driver_fibril(void *arg)
+{
+	dev_node_t *dev_node = (dev_node_t *) arg;
+	assign_driver(dev_node, &drivers_list, &device_tree);
+
+	/* Delete one reference we got from the caller. */
+	dev_del_ref(dev_node);
+	return EOK;
+}
+
+int fun_online(fun_node_t *fun)
+{
+	dev_node_t *dev;
+	
+	fibril_rwlock_write_lock(&device_tree.rwlock);
+	
+	if (fun->state == FUN_ON_LINE) {
+		fibril_rwlock_write_unlock(&device_tree.rwlock);
+		log_msg(LOG_DEFAULT, LVL_WARN, "Function %s is already on line.",
+		    fun->pathname);
+		return EOK;
+	}
+	
+	if (fun->ftype == fun_inner) {
+		dev = create_dev_node();
+		if (dev == NULL) {
+			fibril_rwlock_write_unlock(&device_tree.rwlock);
+			return ENOMEM;
+		}
+		
+		insert_dev_node(&device_tree, dev, fun);
+		dev_add_ref(dev);
+	}
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
+	
+	if (fun->ftype == fun_inner) {
+		dev = fun->child;
+		assert(dev != NULL);
+		
+		/* Give one reference over to assign_driver_fibril(). */
+		dev_add_ref(dev);
+		
+		/*
+		 * 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, dev);
+		if (assign_fibril == 0) {
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to create fibril for "
+			    "assigning driver.");
+			/* XXX Cleanup */
+			fibril_rwlock_write_unlock(&device_tree.rwlock);
+			return ENOMEM;
+		}
+		fibril_add_ready(assign_fibril);
+	} else
+		loc_register_tree_function(fun, &device_tree);
+	
+	fibril_rwlock_write_unlock(&device_tree.rwlock);
+	
+	return EOK;
+}
+
+int fun_offline(fun_node_t *fun)
+{
+	int rc;
+	
+	fibril_rwlock_write_lock(&device_tree.rwlock);
+	
+	if (fun->state == FUN_OFF_LINE) {
+		fibril_rwlock_write_unlock(&device_tree.rwlock);
+		log_msg(LOG_DEFAULT, LVL_WARN, "Function %s is already off line.",
+		    fun->pathname);
+		return EOK;
+	}
+	
+	if (fun->ftype == fun_inner) {
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Offlining inner function %s.",
+		    fun->pathname);
+		
+		if (fun->child != NULL) {
+			dev_node_t *dev = fun->child;
+			device_state_t dev_state;
+			
+			dev_add_ref(dev);
+			dev_state = dev->state;
+			
+			fibril_rwlock_write_unlock(&device_tree.rwlock);
+
+			/* If device is owned by driver, ask driver to give it up. */
+			if (dev_state == DEVICE_USABLE) {
+				rc = driver_dev_remove(&device_tree, dev);
+				if (rc != EOK) {
+					dev_del_ref(dev);
+					return ENOTSUP;
+				}
+			}
+			
+			/* Verify that driver removed all functions */
+			fibril_rwlock_read_lock(&device_tree.rwlock);
+			if (!list_empty(&dev->functions)) {
+				fibril_rwlock_read_unlock(&device_tree.rwlock);
+				dev_del_ref(dev);
+				return EIO;
+			}
+			
+			driver_t *driver = dev->drv;
+			fibril_rwlock_read_unlock(&device_tree.rwlock);
+			
+			if (driver)
+				detach_driver(&device_tree, dev);
+			
+			fibril_rwlock_write_lock(&device_tree.rwlock);
+			remove_dev_node(&device_tree, dev);
+			
+			/* Delete ref created when node was inserted */
+			dev_del_ref(dev);
+			/* Delete ref created by dev_add_ref(dev) above */
+			dev_del_ref(dev);
+		}
+	} else {
+		/* Unregister from location service */
+		rc = loc_service_unregister(fun->service_id);
+		if (rc != EOK) {
+			fibril_rwlock_write_unlock(&device_tree.rwlock);
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Failed unregistering tree service.");
+			return EIO;
+		}
+		
+		fun->service_id = 0;
+	}
+	
+	fun->state = FUN_OFF_LINE;
+	fibril_rwlock_write_unlock(&device_tree.rwlock);
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/devman/fun.h
===================================================================
--- uspace/srv/devman/fun.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/fun.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2013 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 devman
+ * @{
+ */
+
+#ifndef FUN_H_
+#define FUN_H_
+
+#include "devman.h"
+
+extern fun_node_t *create_fun_node(void);
+extern void delete_fun_node(fun_node_t *);
+extern void fun_add_ref(fun_node_t *);
+extern void fun_del_ref(fun_node_t *);
+extern void fun_busy_lock(fun_node_t *);
+extern void fun_busy_unlock(fun_node_t *);
+extern fun_node_t *find_fun_node_no_lock(dev_tree_t *, devman_handle_t);
+extern fun_node_t *find_fun_node(dev_tree_t *, devman_handle_t);
+extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *);
+extern fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *,
+    const char *);
+extern bool set_fun_path(dev_tree_t *, fun_node_t *, fun_node_t *);
+extern int fun_online(fun_node_t *);
+extern int fun_offline(fun_node_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/loc.c
===================================================================
--- uspace/srv/devman/loc.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/loc.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,93 @@
+/*
+ * 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 devman
+ * @{
+ */
+
+#include <loc.h>
+#include <stdio.h>
+
+#include "devman.h"
+#include "fun.h"
+#include "loc.h"
+
+/** Create loc path and name for the function. */
+void loc_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
+{
+	char *loc_pathname = NULL;
+	char *loc_name = NULL;
+	
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+	
+	asprintf(&loc_name, "%s", fun->pathname);
+	if (loc_name == NULL)
+		return;
+	
+	replace_char(loc_name, '/', LOC_SEPARATOR);
+	
+	asprintf(&loc_pathname, "%s/%s", LOC_DEVICE_NAMESPACE,
+	    loc_name);
+	if (loc_pathname == NULL) {
+		free(loc_name);
+		return;
+	}
+	
+	loc_service_register_with_iface(loc_pathname,
+	    &fun->service_id, DEVMAN_CONNECT_FROM_LOC);
+	
+	tree_add_loc_function(tree, fun);
+	
+	free(loc_name);
+	free(loc_pathname);
+}
+
+fun_node_t *find_loc_tree_function(dev_tree_t *tree, service_id_t service_id)
+{
+	fun_node_t *fun = NULL;
+	
+	fibril_rwlock_read_lock(&tree->rwlock);
+	ht_link_t *link = hash_table_find(&tree->loc_functions, &service_id);
+	if (link != NULL) {
+		fun = hash_table_get_inst(link, fun_node_t, loc_fun);
+		fun_add_ref(fun);
+	}
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	return fun;
+}
+
+void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun)
+{
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
+	
+	hash_table_insert(&tree->loc_functions, &fun->loc_fun);
+}
+
+/** @}
+ */
Index: uspace/srv/devman/loc.h
===================================================================
--- uspace/srv/devman/loc.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/loc.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,47 @@
+/*
+ * 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 devman
+ * @{
+ */
+
+#ifndef LOC_H_
+#define LOC_H_
+
+#include <ipc/loc.h>
+#include "devman.h"
+
+extern void loc_register_tree_function(fun_node_t *, dev_tree_t *);
+extern fun_node_t *find_loc_tree_function(dev_tree_t *, service_id_t);
+extern void tree_add_loc_function(dev_tree_t *, fun_node_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/devman/main.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -36,5 +36,4 @@
  */
 
-#include <inttypes.h>
 #include <assert.h>
 #include <ipc/services.h>
@@ -43,1163 +42,27 @@
 #include <stdio.h>
 #include <errno.h>
-#include <str_error.h>
 #include <stdbool.h>
 #include <fibril_synch.h>
 #include <stdlib.h>
 #include <str.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <sys/stat.h>
 #include <ctype.h>
 #include <io/log.h>
 #include <ipc/devman.h>
 #include <ipc/driver.h>
-#include <thread.h>
 #include <loc.h>
 
+#include "client_conn.h"
+#include "dev.h"
 #include "devman.h"
+#include "devtree.h"
+#include "drv_conn.h"
+#include "driver.h"
+#include "fun.h"
+#include "loc.h"
 
 #define DRIVER_DEFAULT_STORE  "/drv"
 
-static driver_list_t drivers_list;
-static dev_tree_t device_tree;
-
-static int init_running_drv(void *drv);
-
-/** Register running driver. */
-static driver_t *devman_driver_register(ipc_callid_t callid, ipc_call_t *call)
-{
-	driver_t *driver = NULL;
-	char *drv_name = NULL;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_driver_register");
-	
-	/* Get driver name. */
-	int rc = async_data_write_accept((void **) &drv_name, true, 0, 0, 0, 0);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return NULL;
-	}
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "The `%s' driver is trying to register.",
-	    drv_name);
-	
-	/* Find driver structure. */
-	driver = find_driver(&drivers_list, drv_name);
-	if (driver == NULL) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "No driver named `%s' was found.", drv_name);
-		free(drv_name);
-		drv_name = NULL;
-		async_answer_0(callid, ENOENT);
-		return NULL;
-	}
-	
-	free(drv_name);
-	drv_name = NULL;
-	
-	fibril_mutex_lock(&driver->driver_mutex);
-	
-	if (driver->sess) {
-		/* We already have a connection to the driver. */
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Driver '%s' already started.\n",
-		    driver->name);
-		fibril_mutex_unlock(&driver->driver_mutex);
-		async_answer_0(callid, EEXISTS);
-		return NULL;
-	}
-	
-	switch (driver->state) {
-	case DRIVER_NOT_STARTED:
-		/* Somebody started the driver manually. */
-		log_msg(LOG_DEFAULT, LVL_NOTE, "Driver '%s' started manually.\n",
-		    driver->name);
-		driver->state = DRIVER_STARTING;
-		break;
-	case DRIVER_STARTING:
-		/* The expected case */
-		break;
-	case DRIVER_RUNNING:
-		/* Should not happen since we do not have a connected session */
-		assert(false);
-	}
-	
-	/* Create connection to the driver. */
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Creating connection to the `%s' driver.",
-	    driver->name);
-	driver->sess = async_callback_receive(EXCHANGE_PARALLEL);
-	if (!driver->sess) {
-		fibril_mutex_unlock(&driver->driver_mutex);
-		async_answer_0(callid, ENOTSUP);
-		return NULL;
-	}
-	/* FIXME: Work around problem with callback sessions */
-	async_sess_args_set(driver->sess, DRIVER_DEVMAN, 0, 0);
-	
-	log_msg(LOG_DEFAULT, LVL_NOTE,
-	    "The `%s' driver was successfully registered as running.",
-	    driver->name);
-	
-	/*
-	 * Initialize the driver as running (e.g. pass assigned devices to it)
-	 * in a separate fibril; the separate fibril is used to enable the
-	 * driver to use devman service during the driver's initialization.
-	 */
-	fid_t fid = fibril_create(init_running_drv, driver);
-	if (fid == 0) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to create initialization fibril " \
-		    "for driver `%s'.", driver->name);
-		fibril_mutex_unlock(&driver->driver_mutex);
-		async_answer_0(callid, ENOMEM);
-		return NULL;
-	}
-	
-	fibril_add_ready(fid);
-	fibril_mutex_unlock(&driver->driver_mutex);
-	
-	async_answer_0(callid, EOK);
-	return driver;
-}
-
-/** Receive device match ID from the device's parent driver and add it to the
- * list of devices match ids.
- *
- * @param match_ids	The list of the device's match ids.
- * @return		Zero on success, negative error code otherwise.
- */
-static int devman_receive_match_id(match_id_list_t *match_ids)
-{
-	match_id_t *match_id = create_match_id();
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int rc = 0;
-	
-	callid = async_get_call(&call);
-	if (DEVMAN_ADD_MATCH_ID != IPC_GET_IMETHOD(call)) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, 
-		    "Invalid protocol when trying to receive match id.");
-		async_answer_0(callid, EINVAL); 
-		delete_match_id(match_id);
-		return EINVAL;
-	}
-	
-	if (match_id == NULL) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to allocate match id.");
-		async_answer_0(callid, ENOMEM);
-		return ENOMEM;
-	}
-	
-	async_answer_0(callid, EOK);
-	
-	match_id->score = IPC_GET_ARG1(call);
-	
-	char *match_id_str;
-	rc = async_data_write_accept((void **) &match_id_str, true, 0, 0, 0, 0);
-	match_id->id = match_id_str;
-	if (rc != EOK) {
-		delete_match_id(match_id);
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to receive match id string: %s.",
-		    str_error(rc));
-		return rc;
-	}
-	
-	list_append(&match_id->link, &match_ids->ids);
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "Received match id `%s', score %d.",
-	    match_id->id, match_id->score);
-	return rc;
-}
-
-/** Receive device match IDs from the device's parent driver and add them to the
- * list of devices match ids.
- *
- * @param match_count	The number of device's match ids to be received.
- * @param match_ids	The list of the device's match ids.
- * @return		Zero on success, negative error code otherwise.
- */
-static int devman_receive_match_ids(sysarg_t match_count,
-    match_id_list_t *match_ids)
-{
-	int ret = EOK;
-	size_t i;
-	
-	for (i = 0; i < match_count; i++) {
-		if (EOK != (ret = devman_receive_match_id(match_ids)))
-			return ret;
-	}
-	return ret;
-}
-
-static int assign_driver_fibril(void *arg)
-{
-	dev_node_t *dev_node = (dev_node_t *) arg;
-	assign_driver(dev_node, &drivers_list, &device_tree);
-
-	/* Delete one reference we got from the caller. */
-	dev_del_ref(dev_node);
-	return EOK;
-}
-
-static int online_function(fun_node_t *fun)
-{
-	dev_node_t *dev;
-	
-	fibril_rwlock_write_lock(&device_tree.rwlock);
-	
-	if (fun->state == FUN_ON_LINE) {
-		fibril_rwlock_write_unlock(&device_tree.rwlock);
-		log_msg(LOG_DEFAULT, LVL_WARN, "Function %s is already on line.",
-		    fun->pathname);
-		return EOK;
-	}
-	
-	if (fun->ftype == fun_inner) {
-		dev = create_dev_node();
-		if (dev == NULL) {
-			fibril_rwlock_write_unlock(&device_tree.rwlock);
-			return ENOMEM;
-		}
-		
-		insert_dev_node(&device_tree, dev, fun);
-		dev_add_ref(dev);
-	}
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
-	
-	if (fun->ftype == fun_inner) {
-		dev = fun->child;
-		assert(dev != NULL);
-		
-		/* Give one reference over to assign_driver_fibril(). */
-		dev_add_ref(dev);
-		
-		/*
-		 * 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, dev);
-		if (assign_fibril == 0) {
-			log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to create fibril for "
-			    "assigning driver.");
-			/* XXX Cleanup */
-			fibril_rwlock_write_unlock(&device_tree.rwlock);
-			return ENOMEM;
-		}
-		fibril_add_ready(assign_fibril);
-	} else
-		loc_register_tree_function(fun, &device_tree);
-	
-	fibril_rwlock_write_unlock(&device_tree.rwlock);
-	
-	return EOK;
-}
-
-static int offline_function(fun_node_t *fun)
-{
-	int rc;
-	
-	fibril_rwlock_write_lock(&device_tree.rwlock);
-	
-	if (fun->state == FUN_OFF_LINE) {
-		fibril_rwlock_write_unlock(&device_tree.rwlock);
-		log_msg(LOG_DEFAULT, LVL_WARN, "Function %s is already off line.",
-		    fun->pathname);
-		return EOK;
-	}
-	
-	if (fun->ftype == fun_inner) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "Offlining inner function %s.",
-		    fun->pathname);
-		
-		if (fun->child != NULL) {
-			dev_node_t *dev = fun->child;
-			device_state_t dev_state;
-			
-			dev_add_ref(dev);
-			dev_state = dev->state;
-			
-			fibril_rwlock_write_unlock(&device_tree.rwlock);
-
-			/* If device is owned by driver, ask driver to give it up. */
-			if (dev_state == DEVICE_USABLE) {
-				rc = driver_dev_remove(&device_tree, dev);
-				if (rc != EOK) {
-					dev_del_ref(dev);
-					return ENOTSUP;
-				}
-			}
-			
-			/* Verify that driver removed all functions */
-			fibril_rwlock_read_lock(&device_tree.rwlock);
-			if (!list_empty(&dev->functions)) {
-				fibril_rwlock_read_unlock(&device_tree.rwlock);
-				dev_del_ref(dev);
-				return EIO;
-			}
-			
-			driver_t *driver = dev->drv;
-			fibril_rwlock_read_unlock(&device_tree.rwlock);
-			
-			if (driver)
-				detach_driver(&device_tree, dev);
-			
-			fibril_rwlock_write_lock(&device_tree.rwlock);
-			remove_dev_node(&device_tree, dev);
-			
-			/* Delete ref created when node was inserted */
-			dev_del_ref(dev);
-			/* Delete ref created by dev_add_ref(dev) above */
-			dev_del_ref(dev);
-		}
-	} else {
-		/* Unregister from location service */
-		rc = loc_service_unregister(fun->service_id);
-		if (rc != EOK) {
-			fibril_rwlock_write_unlock(&device_tree.rwlock);
-			log_msg(LOG_DEFAULT, LVL_ERROR, "Failed unregistering tree service.");
-			return EIO;
-		}
-		
-		fun->service_id = 0;
-	}
-	
-	fun->state = FUN_OFF_LINE;
-	fibril_rwlock_write_unlock(&device_tree.rwlock);
-	
-	return EOK;
-}
-
-/** Handle function registration.
- *
- * Child devices are registered by their parent's device driver.
- */
-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;
-	
-	dev_node_t *pdev = find_dev_node(&device_tree, dev_handle);
-	if (pdev == NULL) {
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	if (ftype != fun_inner && ftype != fun_exposed) {
-		/* Unknown function type */
-		log_msg(LOG_DEFAULT, LVL_ERROR, 
-		    "Unknown function type %d provided by driver.",
-		    (int) ftype);
-
-		dev_del_ref(pdev);
-		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) {
-		dev_del_ref(pdev);
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	fibril_rwlock_write_lock(&tree->rwlock);
-	
-	/* Check device state */
-	if (pdev->state == DEVICE_REMOVED) {
-		fibril_rwlock_write_unlock(&tree->rwlock);
-		dev_del_ref(pdev);
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	/* Check that function with same name is not there already. */
-	fun_node_t *tfun = find_fun_node_in_device(tree, pdev, fun_name);
-	if (tfun) {
-		fun_del_ref(tfun);	/* drop the new unwanted reference */
-		fibril_rwlock_write_unlock(&tree->rwlock);
-		dev_del_ref(pdev);
-		async_answer_0(callid, EEXISTS);
-		printf(NAME ": Warning, driver tried to register `%s' twice.\n",
-		    fun_name);
-		free(fun_name);
-		return;
-	}
-	
-	fun_node_t *fun = create_fun_node();
-	/* One reference for creation, one for us */
-	fun_add_ref(fun);
-	fun_add_ref(fun);
-	fun->ftype = ftype;
-	
-	/*
-	 * We can lock the function here even when holding the tree because
-	 * we know it cannot be held by anyone else yet.
-	 */
-	fun_busy_lock(fun);
-	
-	if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
-		fibril_rwlock_write_unlock(&tree->rwlock);
-		dev_del_ref(pdev);
-		fun_busy_unlock(fun);
-		fun_del_ref(fun);
-		delete_fun_node(fun);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-	
-	fibril_rwlock_write_unlock(&tree->rwlock);
-	dev_del_ref(pdev);
-	
-	devman_receive_match_ids(match_count, &fun->match_ids);
-	
-	rc = online_function(fun);
-	if (rc != EOK) {
-		/* XXX Set some failed state? */
-		fun_busy_unlock(fun);
-		fun_del_ref(fun);
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	fun_busy_unlock(fun);
-	fun_del_ref(fun);
-	
-	/* Return device handle to parent's driver. */
-	async_answer_1(callid, EOK, fun->handle);
-}
-
-static void devman_add_function_to_cat(ipc_callid_t callid, ipc_call_t *call)
-{
-	devman_handle_t handle = IPC_GET_ARG1(*call);
-	category_id_t cat_id;
-	int rc;
-	
-	/* Get category name. */
-	char *cat_name;
-	rc = async_data_write_accept((void **) &cat_name, true,
-	    0, 0, 0, 0);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-	
-	fun_node_t *fun = find_fun_node(&device_tree, handle);
-	if (fun == NULL) {
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	fibril_rwlock_read_lock(&device_tree.rwlock);
-	
-	/* Check function state */
-	if (fun->state == FUN_REMOVED) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING);
-	if (rc == EOK) {
-		loc_service_add_to_cat(fun->service_id, cat_id);
-		log_msg(LOG_DEFAULT, LVL_NOTE, "Function `%s' added to category `%s'.",
-		    fun->pathname, cat_name);
-	} else {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding function `%s' to category "
-		    "`%s'.", fun->pathname, cat_name);
-	}
-	
-	fibril_rwlock_read_unlock(&device_tree.rwlock);
-	fun_del_ref(fun);
-	
-	async_answer_0(callid, rc);
-}
-
-/** Online function by driver request.
- *
- */
-static void devman_drv_fun_online(ipc_callid_t iid, ipc_call_t *icall,
-    driver_t *drv)
-{
-	fun_node_t *fun;
-	int rc;
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_drv_fun_online()");
-	
-	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
-	if (fun == NULL) {
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	fun_busy_lock(fun);
-	
-	fibril_rwlock_read_lock(&device_tree.rwlock);
-	if (fun->dev == NULL || fun->dev->drv != drv) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		fun_busy_unlock(fun);
-		fun_del_ref(fun);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	fibril_rwlock_read_unlock(&device_tree.rwlock);
-	
-	rc = online_function(fun);
-	if (rc != EOK) {
-		fun_busy_unlock(fun);
-		fun_del_ref(fun);
-		async_answer_0(iid, (sysarg_t) rc);
-		return;
-	}
-	
-	fun_busy_unlock(fun);
-	fun_del_ref(fun);
-	
-	async_answer_0(iid, (sysarg_t) EOK);
-}
-
-
-/** Offline function by driver request.
- *
- */
-static void devman_drv_fun_offline(ipc_callid_t iid, ipc_call_t *icall,
-    driver_t *drv)
-{
-	fun_node_t *fun;
-	int rc;
-
-	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
-	if (fun == NULL) {
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	fun_busy_lock(fun);
-	
-	fibril_rwlock_write_lock(&device_tree.rwlock);
-	if (fun->dev == NULL || fun->dev->drv != drv) {
-		fun_busy_unlock(fun);
-		fun_del_ref(fun);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	fibril_rwlock_write_unlock(&device_tree.rwlock);
-	
-	rc = offline_function(fun);
-	if (rc != EOK) {
-		fun_busy_unlock(fun);
-		fun_del_ref(fun);
-		async_answer_0(iid, (sysarg_t) rc);
-		return;
-	}
-	
-	fun_busy_unlock(fun);
-	fun_del_ref(fun);
-	async_answer_0(iid, (sysarg_t) EOK);
-}
-
-/** Remove function. */
-static void devman_remove_function(ipc_callid_t callid, ipc_call_t *call)
-{
-	devman_handle_t fun_handle = IPC_GET_ARG1(*call);
-	dev_tree_t *tree = &device_tree;
-	int rc;
-	
-	fun_node_t *fun = find_fun_node(&device_tree, fun_handle);
-	if (fun == NULL) {
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	fun_busy_lock(fun);
-	
-	fibril_rwlock_write_lock(&tree->rwlock);
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
-	
-	/* Check function state */
-	if (fun->state == FUN_REMOVED) {
-		fibril_rwlock_write_unlock(&tree->rwlock);
-		fun_busy_unlock(fun);
-		fun_del_ref(fun);
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	if (fun->ftype == fun_inner) {
-		/* This is a surprise removal. Handle possible descendants */
-		if (fun->child != NULL) {
-			dev_node_t *dev = fun->child;
-			device_state_t dev_state;
-			int gone_rc;
-			
-			dev_add_ref(dev);
-			dev_state = dev->state;
-			
-			fibril_rwlock_write_unlock(&device_tree.rwlock);
-			
-			/* If device is owned by driver, inform driver it is gone. */
-			if (dev_state == DEVICE_USABLE)
-				gone_rc = driver_dev_gone(&device_tree, dev);
-			else
-				gone_rc = EOK;
-			
-			fibril_rwlock_read_lock(&device_tree.rwlock);
-			
-			/* Verify that driver succeeded and removed all functions */
-			if (gone_rc != EOK || !list_empty(&dev->functions)) {
-				log_msg(LOG_DEFAULT, LVL_ERROR, "Driver did not remove "
-				    "functions for device that is gone. "
-				    "Device node is now defunct.");
-				
-				/*
-				 * Not much we can do but mark the device
-				 * node as having invalid state. This
-				 * is a driver bug.
-				 */
-				dev->state = DEVICE_INVALID;
-				fibril_rwlock_read_unlock(&device_tree.rwlock);
-				dev_del_ref(dev);
-				if (gone_rc == EOK)
-					gone_rc = ENOTSUP;
-				fun_busy_unlock(fun);
-				fun_del_ref(fun);
-				async_answer_0(callid, gone_rc);
-				return;
-			}
-			
-			driver_t *driver = dev->drv;
-			fibril_rwlock_read_unlock(&device_tree.rwlock);
-			
-			if (driver)
-				detach_driver(&device_tree, dev);
-			
-			fibril_rwlock_write_lock(&device_tree.rwlock);
-			remove_dev_node(&device_tree, dev);
-			
-			/* Delete ref created when node was inserted */
-			dev_del_ref(dev);
-			/* Delete ref created by dev_add_ref(dev) above */
-			dev_del_ref(dev);
-		}
-	} else {
-		if (fun->service_id != 0) {
-			/* Unregister from location service */
-			rc = loc_service_unregister(fun->service_id);
-			if (rc != EOK) {
-				log_msg(LOG_DEFAULT, LVL_ERROR, "Failed unregistering tree "
-				    "service.");
-				fibril_rwlock_write_unlock(&tree->rwlock);
-				fun_busy_unlock(fun);
-				fun_del_ref(fun);
-				async_answer_0(callid, EIO);
-				return;
-			}
-		}
-	}
-	
-	remove_fun_node(&device_tree, fun);
-	fibril_rwlock_write_unlock(&tree->rwlock);
-	fun_busy_unlock(fun);
-	
-	/* Delete ref added when inserting function into tree */
-	fun_del_ref(fun);
-	/* Delete ref added above when looking up function */
-	fun_del_ref(fun);
-	
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_remove_function() succeeded.");
-	async_answer_0(callid, EOK);
-}
-
-/** Initialize driver which has registered itself as running and ready.
- *
- * The initialization is done in a separate fibril to avoid deadlocks (if the
- * driver needed to be served by devman during the driver's initialization).
- */
-static int init_running_drv(void *drv)
-{
-	driver_t *driver = (driver_t *) drv;
-	
-	initialize_running_driver(driver, &device_tree);
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "The `%s` driver was successfully initialized.",
-	    driver->name);
-	return 0;
-}
-
-/** Function for handling connections from a driver to the device manager. */
-static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
-{
-	client_t *client;
-	driver_t *driver = NULL;
-	
-	/* Accept the connection. */
-	async_answer_0(iid, EOK);
-	
-	client = async_get_client_data();
-	if (client == NULL) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to allocate client data.");
-		return;
-	}
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			break;
-		
-		if (IPC_GET_IMETHOD(call) != DEVMAN_DRIVER_REGISTER) {
-			fibril_mutex_lock(&client->mutex);
-			driver = client->driver;
-			fibril_mutex_unlock(&client->mutex);
-			if (driver == NULL) {
-				/* First call must be to DEVMAN_DRIVER_REGISTER */
-				async_answer_0(callid, ENOTSUP);
-				continue;
-			}
-		}
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case DEVMAN_DRIVER_REGISTER:
-			fibril_mutex_lock(&client->mutex);
-			if (client->driver != NULL) {
-				fibril_mutex_unlock(&client->mutex);
-				async_answer_0(callid, EINVAL);
-				continue;
-			}
-			client->driver = devman_driver_register(callid, &call);
-			fibril_mutex_unlock(&client->mutex);
-			break;
-		case DEVMAN_ADD_FUNCTION:
-			devman_add_function(callid, &call);
-			break;
-		case DEVMAN_ADD_DEVICE_TO_CATEGORY:
-			devman_add_function_to_cat(callid, &call);
-			break;
-		case DEVMAN_DRV_FUN_ONLINE:
-			devman_drv_fun_online(callid, &call, driver);
-			break;
-		case DEVMAN_DRV_FUN_OFFLINE:
-			devman_drv_fun_offline(callid, &call, driver);
-			break;
-		case DEVMAN_REMOVE_FUNCTION:
-			devman_remove_function(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, EINVAL);
-			break;
-		}
-	}
-}
-
-/** Find handle for the device instance identified by the device's path in the
- * device tree. */
-static void devman_function_get_handle(ipc_callid_t iid, ipc_call_t *icall)
-{
-	char *pathname;
-	devman_handle_t handle;
-	
-	int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-	
-	fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname);
-	
-	free(pathname);
-
-	if (fun == NULL) {
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-
-	fibril_rwlock_read_lock(&device_tree.rwlock);
-
-	/* Check function state */
-	if (fun->state == FUN_REMOVED) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	handle = fun->handle;
-
-	fibril_rwlock_read_unlock(&device_tree.rwlock);
-
-	/* Delete reference created above by find_fun_node_by_path() */
-	fun_del_ref(fun);
-
-	async_answer_1(iid, EOK, handle);
-}
-
-/** Get device name. */
-static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall)
-{
-	devman_handle_t handle = IPC_GET_ARG1(*icall);
-
-	fun_node_t *fun = find_fun_node(&device_tree, handle);
-	if (fun == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-
-	ipc_callid_t data_callid;
-	size_t data_len;
-	if (!async_data_read_receive(&data_callid, &data_len)) {
-		async_answer_0(iid, EINVAL);
-		fun_del_ref(fun);
-		return;
-	}
-
-	void *buffer = malloc(data_len);
-	if (buffer == NULL) {
-		async_answer_0(data_callid, ENOMEM);
-		async_answer_0(iid, ENOMEM);
-		fun_del_ref(fun);
-		return;
-	}
-
-	fibril_rwlock_read_lock(&device_tree.rwlock);
-
-	/* Check function state */
-	if (fun->state == FUN_REMOVED) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		free(buffer);
-
-		async_answer_0(data_callid, ENOENT);
-		async_answer_0(iid, ENOENT);
-		fun_del_ref(fun);
-		return;
-	}
-
-	size_t sent_length = str_size(fun->name);
-	if (sent_length > data_len) {
-		sent_length = data_len;
-	}
-
-	async_data_read_finalize(data_callid, fun->name, sent_length);
-	async_answer_0(iid, EOK);
-
-	fibril_rwlock_read_unlock(&device_tree.rwlock);
-	fun_del_ref(fun);
-	free(buffer);
-}
-
-/** Get function driver name. */
-static void devman_fun_get_driver_name(ipc_callid_t iid, ipc_call_t *icall)
-{
-	devman_handle_t handle = IPC_GET_ARG1(*icall);
-
-	fun_node_t *fun = find_fun_node(&device_tree, handle);
-	if (fun == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-
-	ipc_callid_t data_callid;
-	size_t data_len;
-	if (!async_data_read_receive(&data_callid, &data_len)) {
-		async_answer_0(iid, EINVAL);
-		fun_del_ref(fun);
-		return;
-	}
-
-	void *buffer = malloc(data_len);
-	if (buffer == NULL) {
-		async_answer_0(data_callid, ENOMEM);
-		async_answer_0(iid, ENOMEM);
-		fun_del_ref(fun);
-		return;
-	}
-
-	fibril_rwlock_read_lock(&device_tree.rwlock);
-
-	/* Check function state */
-	if (fun->state == FUN_REMOVED) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		free(buffer);
-
-		async_answer_0(data_callid, ENOENT);
-		async_answer_0(iid, ENOENT);
-		fun_del_ref(fun);
-		return;
-	}
-
-	/* Check whether function has a driver */
-	if (fun->child == NULL || fun->child->drv == NULL) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		free(buffer);
-
-		async_answer_0(data_callid, EINVAL);
-		async_answer_0(iid, EINVAL);
-		fun_del_ref(fun);
-		return;
-	}
-
-	size_t sent_length = str_size(fun->child->drv->name);
-	if (sent_length > data_len) {
-		sent_length = data_len;
-	}
-
-	async_data_read_finalize(data_callid, fun->child->drv->name,
-	    sent_length);
-	async_answer_0(iid, EOK);
-
-	fibril_rwlock_read_unlock(&device_tree.rwlock);
-	fun_del_ref(fun);
-	free(buffer);
-}
-
-/** Get device path. */
-static void devman_fun_get_path(ipc_callid_t iid, ipc_call_t *icall)
-{
-	devman_handle_t handle = IPC_GET_ARG1(*icall);
-
-	fun_node_t *fun = find_fun_node(&device_tree, handle);
-	if (fun == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-
-	ipc_callid_t data_callid;
-	size_t data_len;
-	if (!async_data_read_receive(&data_callid, &data_len)) {
-		async_answer_0(iid, EINVAL);
-		fun_del_ref(fun);
-		return;
-	}
-
-	void *buffer = malloc(data_len);
-	if (buffer == NULL) {
-		async_answer_0(data_callid, ENOMEM);
-		async_answer_0(iid, ENOMEM);
-		fun_del_ref(fun);
-		return;
-	}
-	
-	fibril_rwlock_read_lock(&device_tree.rwlock);
-	
-	/* Check function state */
-	if (fun->state == FUN_REMOVED) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		free(buffer);
-
-		async_answer_0(data_callid, ENOENT);
-		async_answer_0(iid, ENOENT);
-		fun_del_ref(fun);
-		return;
-	}
-	
-	size_t sent_length = str_size(fun->pathname);
-	if (sent_length > data_len) {
-		sent_length = data_len;
-	}
-
-	async_data_read_finalize(data_callid, fun->pathname, sent_length);
-	async_answer_0(iid, EOK);
-
-	fibril_rwlock_read_unlock(&device_tree.rwlock);
-	fun_del_ref(fun);
-	free(buffer);
-}
-
-static void devman_dev_get_functions(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	size_t size;
-	size_t act_size;
-	int rc;
-	
-	if (!async_data_read_receive(&callid, &size)) {
-		async_answer_0(callid, EREFUSED);
-		async_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	fibril_rwlock_read_lock(&device_tree.rwlock);
-	
-	dev_node_t *dev = find_dev_node_no_lock(&device_tree,
-	    IPC_GET_ARG1(*icall));
-	if (dev == NULL || dev->state == DEVICE_REMOVED) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		async_answer_0(callid, ENOENT);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
-	if (hdl_buf == NULL) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		async_answer_0(callid, ENOMEM);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size);
-	if (rc != EOK) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		async_answer_0(callid, rc);
-		async_answer_0(iid, rc);
-		return;
-	}
-	
-	fibril_rwlock_read_unlock(&device_tree.rwlock);
-	
-	sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size);
-	free(hdl_buf);
-	
-	async_answer_1(iid, retval, act_size);
-}
-
-
-/** Get handle for child device of a function. */
-static void devman_fun_get_child(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fun_node_t *fun;
-	
-	fibril_rwlock_read_lock(&device_tree.rwlock);
-	
-	fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
-	if (fun == NULL || fun->state == FUN_REMOVED) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	if (fun->child == NULL) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	async_answer_1(iid, EOK, fun->child->handle);
-	
-	fibril_rwlock_read_unlock(&device_tree.rwlock);
-}
-
-/** Online function.
- *
- * Send a request to online a function to the responsible driver.
- * The driver may offline other functions if necessary (i.e. if the state
- * of this function is linked to state of another function somehow).
- */
-static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fun_node_t *fun;
-	int rc;
-
-	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
-	if (fun == NULL) {
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	rc = driver_fun_online(&device_tree, fun);
-	fun_del_ref(fun);
-	
-	async_answer_0(iid, (sysarg_t) rc);
-}
-
-/** Offline function.
- *
- * Send a request to offline a function to the responsible driver. As
- * a result the subtree rooted at that function should be cleanly
- * detatched. The driver may offline other functions if necessary
- * (i.e. if the state of this function is linked to state of another
- * function somehow).
- */
-static void devman_fun_offline(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fun_node_t *fun;
-	int rc;
-
-	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
-	if (fun == NULL) {
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	rc = driver_fun_offline(&device_tree, fun);
-	fun_del_ref(fun);
-	
-	async_answer_0(iid, (sysarg_t) rc);
-}
-
-/** Find handle for the function instance identified by its service ID. */
-static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fun_node_t *fun;
-
-	fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall));
-	
-	if (fun == NULL) {
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-
-	fibril_rwlock_read_lock(&device_tree.rwlock);
-
-	/* Check function state */
-	if (fun->state == FUN_REMOVED) {
-		fibril_rwlock_read_unlock(&device_tree.rwlock);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-
-	async_answer_1(iid, EOK, fun->handle);
-	fibril_rwlock_read_unlock(&device_tree.rwlock);
-	fun_del_ref(fun);
-}
-
-/** Function for handling connections from a client to the device manager. */
-static void devman_connection_client(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Accept connection. */
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			break;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case DEVMAN_DEVICE_GET_HANDLE:
-			devman_function_get_handle(callid, &call);
-			break;
-		case DEVMAN_DEV_GET_FUNCTIONS:
-			devman_dev_get_functions(callid, &call);
-			break;
-		case DEVMAN_FUN_GET_CHILD:
-			devman_fun_get_child(callid, &call);
-			break;
-		case DEVMAN_FUN_GET_NAME:
-			devman_fun_get_name(callid, &call);
-			break;
-		case DEVMAN_FUN_GET_DRIVER_NAME:
-			devman_fun_get_driver_name(callid, &call);
-			break;
-		case DEVMAN_FUN_GET_PATH:
-			devman_fun_get_path(callid, &call);
-			break;
-		case DEVMAN_FUN_ONLINE:
-			devman_fun_online(callid, &call);
-			break;
-		case DEVMAN_FUN_OFFLINE:
-			devman_fun_offline(callid, &call);
-			break;
-		case DEVMAN_FUN_SID_TO_HANDLE:
-			devman_fun_sid_to_handle(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOENT);
-		}
-	}
-}
+driver_list_t drivers_list;
+dev_tree_t device_tree;
 
 static void devman_forward(ipc_callid_t iid, ipc_call_t *icall,
Index: uspace/srv/devman/main.h
===================================================================
--- uspace/srv/devman/main.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/main.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 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 devman
+ * @{
+ */
+
+#ifndef MAIN_H_
+#define MAIN_H_
+
+#include "devman.h"
+
+extern driver_list_t drivers_list;
+extern dev_tree_t device_tree;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/match.c
===================================================================
--- uspace/srv/devman/match.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/devman/match.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -31,7 +31,13 @@
  */
 
+#include <fcntl.h>
+#include <io/log.h>
 #include <str.h>
+#include <str_error.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include "devman.h"
+#include "match.h"
 
 /** Compute compound score of driver and device.
@@ -93,4 +99,141 @@
 }
 
+/** Read match id at the specified position of a string and set the position in
+ * the string to the first character following the id.
+ *
+ * @param buf		The position in the input string.
+ * @return		The match id.
+ */
+char *read_match_id(char **buf)
+{
+	char *res = NULL;
+	size_t len = get_nonspace_len(*buf);
+	
+	if (len > 0) {
+		res = malloc(len + 1);
+		if (res != NULL) {
+			str_ncpy(res, len + 1, *buf, len);
+			*buf += len;
+		}
+	}
+	
+	return res;
+}
+
+/**
+ * Read match ids and associated match scores from a string.
+ *
+ * Each match score in the string is followed by its match id.
+ * The match ids and match scores are separated by whitespaces.
+ * Neither match ids nor match scores can contain whitespaces.
+ *
+ * @param buf		The string from which the match ids are read.
+ * @param ids		The list of match ids into which the match ids and
+ *			scores are added.
+ * @return		True if at least one match id and associated match score
+ *			was successfully read, false otherwise.
+ */
+bool parse_match_ids(char *buf, match_id_list_t *ids)
+{
+	int score = 0;
+	char *id = NULL;
+	int ids_read = 0;
+	
+	while (true) {
+		/* skip spaces */
+		if (!skip_spaces(&buf))
+			break;
+		
+		/* read score */
+		score = strtoul(buf, &buf, 10);
+		
+		/* skip spaces */
+		if (!skip_spaces(&buf))
+			break;
+		
+		/* read id */
+		id = read_match_id(&buf);
+		if (NULL == id)
+			break;
+		
+		/* create new match_id structure */
+		match_id_t *mid = create_match_id();
+		mid->id = id;
+		mid->score = score;
+		
+		/* add it to the list */
+		add_match_id(ids, mid);
+		
+		ids_read++;
+	}
+	
+	return ids_read > 0;
+}
+
+/**
+ * Read match ids and associated match scores from a file.
+ *
+ * Each match score in the file is followed by its match id.
+ * The match ids and match scores are separated by whitespaces.
+ * Neither match ids nor match scores can contain whitespaces.
+ *
+ * @param buf		The path to the file from which the match ids are read.
+ * @param ids		The list of match ids into which the match ids and
+ *			scores are added.
+ * @return		True if at least one match id and associated match score
+ *			was successfully read, false otherwise.
+ */
+bool read_match_ids(const char *conf_path, match_id_list_t *ids)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path);
+	
+	bool suc = false;
+	char *buf = NULL;
+	bool opened = false;
+	int fd;
+	size_t len = 0;
+	
+	fd = open(conf_path, O_RDONLY);
+	if (fd < 0) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to open `%s' for reading: %s.",
+		    conf_path, str_error(fd));
+		goto cleanup;
+	}
+	opened = true;
+	
+	len = lseek(fd, 0, SEEK_END);
+	lseek(fd, 0, SEEK_SET);
+	if (len == 0) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Configuration file '%s' is empty.",
+		    conf_path);
+		goto cleanup;
+	}
+	
+	buf = malloc(len + 1);
+	if (buf == NULL) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Memory allocation failed when parsing file "
+		    "'%s'.", conf_path);
+		goto cleanup;
+	}
+	
+	ssize_t read_bytes = read_all(fd, buf, len);
+	if (read_bytes <= 0) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to read file '%s' (%zd).", conf_path,
+		    read_bytes);
+		goto cleanup;
+	}
+	buf[read_bytes] = 0;
+	
+	suc = parse_match_ids(buf, ids);
+	
+cleanup:
+	free(buf);
+	
+	if (opened)
+		close(fd);
+	
+	return suc;
+}
+
 /** @}
  */
Index: uspace/srv/devman/match.h
===================================================================
--- uspace/srv/devman/match.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
+++ uspace/srv/devman/match.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2013 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 devman
+ * @{
+ */
+
+#ifndef MATCH_H_
+#define MATCH_H_
+
+#include <stdbool.h>
+
+#include "devman.h"
+
+#define MATCH_EXT ".ma"
+
+extern int get_match_score(driver_t *, dev_node_t *);
+extern bool parse_match_ids(char *, match_id_list_t *);
+extern bool read_match_ids(const char *, match_id_list_t *);
+extern char *read_match_id(char **);
+extern char *read_id(const char **);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/util.c
===================================================================
--- uspace/srv/devman/util.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/devman/util.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -85,10 +85,4 @@
 }
 
-void free_not_null(const void *ptr)
-{
-	if (ptr != NULL)
-		free(ptr);
-}
-
 void replace_char(char *str, char orig, char repl)
 {
Index: uspace/srv/devman/util.h
===================================================================
--- uspace/srv/devman/util.h	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/devman/util.h	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -43,5 +43,4 @@
 extern bool skip_spaces(char **);
 extern size_t get_nonspace_len(const char *);
-extern void free_not_null(const void *);
 extern void replace_char(char *, char, char);
 
Index: uspace/srv/fs/cdfs/cdfs_ops.c
===================================================================
--- uspace/srv/fs/cdfs/cdfs_ops.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/fs/cdfs/cdfs_ops.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -365,8 +365,5 @@
 	
 	/* Check for duplicate entries */
-	list_foreach(parent->cs_list, link) {
-		cdfs_dentry_t *dentry =
-		    list_get_instance(link, cdfs_dentry_t, link);
-		
+	list_foreach(parent->cs_list, link, cdfs_dentry_t, dentry) {
 		if (str_cmp(dentry->name, name) == 0)
 			return EEXIST;
@@ -524,8 +521,5 @@
 	}
 	
-	list_foreach(parent->cs_list, link) {
-		cdfs_dentry_t *dentry =
-		    list_get_instance(link, cdfs_dentry_t, link);
-		
+	list_foreach(parent->cs_list, link, cdfs_dentry_t, dentry) {
 		if (str_cmp(dentry->name, component) == 0) {
 			*fn = get_cached_node(parent->service_id, dentry->index);
Index: uspace/srv/fs/exfat/exfat_idx.c
===================================================================
--- uspace/srv/fs/exfat/exfat_idx.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/fs/exfat/exfat_idx.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -88,11 +88,8 @@
 static unused_t *unused_find(service_id_t service_id, bool lock)
 {
-	unused_t *u;
-
 	if (lock)
 		fibril_mutex_lock(&unused_lock);
 
-	list_foreach(unused_list, l) {
-		u = list_get_instance(l, unused_t, link);
+	list_foreach(unused_list, link, unused_t, u) {
 		if (u->service_id == service_id) 
 			return u;
Index: uspace/srv/fs/exfat/exfat_ops.c
===================================================================
--- uspace/srv/fs/exfat/exfat_ops.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/fs/exfat/exfat_ops.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -158,5 +158,4 @@
 static int exfat_node_fini_by_service_id(service_id_t service_id)
 {
-	exfat_node_t *nodep;
 	int rc;
 
@@ -169,6 +168,5 @@
 restart:
 	fibril_mutex_lock(&ffn_mutex);
-	list_foreach(ffn_list, lnk) {
-		nodep = list_get_instance(lnk, exfat_node_t, ffn_link);
+	list_foreach(ffn_list, ffn_link, exfat_node_t, nodep) {
 		if (!fibril_mutex_trylock(&nodep->lock)) {
 			fibril_mutex_unlock(&ffn_mutex);
Index: uspace/srv/fs/ext4fs/ext4fs_ops.c
===================================================================
--- uspace/srv/fs/ext4fs/ext4fs_ops.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/fs/ext4fs/ext4fs_ops.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -197,8 +197,5 @@
 	}
 	
-	list_foreach(instance_list, link) {
-		ext4fs_instance_t *tmp =
-		    list_get_instance(link, ext4fs_instance_t, link);
-		
+	list_foreach(instance_list, link, ext4fs_instance_t, tmp) {
 		if (tmp->service_id == service_id) {
 			*inst = tmp;
Index: uspace/srv/fs/fat/fat_idx.c
===================================================================
--- uspace/srv/fs/fat/fat_idx.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/fs/fat/fat_idx.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -88,11 +88,8 @@
 static unused_t *unused_find(service_id_t service_id, bool lock)
 {
-	unused_t *u;
-
 	if (lock)
 		fibril_mutex_lock(&unused_lock);
 
-	list_foreach(unused_list, l) {
-		u = list_get_instance(l, unused_t, link);
+	list_foreach(unused_list, link, unused_t, u) {
 		if (u->service_id == service_id) 
 			return u;
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -152,5 +152,4 @@
 static int fat_node_fini_by_service_id(service_id_t service_id)
 {
-	fat_node_t *nodep;
 	int rc;
 
@@ -163,6 +162,5 @@
 restart:
 	fibril_mutex_lock(&ffn_mutex);
-	list_foreach(ffn_list, lnk) {
-		nodep = list_get_instance(lnk, fat_node_t, ffn_link);
+	list_foreach(ffn_list, ffn_link, fat_node_t, nodep) {
 		if (!fibril_mutex_trylock(&nodep->lock)) {
 			fibril_mutex_unlock(&ffn_mutex);
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -259,7 +259,5 @@
 	tmpfs_node_t *parentp = TMPFS_NODE(pfn);
 
-	list_foreach(parentp->cs_list, lnk) {
-		tmpfs_dentry_t *dentryp;
-		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
+	list_foreach(parentp->cs_list, link, tmpfs_dentry_t, dentryp) {
 		if (!str_cmp(dentryp->name, component)) {
 			*rfn = FS_NODE(dentryp->node);
@@ -365,7 +363,6 @@
 
 	/* Check for duplicit entries. */
-	list_foreach(parentp->cs_list, lnk) {
-		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);	
-		if (!str_cmp(dentryp->name, nm))
+	list_foreach(parentp->cs_list, link, tmpfs_dentry_t, dp) {
+		if (!str_cmp(dp->name, nm))
 			return EEXIST;
 	}
@@ -400,8 +397,8 @@
 	if (!parentp)
 		return EBUSY;
-	
-	list_foreach(parentp->cs_list, lnk) {
-		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
-		if (!str_cmp(dentryp->name, nm)) {
+
+	list_foreach(parentp->cs_list, link, tmpfs_dentry_t, dp) {
+		if (!str_cmp(dp->name, nm)) {
+			dentryp = dp;
 			childp = dentryp->node;
 			assert(FS_NODE(childp) == cfn);
Index: uspace/srv/hid/compositor/compositor.c
===================================================================
--- uspace/srv/hid/compositor/compositor.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/hid/compositor/compositor.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -335,6 +335,5 @@
 	}
 
-	list_foreach(viewport_list, link) {
-		viewport_t *vp = list_get_instance(link, viewport_t, link);
+	list_foreach(viewport_list, link, viewport_t, vp) {
 		sysarg_t w_vp, h_vp;
 		surface_get_resolution(vp->surface, &w_vp, &h_vp);
@@ -354,6 +353,5 @@
 	fibril_mutex_lock(&pointer_list_mtx);
 
-	list_foreach(pointer_list, link) {
-		pointer_t *ptr = list_get_instance(link, pointer_t, link);
+	list_foreach(pointer_list, link, pointer_t, ptr) {
 		ptr->pos.x = ptr->pos.x > viewport_bound_rect.x ? ptr->pos.x : viewport_bound_rect.x;
 		ptr->pos.y = ptr->pos.y > viewport_bound_rect.y ? ptr->pos.y : viewport_bound_rect.y;
@@ -374,8 +372,6 @@
 	fibril_mutex_lock(&pointer_list_mtx);
 
-	list_foreach(viewport_list, link) {
-
+	list_foreach(viewport_list, link, viewport_t, vp) {
 		/* Determine what part of the viewport must be updated. */
-		viewport_t *vp = list_get_instance(link, viewport_t, link);
 		sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
 		surface_get_resolution(vp->surface, &w_dmg_vp, &h_dmg_vp);
@@ -446,7 +442,5 @@
 			}
 
-			list_foreach(pointer_list, link) {
-
-				pointer_t *ptr = list_get_instance(link, pointer_t, link);
+			list_foreach(pointer_list, link, pointer_t, ptr) {
 				if (ptr->ghost.surface) {
 
@@ -522,9 +516,8 @@
 			}
 
-			list_foreach(pointer_list, link) {
+			list_foreach(pointer_list, link, pointer_t, ptr) {
 
 				/* Determine what part of the pointer intersects with the
 				 * updated area of the current viewport. */
-				pointer_t *ptr = list_get_instance(link, pointer_t, link);
 				sysarg_t x_dmg_ptr, y_dmg_ptr, w_dmg_ptr, h_dmg_ptr;
 				surface_t *sf_ptr = ptr->cursor.states[ptr->state];
@@ -569,6 +562,5 @@
 
 	/* Notify visualizers about updated regions. */
-	list_foreach(viewport_list, link) {
-		viewport_t *vp = list_get_instance(link, viewport_t, link);
+	list_foreach(viewport_list, link, viewport_t, vp) {
 		sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
 		surface_get_damaged_region(vp->surface, &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
@@ -631,6 +623,5 @@
 
 	fibril_mutex_lock(&pointer_list_mtx);
-	list_foreach(pointer_list, link) {
-		pointer_t *pointer = list_get_instance(link, pointer_t, link);
+	list_foreach(pointer_list, link, pointer_t, pointer) {
 		if (pointer->id == pos_id) {
 			pointer->grab_flags = pointer->pressed ? grab_flags : GF_EMPTY;
@@ -710,15 +701,15 @@
 {
 	fibril_mutex_lock(&window_list_mtx);
-	window_t *window = NULL;
-	list_foreach(window_list, link) {
-		window = list_get_instance(link, window_t, link);
+
+	list_foreach(window_list, link, window_t, window) {
 		if (window == target) {
 			prodcons_produce(&window->queue, &event->link);
-		}
-	}
-	if (!window) {
-		free(event);
-	}
+			fibril_mutex_unlock(&window_list_mtx);
+			return;
+		}
+	}
+
 	fibril_mutex_unlock(&window_list_mtx);
+	free(event);
 }
 
@@ -863,6 +854,5 @@
 	window_t *win = NULL;
 	fibril_mutex_lock(&window_list_mtx);
-	list_foreach(window_list, link) {
-		window_t *cur = list_get_instance(link, window_t, link);
+	list_foreach(window_list, link, window_t, cur) {
 		if (cur->in_dsid == service_id || cur->out_dsid == service_id) {
 			win = cur;
@@ -1007,6 +997,5 @@
 		/* Close all clients and their windows. */
 		fibril_mutex_lock(&window_list_mtx);
-		list_foreach(window_list, link) {
-			window_t *win = list_get_instance(link, window_t, link);
+		list_foreach(window_list, link, window_t, win) {
 			window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
 			if (event) {
@@ -1034,6 +1023,5 @@
 	viewport_t *vp = NULL;
 	fibril_mutex_lock(&viewport_list_mtx);
-	list_foreach(viewport_list, link) {
-		viewport_t *cur = list_get_instance(link, viewport_t, link);
+	list_foreach(viewport_list, link, viewport_t, cur) {
 		if (cur->dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
 			vp = cur;
@@ -1571,6 +1559,6 @@
 
 	/* Determine the window which the mouse click belongs to. */
-	list_foreach(window_list, link) {
-		win = list_get_instance(link, window_t, link);
+	list_foreach(window_list, link, window_t, cw) {
+		win = cw;
 		if (win->surface) {
 			surface_get_resolution(win->surface, &width, &height);
Index: uspace/srv/hid/input/input.c
===================================================================
--- uspace/srv/hid/input/input.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/hid/input/input.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -470,8 +470,5 @@
 {
 	/* For each keyboard device */
-	list_foreach(kbd_devs, kdev_link) {
-		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
-		    kbd_devs);
-		
+	list_foreach(kbd_devs, kbd_devs, kbd_dev_t, kdev) {
 		/* Yield port */
 		if (kdev->port_ops != NULL)
@@ -483,8 +480,5 @@
 {
 	/* For each keyboard device */
-	list_foreach(kbd_devs, kdev_link) {
-		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
-		    kbd_devs);
-		
+	list_foreach(kbd_devs, kbd_devs, kbd_dev_t, kdev) {
 		/* Reclaim port */
 		if (kdev->port_ops != NULL)
@@ -521,7 +515,5 @@
 		
 		/* Determine whether we already know this device. */
-		list_foreach(kbd_devs, kdev_link) {
-			kbd_dev_t *kdev = list_get_instance(kdev_link,
-			    kbd_dev_t, kbd_devs);
+		list_foreach(kbd_devs, kbd_devs, kbd_dev_t, kdev) {
 			if (kdev->svc_id == svcs[i]) {
 				already_known = true;
@@ -574,7 +566,5 @@
 		
 		/* Determine whether we already know this device. */
-		list_foreach(mouse_devs, mdev_link) {
-			mouse_dev_t *mdev = list_get_instance(mdev_link,
-			    mouse_dev_t, mouse_devs);
+		list_foreach(mouse_devs, mouse_devs, mouse_dev_t, mdev) {
 			if (mdev->svc_id == svcs[i]) {
 				already_known = true;
Index: uspace/srv/hid/input/port/niagara.c
===================================================================
--- uspace/srv/hid/input/port/niagara.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/hid/input/port/niagara.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -97,6 +97,6 @@
 		return -1;
 	
-	int rc = physmem_map((void *) paddr, 1,
-	    AS_AREA_READ | AS_AREA_WRITE, (void *) &input_buffer);
+	int rc = physmem_map(paddr, 1, AS_AREA_READ | AS_AREA_WRITE,
+	    (void *) &input_buffer);
 	if (rc != 0) {
 		printf("Niagara: uspace driver couldn't map physical memory: %d\n",
Index: uspace/srv/hid/output/output.c
===================================================================
--- uspace/srv/hid/output/output.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/hid/output/output.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -82,7 +82,5 @@
 	int ret = EOK;
 	
-	list_foreach(outdevs, link) {
-		outdev_t *dev = list_get_instance(link, outdev_t, link);
-		
+	list_foreach(outdevs, link, outdev_t, dev) {
 		assert(dev->ops.yield);
 		
@@ -99,7 +97,5 @@
 	int ret = EOK;
 	
-	list_foreach(outdevs, link) {
-		outdev_t *dev = list_get_instance(link, outdev_t, link);
-		
+	list_foreach(outdevs, link, outdev_t, dev) {
 		assert(dev->ops.claim);
 		
@@ -117,7 +113,5 @@
 	sysarg_t rows = MAX_ROWS;
 	
-	list_foreach(outdevs, link) {
-		outdev_t *dev = list_get_instance(link, outdev_t, link);
-		
+	list_foreach(outdevs, link, outdev_t, dev) {
 		cols = min(cols, dev->cols);
 		rows = min(rows, dev->rows);
@@ -131,7 +125,5 @@
 	console_caps_t caps = 0;
 	
-	list_foreach(outdevs, link) {
-		outdev_t *dev = list_get_instance(link, outdev_t, link);
-		
+	list_foreach(outdevs, link, outdev_t, dev) {
 		assert(dev->ops.get_caps);
 		
@@ -145,6 +137,5 @@
 {
 	frontbuf_t *frontbuf = NULL;
-	list_foreach(frontbufs, link) {
-		frontbuf_t *cur = list_get_instance(link, frontbuf_t, link);
+	list_foreach(frontbufs, link, frontbuf_t, cur) {
 		if (cur == (frontbuf_t *) handle) {
 			frontbuf = cur;
@@ -216,7 +207,5 @@
 	chargrid_get_cursor(buf, &col, &row);
 	
-	list_foreach(outdevs, link) {
-		outdev_t *dev = list_get_instance(link, outdev_t, link);
-		
+	list_foreach(outdevs, link, outdev_t, dev) {
 		assert(dev->ops.cursor_update);
 		
@@ -237,7 +226,5 @@
 static void srv_set_style(ipc_callid_t iid, ipc_call_t *icall)
 {
-	list_foreach(outdevs, link) {
-		outdev_t *dev = list_get_instance(link, outdev_t, link);
-		
+	list_foreach(outdevs, link, outdev_t, dev) {
 		dev->attrs.type = CHAR_ATTR_STYLE;
 		dev->attrs.val.style =
@@ -250,7 +237,5 @@
 static void srv_set_color(ipc_callid_t iid, ipc_call_t *icall)
 {
-	list_foreach(outdevs, link) {
-		outdev_t *dev = list_get_instance(link, outdev_t, link);
-		
+	list_foreach(outdevs, link, outdev_t, dev) {
 		dev->attrs.type = CHAR_ATTR_INDEX;
 		dev->attrs.val.index.bgcolor =
@@ -267,7 +252,5 @@
 static void srv_set_rgb_color(ipc_callid_t iid, ipc_call_t *icall)
 {
-	list_foreach(outdevs, link) {
-		outdev_t *dev = list_get_instance(link, outdev_t, link);
-		
+	list_foreach(outdevs, link, outdev_t, dev) {
 		dev->attrs.type = CHAR_ATTR_RGB;
 		dev->attrs.val.rgb.bgcolor = IPC_GET_ARG1(*icall);
@@ -325,7 +308,5 @@
 	chargrid_t *buf = (chargrid_t *) frontbuf->data;
 	
-	list_foreach(outdevs, link) {
-		outdev_t *dev = list_get_instance(link, outdev_t, link);
-		
+	list_foreach(outdevs, link, outdev_t, dev) {
 		assert(dev->ops.char_update);
 		
@@ -374,7 +355,5 @@
 	chargrid_t *buf = (chargrid_t *) frontbuf->data;
 	
-	list_foreach(outdevs, link) {
-		outdev_t *dev = list_get_instance(link, outdev_t, link);
-		
+	list_foreach(outdevs, link, outdev_t, dev) {
 		assert(dev->ops.char_update);
 		
Index: uspace/srv/hid/output/port/ega.c
===================================================================
--- uspace/srv/hid/output/port/ega.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/hid/output/port/ega.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -216,5 +216,5 @@
 	ega.size = (ega.cols * ega.rows) << 1;
 	
-	rc = physmem_map((void *) paddr,
+	rc = physmem_map(paddr,
 	    ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH,
 	    AS_AREA_READ | AS_AREA_WRITE, (void *) &ega.addr);
Index: uspace/srv/hid/output/port/kchar.c
===================================================================
--- uspace/srv/hid/output/port/kchar.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/hid/output/port/kchar.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -84,5 +84,5 @@
 		return rc;
 	
-	rc = physmem_map((void *) paddr,
+	rc = physmem_map(paddr,
 	    ALIGN_UP(1, PAGE_SIZE) >> PAGE_WIDTH,
 	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kchar.addr);
Index: uspace/srv/hid/output/port/niagara.c
===================================================================
--- uspace/srv/hid/output/port/niagara.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/hid/output/port/niagara.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -104,6 +104,6 @@
 		return rc;
 	
-	rc = physmem_map((void *) paddr, 1,
-	    AS_AREA_READ | AS_AREA_WRITE, (void *) &niagara.fifo);
+	rc = physmem_map(paddr, 1, AS_AREA_READ | AS_AREA_WRITE,
+	    (void *) &niagara.fifo);
 	if (rc != EOK)
 		return rc;
Index: uspace/srv/hid/remcons/user.c
===================================================================
--- uspace/srv/hid/remcons/user.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/hid/remcons/user.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -128,6 +128,5 @@
 
 	fibril_mutex_lock(&users_guard);
-	list_foreach(users, link) {
-		telnet_user_t *tmp = list_get_instance(link, telnet_user_t, link);
+	list_foreach(users, link, telnet_user_t, tmp) {
 		if (tmp->service_id == id) {
 			user = tmp;
Index: uspace/srv/hw/irc/obio/obio.c
===================================================================
--- uspace/srv/hw/irc/obio/obio.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/hw/irc/obio/obio.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -69,5 +69,5 @@
 #define INO_MASK	0x1f
 
-static void *base_phys;
+static uintptr_t base_phys;
 static volatile uint64_t *base_virt;
 
@@ -123,5 +123,5 @@
 	}
 	
-	base_phys = (void *) paddr;
+	base_phys = (uintptr_t) paddr;
 	
 	int flags = AS_AREA_READ | AS_AREA_WRITE;
@@ -135,5 +135,5 @@
 	}
 	
-	printf("%s: OBIO registers with base at %p\n", NAME, base_phys);
+	printf("%s: OBIO registers with base at %zu\n", NAME, base_phys);
 	
 	async_set_client_connection(obio_connection);
Index: uspace/srv/locsrv/category.c
===================================================================
--- uspace/srv/locsrv/category.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/locsrv/category.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -73,8 +73,5 @@
 
 	size_t pos = 0;
-	list_foreach(cdir->categories, item) {
-		category_t *cat =
-		    list_get_instance(item, category_t, cat_list);
-
+	list_foreach(cdir->categories, cat_list, category_t, cat) {
 		if (pos < buf_cnt)
 			id_buf[pos] = cat->id;
@@ -116,7 +113,5 @@
 
 	/* Verify that category does not contain this service yet. */
-	list_foreach(cat->svc_memb, item) {
-		svc_categ_t *memb = list_get_instance(item, svc_categ_t,
-		    cat_link);
+	list_foreach(cat->svc_memb, cat_link, svc_categ_t, memb) {
 		if (memb->svc == svc) {
 			return EEXIST;
@@ -154,7 +149,5 @@
 	assert(fibril_mutex_is_locked(&cdir->mutex));
 
-	list_foreach(cdir->categories, item) {
-		category_t *cat = list_get_instance(item, category_t,
-		    cat_list);
+	list_foreach(cdir->categories, cat_list, category_t, cat) {
 		if (cat->id == catid)
 			return cat;
@@ -169,7 +162,5 @@
 	assert(fibril_mutex_is_locked(&cdir->mutex));
 
-	list_foreach(cdir->categories, item) {
-		category_t *cat = list_get_instance(item, category_t,
-		    cat_list);
+	list_foreach(cdir->categories, cat_list, category_t, cat) {
 		if (str_cmp(cat->name, name) == 0)
 			return cat;
@@ -197,8 +188,5 @@
 
 	size_t pos = 0;
-	list_foreach(cat->svc_memb, item) {
-		svc_categ_t *memb =
-		    list_get_instance(item, svc_categ_t, cat_link);
-
+	list_foreach(cat->svc_memb, cat_link, svc_categ_t, memb) {
 		if (pos < buf_cnt)
 			id_buf[pos] = memb->svc->id;
Index: uspace/srv/locsrv/locsrv.c
===================================================================
--- uspace/srv/locsrv/locsrv.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/locsrv/locsrv.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -184,7 +184,5 @@
 	assert(fibril_mutex_is_locked(&services_list_mutex));
 	
-	list_foreach(namespaces_list, item) {
-		loc_namespace_t *namespace =
-		    list_get_instance(item, loc_namespace_t, namespaces);
+	list_foreach(namespaces_list, namespaces, loc_namespace_t, namespace) {
 		if (str_cmp(namespace->name, name) == 0)
 			return namespace;
@@ -203,7 +201,5 @@
 	assert(fibril_mutex_is_locked(&services_list_mutex));
 	
-	list_foreach(namespaces_list, item) {
-		loc_namespace_t *namespace =
-		    list_get_instance(item, loc_namespace_t, namespaces);
+	list_foreach(namespaces_list, namespaces, loc_namespace_t, namespace) {
 		if (namespace->id == id)
 			return namespace;
@@ -219,7 +215,5 @@
 	assert(fibril_mutex_is_locked(&services_list_mutex));
 	
-	list_foreach(services_list, item) {
-		loc_service_t *service =
-		    list_get_instance(item, loc_service_t, services);
+	list_foreach(services_list, services, loc_service_t, service) {
 		if ((str_cmp(service->namespace->name, ns_name) == 0)
 		    && (str_cmp(service->name, name) == 0))
@@ -239,7 +233,5 @@
 	assert(fibril_mutex_is_locked(&services_list_mutex));
 	
-	list_foreach(services_list, item) {
-		loc_service_t *service =
-		    list_get_instance(item, loc_service_t, services);
+	list_foreach(services_list, services, loc_service_t, service) {
 		if (service->id == id)
 			return service;
@@ -889,9 +881,5 @@
 	fibril_mutex_lock(&callback_sess_mutex);
 	
-	list_foreach(callback_sess_list, link) {
-		cb_sess_t *cb_sess;
-		
-		cb_sess = list_get_instance(link, cb_sess_t, cb_sess_list);
-		
+	list_foreach(callback_sess_list, cb_sess_list, cb_sess_t, cb_sess) {
 		async_exch_t *exch = async_exchange_begin(cb_sess->sess);
 		async_msg_0(exch, LOC_EVENT_CAT_CHANGE);
@@ -1050,8 +1038,5 @@
 	
 	size_t pos = 0;
-	list_foreach(namespaces_list, item) {
-		loc_namespace_t *namespace =
-		    list_get_instance(item, loc_namespace_t, namespaces);
-		
+	list_foreach(namespaces_list, namespaces, loc_namespace_t, namespace) {
 		desc[pos].id = namespace->id;
 		str_cpy(desc[pos].name, LOC_NAME_MAXLEN, namespace->name);
@@ -1114,8 +1099,5 @@
 	
 	size_t pos = 0;
-	list_foreach(services_list, item) {
-		loc_service_t *service =
-		    list_get_instance(item, loc_service_t, services);
-		
+	list_foreach(services_list, services, loc_service_t, service) {
 		if (service->namespace == namespace) {
 			desc[pos].id = service->id;
Index: uspace/srv/logger/logs.c
===================================================================
--- uspace/srv/logger/logs.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/logger/logs.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -44,6 +44,5 @@
 static logger_log_t *find_log_by_name_and_parent_no_list_lock(const char *name, logger_log_t *parent)
 {
-	list_foreach(log_list, it) {
-		logger_log_t *log = list_get_instance(it, logger_log_t, link);
+	list_foreach(log_list, link, logger_log_t, log) {
 		if ((parent == log->parent) && (str_cmp(log->name, name) == 0))
 			return log;
@@ -148,6 +147,5 @@
 
 	fibril_mutex_lock(&log_list_guard);
-	list_foreach(log_list, it) {
-		logger_log_t *log = list_get_instance(it, logger_log_t, link);
+	list_foreach(log_list, link, logger_log_t, log) {
 		if (str_cmp(log->full_name, name) == 0) {
 			fibril_mutex_lock(&log->guard);
@@ -166,6 +164,5 @@
 
 	fibril_mutex_lock(&log_list_guard);
-	list_foreach(log_list, it) {
-		logger_log_t *log = list_get_instance(it, logger_log_t, link);
+	list_foreach(log_list, link, logger_log_t, log) {
 		if ((sysarg_t) log == id) {
 			fibril_mutex_lock(&log->guard);
Index: uspace/srv/net/dnsrsrv/dns_msg.c
===================================================================
--- uspace/srv/net/dnsrsrv/dns_msg.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/dnsrsrv/dns_msg.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -510,6 +510,5 @@
 	size = sizeof(dns_header_t);
 
-	list_foreach(msg->question, link) {
-		dns_question_t *q = list_get_instance(link, dns_question_t, msg);
+	list_foreach(msg->question, msg, dns_question_t, q) {
 		rc = dns_question_encode(q, NULL, 0, &q_size);
 		if (rc != EOK)
@@ -526,6 +525,5 @@
 	di = sizeof(dns_header_t);
 
-	list_foreach(msg->question, link) {
-		dns_question_t *q = list_get_instance(link, dns_question_t, msg);
+	list_foreach(msg->question, msg, dns_question_t, q) {
 		rc = dns_question_encode(q, data + di, size - di, &q_size);
 		if (rc != EOK) {
Index: uspace/srv/net/dnsrsrv/query.c
===================================================================
--- uspace/srv/net/dnsrsrv/query.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/dnsrsrv/query.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -99,7 +99,5 @@
 	}
 	
-	list_foreach(amsg->answer, link) {
-		dns_rr_t *rr = list_get_instance(link, dns_rr_t, msg);
-		
+	list_foreach(amsg->answer, msg, dns_rr_t, rr) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, " - '%s' %u/%u, dsize %zu",
 		    rr->name, rr->rtype, rr->rclass, rr->rdata_size);
Index: uspace/srv/net/dnsrsrv/transport.c
===================================================================
--- uspace/srv/net/dnsrsrv/transport.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/dnsrsrv/transport.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -158,7 +158,5 @@
 	assert(fibril_mutex_is_locked(&treq_lock));
 
-	list_foreach(treq_list, link) {
-		trans_req_t *treq = list_get_instance(link, trans_req_t, lreq);
-
+	list_foreach(treq_list, lreq, trans_req_t, treq) {
 		if (treq->req->id == resp->id) {
 			/* Match */
Index: uspace/srv/net/ethip/atrans.c
===================================================================
--- uspace/srv/net/ethip/atrans.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/ethip/atrans.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -51,8 +51,5 @@
 static ethip_atrans_t *atrans_find(addr32_t ip_addr)
 {
-	list_foreach(atrans_list, link) {
-		ethip_atrans_t *atrans = list_get_instance(link,
-		    ethip_atrans_t, atrans_list);
-
+	list_foreach(atrans_list, atrans_list, ethip_atrans_t, atrans) {
 		if (atrans->ip_addr == ip_addr)
 			return atrans;
Index: uspace/srv/net/ethip/ethip_nic.c
===================================================================
--- uspace/srv/net/ethip/ethip_nic.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/ethip/ethip_nic.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -84,7 +84,5 @@
 		already_known = false;
 
-		list_foreach(ethip_nic_list, link) {
-			ethip_nic_t *nic = list_get_instance(link,
-			    ethip_nic_t, link);
+		list_foreach(ethip_nic_list, link, ethip_nic_t, nic) {
 			if (nic->svc_id == svcs[i]) {
 				already_known = true;
@@ -313,8 +311,6 @@
 	    (unsigned) iplink_sid);
 
-	list_foreach(ethip_nic_list, link) {
+	list_foreach(ethip_nic_list, link, ethip_nic_t, nic) {
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_find_by_iplink_sid - element");
-		ethip_nic_t *nic = list_get_instance(link, ethip_nic_t, link);
-
 		if (nic->iplink_sid == iplink_sid) {
 			log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_find_by_iplink_sid - found %p", nic);
@@ -350,8 +346,5 @@
 	size_t count = 0;
 	
-	list_foreach(nic->addr_list, link) {
-		ethip_link_addr_t *laddr = list_get_instance(link,
-		    ethip_link_addr_t, link);
-		
+	list_foreach(nic->addr_list, link, ethip_link_addr_t, laddr) {
 		uint16_t af = inet_addr_get(&laddr->addr, NULL, NULL);
 		if (af == AF_INET6)
@@ -371,14 +364,11 @@
 	size_t i = 0;
 	
-	list_foreach(nic->addr_list, link) {
-		assert(i < count);
-		
-		ethip_link_addr_t *laddr = list_get_instance(link,
-		    ethip_link_addr_t, link);
-		
+	list_foreach(nic->addr_list, link, ethip_link_addr_t, laddr) {
 		addr128_t v6;
 		uint16_t af = inet_addr_get(&laddr->addr, NULL, &v6);
 		if (af != AF_INET6)
 			continue;
+		
+		assert(i < count);
 		
 		addr48_t mac;
@@ -444,8 +434,5 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_addr_find()");
 	
-	list_foreach(nic->addr_list, link) {
-		ethip_link_addr_t *laddr = list_get_instance(link,
-		    ethip_link_addr_t, link);
-		
+	list_foreach(nic->addr_list, link, ethip_link_addr_t, laddr) {
 		if (inet_addr_compare(addr, &laddr->addr))
 			return laddr;
Index: uspace/srv/net/inetsrv/addrobj.c
===================================================================
--- uspace/srv/net/inetsrv/addrobj.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/inetsrv/addrobj.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -115,8 +115,5 @@
 	fibril_mutex_lock(&addr_list_lock);
 	
-	list_foreach(addr_list, link) {
-		inet_addrobj_t *naddr = list_get_instance(link,
-		    inet_addrobj_t, addr_list);
-		
+	list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
 		switch (find) {
 		case iaf_net:
@@ -158,8 +155,5 @@
 	    name, ilink->svc_name);
 
-	list_foreach(addr_list, link) {
-		inet_addrobj_t *naddr = list_get_instance(link,
-		    inet_addrobj_t, addr_list);
-
+	list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
 		if (naddr->ilink == ilink && str_cmp(naddr->name, name) == 0) {
 			log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name_locked: found %p",
@@ -206,8 +200,5 @@
 	fibril_mutex_lock(&addr_list_lock);
 
-	list_foreach(addr_list, link) {
-		inet_addrobj_t *naddr = list_get_instance(link,
-		    inet_addrobj_t, addr_list);
-
+	list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
 		if (naddr->id == id) {
 			fibril_mutex_unlock(&addr_list_lock);
@@ -277,8 +268,5 @@
 
 	i = 0;
-	list_foreach(addr_list, link) {
-		inet_addrobj_t *addr = list_get_instance(link,
-		    inet_addrobj_t, addr_list);
-
+	list_foreach(addr_list, addr_list, inet_addrobj_t, addr) {
 		id_list[i++] = addr->id;
 	}
Index: uspace/srv/net/inetsrv/inet_link.c
===================================================================
--- uspace/srv/net/inetsrv/inet_link.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/inetsrv/inet_link.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -140,7 +140,5 @@
 		already_known = false;
 
-		list_foreach(inet_link_list, ilink_link) {
-			inet_link_t *ilink = list_get_instance(ilink_link,
-			    inet_link_t, link_list);
+		list_foreach(inet_link_list, link_list, inet_link_t, ilink) {
 			if (ilink->svc_id == svcs[i]) {
 				already_known = true;
@@ -492,8 +490,5 @@
 	fibril_mutex_lock(&inet_discovery_lock);
 
-	list_foreach(inet_link_list, elem) {
-		inet_link_t *ilink = list_get_instance(elem, inet_link_t,
-		    link_list);
-
+	list_foreach(inet_link_list, link_list, inet_link_t, ilink) {
 		if (ilink->svc_id == link_id) {
 			fibril_mutex_unlock(&inet_discovery_lock);
Index: uspace/srv/net/inetsrv/inetping.c
===================================================================
--- uspace/srv/net/inetsrv/inetping.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/inetsrv/inetping.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -82,8 +82,5 @@
 	fibril_mutex_lock(&client_list_lock);
 	
-	list_foreach(client_list, link) {
-		inetping_client_t *client = list_get_instance(link,
-		    inetping_client_t, client_list);
-		
+	list_foreach(client_list, client_list, inetping_client_t, client) {
 		if (client->ident == ident) {
 			fibril_mutex_unlock(&client_list_lock);
Index: uspace/srv/net/inetsrv/inetping6.c
===================================================================
--- uspace/srv/net/inetsrv/inetping6.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/inetsrv/inetping6.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -82,8 +82,5 @@
 	fibril_mutex_lock(&client_list_lock);
 	
-	list_foreach(client_list, link) {
-		inetping6_client_t *client = list_get_instance(link,
-		    inetping6_client_t, client_list);
-		
+	list_foreach(client_list, client_list, inetping6_client_t, client) {
 		if (client->ident == ident) {
 			fibril_mutex_unlock(&client_list_lock);
Index: uspace/srv/net/inetsrv/inetsrv.c
===================================================================
--- uspace/srv/net/inetsrv/inetsrv.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/inetsrv/inetsrv.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -446,8 +446,5 @@
 	fibril_mutex_lock(&client_list_lock);
 
-	list_foreach(client_list, link) {
-		inet_client_t *client = list_get_instance(link, inet_client_t,
-		    client_list);
-
+	list_foreach(client_list, client_list, inet_client_t, client) {
 		if (client->protocol == proto) {
 			fibril_mutex_unlock(&client_list_lock);
Index: uspace/srv/net/inetsrv/ntrans.c
===================================================================
--- uspace/srv/net/inetsrv/ntrans.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/inetsrv/ntrans.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -56,8 +56,5 @@
 static inet_ntrans_t *ntrans_find(addr128_t ip_addr)
 {
-	list_foreach(ntrans_list, link) {
-		inet_ntrans_t *ntrans = list_get_instance(link,
-		    inet_ntrans_t, ntrans_list);
-
+	list_foreach(ntrans_list, ntrans_list, inet_ntrans_t, ntrans) {
 		if (addr128_compare(ntrans->ip_addr, ip_addr))
 			return ntrans;
Index: uspace/srv/net/inetsrv/reass.c
===================================================================
--- uspace/srv/net/inetsrv/reass.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/inetsrv/reass.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -129,8 +129,5 @@
 	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
 
-	list_foreach(reass_dgram_map, link) {
-		reass_dgram_t *rdg = list_get_instance(link, reass_dgram_t,
-		    map_link);
-
+	list_foreach(reass_dgram_map, map_link, reass_dgram_t, rdg) {
 		link_t *f1_link = list_first(&rdg->frags);
 		assert(f1_link != NULL);
@@ -289,6 +286,6 @@
 	size_t fragoff_limit;
 	inet_dgram_t dgram;
+	uint8_t proto;
 	reass_frag_t *frag;
-	uint8_t proto;
 
 	/*
@@ -297,9 +294,9 @@
 	 */
 	frag = NULL;
-	list_foreach(rdg->frags, link) {
-		frag = list_get_instance(link, reass_frag_t, dgram_link);
-
-		if (!frag->packet.mf)
+	list_foreach(rdg->frags, dgram_link, reass_frag_t, cfrag) {
+		if (!cfrag->packet.mf) {
+			frag = cfrag;
 			break;
+		}
 	}
 
@@ -330,20 +327,17 @@
 	size_t doffs = 0;
 
-	frag = NULL;
-	list_foreach(rdg->frags, link) {
-		frag = list_get_instance(link, reass_frag_t, dgram_link);
-
+	list_foreach(rdg->frags, dgram_link, reass_frag_t, cfrag) {
 		size_t cb, ce;
 
-		cb = max(doffs, frag->packet.offs);
-		ce = min(dgram_size, frag->packet.offs + frag->packet.size);
+		cb = max(doffs, cfrag->packet.offs);
+		ce = min(dgram_size, cfrag->packet.offs + cfrag->packet.size);
 
 		if (ce > cb) {
 			memcpy(dgram.data + cb,
-			    frag->packet.data + cb - frag->packet.offs,
+			    cfrag->packet.data + cb - cfrag->packet.offs,
 			    ce - cb);
 		}
 
-		if (!frag->packet.mf)
+		if (!cfrag->packet.mf)
 			break;
 	}
Index: uspace/srv/net/inetsrv/sroute.c
===================================================================
--- uspace/srv/net/inetsrv/sroute.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/inetsrv/sroute.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -89,5 +89,5 @@
 }
 
-/** Find address object matching address @a addr.
+/** Find static route object matching address @a addr.
  *
  * @param addr	Address
@@ -102,8 +102,5 @@
 	fibril_mutex_lock(&sroute_list_lock);
 	
-	list_foreach(sroute_list, link) {
-		inet_sroute_t *sroute = list_get_instance(link,
-		    inet_sroute_t, sroute_list);
-		
+	list_foreach(sroute_list, sroute_list, inet_sroute_t, sroute) {
 		uint8_t dest_bits;
 		uint16_t dest_af = inet_naddr_get(&sroute->dest, NULL, NULL,
@@ -147,8 +144,5 @@
 	fibril_mutex_lock(&sroute_list_lock);
 
-	list_foreach(sroute_list, link) {
-		inet_sroute_t *sroute = list_get_instance(link,
-		    inet_sroute_t, sroute_list);
-
+	list_foreach(sroute_list, sroute_list, inet_sroute_t, sroute) {
 		if (str_cmp(sroute->name, name) == 0) {
 			fibril_mutex_unlock(&sroute_list_lock);
@@ -176,8 +170,5 @@
 	fibril_mutex_lock(&sroute_list_lock);
 
-	list_foreach(sroute_list, link) {
-		inet_sroute_t *sroute = list_get_instance(link,
-		    inet_sroute_t, sroute_list);
-
+	list_foreach(sroute_list, sroute_list, inet_sroute_t, sroute) {
 		if (sroute->id == id) {
 			fibril_mutex_unlock(&sroute_list_lock);
@@ -207,8 +198,5 @@
 
 	i = 0;
-	list_foreach(sroute_list, link) {
-		inet_sroute_t *sroute = list_get_instance(link,
-		    inet_sroute_t, sroute_list);
-
+	list_foreach(sroute_list, sroute_list, inet_sroute_t, sroute) {
 		id_list[i++] = sroute->id;
 	}
Index: uspace/srv/net/tcp/conn.c
===================================================================
--- uspace/srv/net/tcp/conn.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/tcp/conn.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -360,6 +360,5 @@
 	fibril_mutex_lock(&conn_list_lock);
 	
-	list_foreach(conn_list, link) {
-		tcp_conn_t *conn = list_get_instance(link, tcp_conn_t, link);
+	list_foreach(conn_list, link, tcp_conn_t, conn) {
 		tcp_sockpair_t *csp = &conn->ident;
 		
Index: uspace/srv/net/udp/assoc.c
===================================================================
--- uspace/srv/net/udp/assoc.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/net/udp/assoc.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -419,6 +419,5 @@
 	fibril_mutex_lock(&assoc_list_lock);
 	
-	list_foreach(assoc_list, link) {
-		udp_assoc_t *assoc = list_get_instance(link, udp_assoc_t, link);
+	list_foreach(assoc_list, link, udp_assoc_t, assoc) {
 		udp_sockpair_t *asp = &assoc->ident;
 		
Index: uspace/srv/ns/service.c
===================================================================
--- uspace/srv/ns/service.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/ns/service.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -106,7 +106,5 @@
 {
 loop:
-	list_foreach(pending_conn, cur) {
-		pending_conn_t *pr = list_get_instance(cur, pending_conn_t, link);
-		
+	list_foreach(pending_conn, link, pending_conn_t, pr) {
 		ht_link_t *link = hash_table_find(&service_hash_table, &pr->service);
 		if (!link)
@@ -117,5 +115,5 @@
 		    pr->arg3, 0, IPC_FF_NONE);
 		
-		list_remove(cur);
+		list_remove(&pr->link);
 		free(pr);
 		goto loop;
Index: uspace/srv/ns/task.c
===================================================================
--- uspace/srv/ns/task.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/ns/task.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -179,7 +179,5 @@
 	
 loop:
-	list_foreach(pending_wait, cur) {
-		pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link);
-		
+	list_foreach(pending_wait, link, pending_wait_t, pr) {
 		ht_link_t *link = hash_table_find(&task_hash_table, &pr->id);
 		if (!link)
@@ -198,5 +196,5 @@
 		
 		hash_table_remove(&task_hash_table, &pr->id);
-		list_remove(cur);
+		list_remove(&pr->link);
 		free(pr);
 		goto loop;
Index: uspace/srv/taskmon/taskmon.c
===================================================================
--- uspace/srv/taskmon/taskmon.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/taskmon/taskmon.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2013 Jiri Svoboda
  * All rights reserved.
  *
@@ -41,4 +41,6 @@
 #include <task.h>
 #include <event.h>
+#include <ipc/corecfg.h>
+#include <loc.h>
 #include <macros.h>
 #include <errno.h>
@@ -47,8 +49,13 @@
 #define NAME  "taskmon"
 
+static bool write_core_files;
+
+static void corecfg_client_conn(ipc_callid_t , ipc_call_t *, void *);
+
 static void fault_event(ipc_callid_t callid, ipc_call_t *call)
 {
 	const char *fname;
 	char *s_taskid;
+	char *dump_fname;
 	int rc;
 
@@ -69,22 +76,59 @@
 	fname = "/app/taskdump";
 
-#ifdef CONFIG_WRITE_CORE_FILES
-	char *dump_fname;
+	if (write_core_files) {
+		if (asprintf(&dump_fname, "/data/core%" PRIu64, taskid) < 0) {
+			printf("Memory allocation failed.\n");
+			return;
+		}
 
-	if (asprintf(&dump_fname, "/data/core%" PRIu64, taskid) < 0) {
-		printf("Memory allocation failed.\n");
-		return;
+		printf(NAME ": Executing %s -c %s -t %s\n", fname, dump_fname, s_taskid);
+		rc = task_spawnl(NULL, fname, fname, "-c", dump_fname, "-t", s_taskid,
+		    NULL);
+	} else {
+		printf(NAME ": Executing %s -t %s\n", fname, s_taskid);
+		rc = task_spawnl(NULL, fname, fname, "-t", s_taskid, NULL);
 	}
 
-	printf(NAME ": Executing %s -c %s -t %s\n", fname, dump_fname, s_taskid);
-	rc = task_spawnl(NULL, fname, fname, "-c", dump_fname, "-t", s_taskid,
-	    NULL);
-#else
-	printf(NAME ": Executing %s -t %s\n", fname, s_taskid);
-	rc = task_spawnl(NULL, fname, fname, "-t", s_taskid, NULL);
-#endif
 	if (rc != EOK) {
 		printf("%s: Error spawning %s (%s).\n", NAME, fname,
 		    str_error(rc));
+	}
+}
+
+static void corecfg_get_enable_srv(ipc_callid_t iid, ipc_call_t *icall)
+{
+	async_answer_1(iid, EOK, write_core_files);
+}
+
+static void corecfg_set_enable_srv(ipc_callid_t iid, ipc_call_t *icall)
+{
+	write_core_files = IPC_GET_ARG1(*icall);
+	async_answer_0(iid, EOK);
+}
+
+static void corecfg_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			return;
+		}
+
+		switch (method) {
+		case CORECFG_GET_ENABLE:
+			corecfg_get_enable_srv(callid, &call);
+			break;
+		case CORECFG_SET_ENABLE:
+			corecfg_set_enable_srv(callid, &call);
+			break;
+		}
 	}
 }
@@ -94,6 +138,28 @@
 	printf("%s: Task Monitoring Service\n", NAME);
 	
+#ifdef CONFIG_WRITE_CORE_FILES
+	write_core_files = true;
+#else
+	write_core_files = false;
+#endif
 	if (event_subscribe(EVENT_FAULT, 0) != EOK) {
 		printf("%s: Error registering fault notifications.\n", NAME);
+		return -1;
+	}
+	
+	async_set_client_connection(corecfg_client_conn);
+	
+	int rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		printf("%s: Failed registering server (%d).\n",
+		    NAME, rc);
+		return -1;
+	}
+	
+	service_id_t sid;
+	rc = loc_service_register(SERVICE_NAME_CORECFG, &sid);
+	if (rc != EOK) {
+		printf("%s: Failed registering service (%d).\n",
+		    NAME, rc);
 		return -1;
 	}
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/vfs/vfs_ops.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -548,8 +548,5 @@
 	int found = 0;
 
-	list_foreach(mtab_list, cur) {
-		mtab_ent_t *mtab_ent = list_get_instance(cur, mtab_ent_t,
-		    link);
-
+	list_foreach(mtab_list, link, mtab_ent_t, mtab_ent) {
 		if (str_cmp(mtab_ent->mp, mp) == 0) {
 			list_remove(&mtab_ent->link);
@@ -1371,8 +1368,5 @@
 	async_answer_1(callid, EOK, mtab_size);
 
-	list_foreach(mtab_list, cur) {
-		mtab_ent_t *mtab_ent = list_get_instance(cur, mtab_ent_t,
-		    link);
-
+	list_foreach(mtab_list, link, mtab_ent_t, mtab_ent) {
 		rc = ENOTSUP;
 
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 9dbdda91731f77f12ce8c42162b0f95a9b75d72a)
+++ uspace/srv/vfs/vfs_register.c	(revision 758f8d55da31118ef5accb99051c4f46cc5c880a)
@@ -260,7 +260,5 @@
 	fibril_mutex_lock(&fs_list_lock);
 	
-	list_foreach(fs_list, cur) {
-		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
-		
+	list_foreach(fs_list, fs_link, fs_info_t, fs) {
 		if (fs->fs_handle == handle) {
 			fibril_mutex_unlock(&fs_list_lock);
@@ -305,6 +303,5 @@
 		fibril_mutex_lock(&fs_list_lock);
 	
-	list_foreach(fs_list, cur) {
-		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
+	list_foreach(fs_list, fs_link, fs_info_t, fs) {
 		if (str_cmp(fs->vfs_info.name, name) == 0 &&
 		    instance == fs->vfs_info.instance) {
@@ -332,6 +329,5 @@
 	
 	fibril_mutex_lock(&fs_list_lock);
-	list_foreach(fs_list, cur) {
-		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
+	list_foreach(fs_list, fs_link, fs_info_t, fs) {
 		if (fs->fs_handle == handle) { 
 			info = &fs->vfs_info;
