Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ HelenOS.config	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -70,4 +70,5 @@
 @ "pentium4" Pentium 4
 @ "pentium3" Pentium 3
+@ "i486" i486
 @ "core" Core Solo/Duo
 @ "athlon_xp" Athlon XP
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ boot/Makefile.common	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -143,4 +143,5 @@
 	$(USPACE_PATH)/app/blkdump/blkdump \
 	$(USPACE_PATH)/app/bnchmark/bnchmark \
+	$(USPACE_PATH)/app/devctl/devctl \
 	$(USPACE_PATH)/app/dltest/dltest \
 	$(USPACE_PATH)/app/dltest2/dltest2 \
Index: kernel/arch/ia32/Makefile.inc
===================================================================
--- kernel/arch/ia32/Makefile.inc	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ kernel/arch/ia32/Makefile.inc	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -64,4 +64,8 @@
 endif
 
+ifeq ($(PROCESSOR),i486)
+	CMN2 = -march=i486
+endif
+
 ifeq ($(PROCESSOR),core)
 	CMN2 = -march=prescott
Index: kernel/arch/ia32/include/asm.h
===================================================================
--- kernel/arch/ia32/include/asm.h	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ kernel/arch/ia32/include/asm.h	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -311,4 +311,5 @@
 }
 
+#ifndef PROCESSOR_i486
 /** Write to MSR */
 NO_TRACE static inline void write_msr(uint32_t msr, uint64_t value)
@@ -335,4 +336,5 @@
 	return ((uint64_t) dx << 32) | ax;
 }
+#endif
 
 
Index: kernel/arch/ia32/include/atomic.h
===================================================================
--- kernel/arch/ia32/include/atomic.h	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ kernel/arch/ia32/include/atomic.h	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -121,5 +121,7 @@
 	asm volatile (
 		"0:\n"
+#ifndef PROCESSOR_i486
 		"pause\n"        /* Pentium 4's HT love this instruction */
+#endif
 		"mov %[count], %[tmp]\n"
 		"testl %[tmp], %[tmp]\n"
Index: kernel/arch/ia32/include/cycle.h
===================================================================
--- kernel/arch/ia32/include/cycle.h	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ kernel/arch/ia32/include/cycle.h	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -40,4 +40,7 @@
 NO_TRACE static inline uint64_t get_cycle(void)
 {
+#ifdef PROCESSOR_i486
+	return 0;
+#else
 	uint64_t v;
 	
@@ -48,4 +51,5 @@
 	
 	return v;
+#endif
 }
 
Index: kernel/arch/ia32/src/asm.S
===================================================================
--- kernel/arch/ia32/src/asm.S	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ kernel/arch/ia32/src/asm.S	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -405,5 +405,11 @@
 	xorl %eax, %eax
 	cmpl $(GDT_SELECTOR(KTEXT_DES)), ISTATE_OFFSET_CS(%esp)
+#ifdef PROCESSOR_i486
+	jz 0f
+	movl %eax, %ebp
+0:
+#else
 	cmovnzl %eax, %ebp
+#endif
 
 	movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp)
Index: kernel/arch/ia32/src/boot/boot.S
===================================================================
--- kernel/arch/ia32/src/boot/boot.S	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ kernel/arch/ia32/src/boot/boot.S	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -97,20 +97,4 @@
 	pm_status $status_prot
 	
-	movl $(INTEL_CPUID_LEVEL), %eax
-	cpuid
-	cmp $0x0, %eax  /* any function > 0? */
-	jbe pse_unsupported
-	
-	movl $(INTEL_CPUID_STANDARD), %eax
-	cpuid
-	bt $(INTEL_PSE), %edx
-	jc pse_supported
-	
-	pse_unsupported:
-		
-		pm_error $err_pse
-	
-	pse_supported:
-	
 #include "vesa_prot.inc"
 	
@@ -140,4 +124,71 @@
 		jmp hlt0
 
+/** Calculate unmapped address of the end of the kernel. */
+calc_end_of_kernel:
+	movl $hardcoded_load_address, %edi
+	andl $0x7fffffff, %edi
+	movl (%edi), %esi
+	andl $0x7fffffff, %esi
+	
+	movl $hardcoded_ktext_size, %edi
+	andl $0x7fffffff, %edi
+	addl (%edi), %esi
+	andl $0x7fffffff, %esi
+	
+	movl $hardcoded_kdata_size, %edi
+	andl $0x7fffffff, %edi
+	addl (%edi), %esi
+	andl $0x7fffffff, %esi
+	movl %esi, end_of_kernel
+	ret
+
+/** Find free 2M (+4k for alignment) region where to store page tables */
+find_mem_for_pt:
+	/* Check if multiboot info is present */
+	cmpl $0x2BADB002, grub_eax
+	je check_multiboot_map
+	ret
+check_multiboot_map:
+	/* Copy address of the multiboot info to ebx */
+	movl grub_ebx, %ebx
+	/* Check if memory map flag is present */
+	movl (%ebx), %edx
+	andl $(1 << 6), %edx
+	jnz use_multiboot_map
+	ret
+use_multiboot_map:
+	/* Copy address of the memory map to edx */
+	movl 48(%ebx), %edx
+	movl %edx, %ecx
+	addl 44(%ebx), %ecx
+	/* Find a free region at least 2M in size */
+	check_memmap_loop:
+		/* Is this a free region? */
+		cmp $1, 20(%edx)
+		jnz next_region
+		/* Check size */
+		cmp $0, 16(%edx)
+		jnz next_region
+		cmpl $(2 * 1024 * 1024 + 4 * 1024), 12(%edx)
+		jbe next_region
+		cmp $0, 8(%edx)
+		jz found_region
+	next_region:
+		cmp %ecx, %edx
+		jbe next_region_do
+		ret
+	next_region_do:
+		addl (%edx), %edx
+		addl $4, %edx
+		jmp check_memmap_loop
+	found_region:
+		/* Use end of the found region */
+		mov 4(%edx), %ecx
+		add 12(%edx), %ecx
+		sub $(2 * 1024 * 1024), %ecx
+		mov %ecx, free_area
+	ret
+		
+
 /** Setup mapping for the kernel.
  *
@@ -148,16 +199,54 @@
 .global map_kernel
 map_kernel:
+	/* Paging features */
 	movl %cr4, %ecx
-	orl $(1 << 4), %ecx      /* PSE on */
 	andl $(~(1 << 5)), %ecx  /* PAE off */
 	movl %ecx, %cr4
 	
+	call calc_end_of_kernel
+	call find_mem_for_pt
+	mov end_of_kernel, %esi
+	mov free_area, %ecx
+	cmpl %esi, %ecx
+	jbe use_end_of_kernel
+	mov %ecx, %esi
+	/* Align address down to 4k */
+	andl $(~4095), %esi
+use_end_of_kernel:
+	
+	/* Align address to 4k */
+	addl $4095, %esi
+	andl $(~4095), %esi
+	
+	/* Allocate space for page tables*/	
+	movl %esi, pt_loc
+	movl $ballocs, %edi
+	andl $0x7fffffff, %edi
+	movl %esi, (%edi)
+	addl $4, %edi
+	movl $(2*1024*1024), (%edi)
+	
+	/* Fill page tables */
+	xorl %ecx, %ecx
+	xorl %ebx, %ebx
+	
+	floop_pt:
+		movl $((1 << 1) | (1 << 0)), %eax
+		orl %ebx, %eax
+		movl %eax, (%esi, %ecx, 4)
+		addl $(4 * 1024), %ebx
+		
+		incl %ecx
+		cmpl $(512 * 1024), %ecx
+		jl floop_pt
+	
+	/* Fill page directory */
 	movl $(page_directory + 0), %esi
 	movl $(page_directory + 2048), %edi
 	xorl %ecx, %ecx
-	xorl %ebx, %ebx
+	movl pt_loc, %ebx
 	
 	floop:
-		movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
+		movl $((1 << 1) | (1 << 0)), %eax
 		orl %ebx, %eax
 		/* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
@@ -165,5 +254,5 @@
 		/* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
 		movl %eax, (%edi, %ecx, 4)
-		addl $(4 * 1024 * 1024), %ebx
+		addl $(4 * 1024), %ebx
 		
 		incl %ecx
@@ -523,4 +612,11 @@
 
 grub_ebx:
+	.long 0
+
+pt_loc:
+	.long 0
+end_of_kernel:
+	.long 0
+free_area:
 	.long 0
 
Index: kernel/arch/ia32/src/cpu/cpu.c
===================================================================
--- kernel/arch/ia32/src/cpu/cpu.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ kernel/arch/ia32/src/cpu/cpu.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -118,9 +118,11 @@
 		);
 	}
-	
+
+#ifndef PROCESSOR_i486
 	if (CPU->arch.fi.bits.sep) {
 		/* Setup fast SYSENTER/SYSEXIT syscalls */
 		syscall_setup_cpu();
 	}
+#endif
 }
 
Index: kernel/arch/ia32/src/proc/scheduler.c
===================================================================
--- kernel/arch/ia32/src/proc/scheduler.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ kernel/arch/ia32/src/proc/scheduler.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -60,8 +60,10 @@
 	uintptr_t kstk = (uintptr_t) &THREAD->kstack[STACK_SIZE];
 	
+#ifndef PROCESSOR_i486
 	if (CPU->arch.fi.bits.sep) {
 		/* Set kernel stack for CP3 -> CPL0 switch via SYSENTER */
 		write_msr(IA32_MSR_SYSENTER_ESP, kstk - sizeof(istate_t));
 	}
+#endif
 	
 	/* Set kernel stack for CPL3 -> CPL0 switch via interrupt */
Index: kernel/arch/ia32/src/syscall.c
===================================================================
--- kernel/arch/ia32/src/syscall.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ kernel/arch/ia32/src/syscall.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -39,4 +39,5 @@
 #include <arch/pm.h>
 
+#ifndef PROCESSOR_i486
 /** Enable & setup support for SYSENTER/SYSEXIT */
 void syscall_setup_cpu(void)
@@ -49,4 +50,5 @@
 	write_msr(IA32_MSR_SYSENTER_EIP, (uint32_t) sysenter_handler);
 }
+#endif
 
 /** @}
Index: kernel/generic/include/ipc/event.h
===================================================================
--- kernel/generic/include/ipc/event.h	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ kernel/generic/include/ipc/event.h	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -41,5 +41,5 @@
 #include <ipc/ipc.h>
 
-typedef struct task task_t;
+struct task;
 
 typedef void (*event_callback_t)(void *);
@@ -63,8 +63,8 @@
 
 extern void event_init(void);
-extern void event_task_init(task_t *);
+extern void event_task_init(struct task *);
 extern void event_cleanup_answerbox(answerbox_t *);
 extern void event_set_unmask_callback(event_type_t, event_callback_t);
-extern void event_task_set_unmask_callback(task_t *, event_task_type_t,
+extern void event_task_set_unmask_callback(struct task *, event_task_type_t,
     event_callback_t);
 
@@ -97,5 +97,5 @@
 extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t);
-extern int event_task_notify(task_t *, event_task_type_t, bool, sysarg_t, sysarg_t,
+extern int event_task_notify(struct task *, event_task_type_t, bool, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, sysarg_t);
 
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/Makefile	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -37,4 +37,5 @@
 	app/blkdump \
 	app/bnchmark \
+	app/devctl \
 	app/edit \
 	app/ext2info \
Index: uspace/app/devctl/Makefile
===================================================================
--- uspace/app/devctl/Makefile	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
+++ uspace/app/devctl/Makefile	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../..
+BINARY = devctl
+
+SOURCES = \
+	devctl.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/devctl/devctl.c
===================================================================
--- uspace/app/devctl/devctl.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
+++ uspace/app/devctl/devctl.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -0,0 +1,111 @@
+/*
+ * 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 devctl
+ * @{
+ */
+/** @file Control device framework (devman server).
+ */
+
+#include <devman.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/typefmt.h>
+
+#define NAME "devctl"
+
+#define MAX_NAME_LENGTH 1024
+
+static int fun_tree_print(devman_handle_t funh, int lvl)
+{
+	char name[MAX_NAME_LENGTH];
+	devman_handle_t devh;
+	devman_handle_t *cfuns;
+	size_t count, i;
+	int rc;
+	int j;
+
+	for (j = 0; j < lvl; j++)
+		printf("    ");
+
+	rc = devman_fun_get_name(funh, name, MAX_NAME_LENGTH);
+	if (rc != EOK) {
+		str_cpy(name, MAX_NAME_LENGTH, "unknown");
+		return ENOMEM;
+	}
+
+	if (name[0] == '\0')
+		str_cpy(name, MAX_NAME_LENGTH, "/");
+
+	printf("%s (%" PRIun ")\n", name, funh);
+
+	rc = devman_fun_get_child(funh, &devh);
+	if (rc == ENOENT)
+		return EOK;
+
+	if (rc != EOK) {
+		printf(NAME ": Failed getting child device for function "
+		    "%s.\n", "xxx");
+		return rc;
+	}
+
+	rc = devman_dev_get_functions(devh, &cfuns, &count);
+	if (rc != EOK) {
+		printf(NAME ": Failed getting list of functions for "
+		    "device %s.\n", "xxx");
+		return rc;
+	}
+
+	for (i = 0; i < count; i++)
+		fun_tree_print(cfuns[i], lvl + 1);
+
+	free(cfuns);
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	devman_handle_t root_fun;
+	int rc;
+
+	rc = devman_fun_get_handle("/", &root_fun, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving root function.\n");
+		return 1;
+	}
+
+	rc = fun_tree_print(root_fun, 0);
+	if (rc != EOK)
+		return 1;
+
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/lsusb/main.c
===================================================================
--- uspace/app/lsusb/main.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/app/lsusb/main.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -81,5 +81,5 @@
 		}
 		char path[MAX_PATH_LENGTH];
-		rc = devman_get_device_path(dev_handle, path, MAX_PATH_LENGTH);
+		rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
 		if (rc != EOK) {
 			continue;
@@ -120,5 +120,5 @@
 		}
 		char path[MAX_PATH_LENGTH];
-		rc = devman_get_device_path(hc_handle, path, MAX_PATH_LENGTH);
+		rc = devman_fun_get_path(hc_handle, path, MAX_PATH_LENGTH);
 		if (rc != EOK) {
 			printf(NAME ": Error resolving path of HC with SID %"
Index: uspace/app/mkbd/main.c
===================================================================
--- uspace/app/mkbd/main.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/app/mkbd/main.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -240,5 +240,5 @@
 	
 	char path[MAX_PATH_LENGTH];
-	rc = devman_get_device_path(dev_handle, path, MAX_PATH_LENGTH);
+	rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
 	if (rc != EOK) {
 		return ENOMEM;
Index: uspace/app/tester/hw/serial/serial1.c
===================================================================
--- uspace/app/tester/hw/serial/serial1.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/app/tester/hw/serial/serial1.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -72,5 +72,5 @@
 	
 	devman_handle_t handle;
-	int res = devman_device_get_handle("/hw/pci0/00:01.0/com1/a", &handle,
+	int res = devman_fun_get_handle("/hw/pci0/00:01.0/com1/a", &handle,
 	    IPC_FLAG_BLOCKING);
 	if (res != EOK)
Index: uspace/lib/c/arch/ia32/Makefile.common
===================================================================
--- uspace/lib/c/arch/ia32/Makefile.common	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/lib/c/arch/ia32/Makefile.common	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -28,5 +28,9 @@
 
 CLANG_ARCH = i386
+ifeq ($(PROCESSOR),i486)
+GCC_CFLAGS += -march=i486 -fno-omit-frame-pointer
+else
 GCC_CFLAGS += -march=pentium -fno-omit-frame-pointer
+endif
 
 ENDIANESS = LE
Index: uspace/lib/c/arch/ia32/Makefile.inc
===================================================================
--- uspace/lib/c/arch/ia32/Makefile.inc	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/lib/c/arch/ia32/Makefile.inc	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -28,5 +28,5 @@
 
 ARCH_SOURCES = \
-	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entry.S \
 	arch/$(UARCH)/src/entryjmp.s \
 	arch/$(UARCH)/src/thread_entry.s \
Index: uspace/lib/c/arch/ia32/src/entry.S
===================================================================
--- uspace/lib/c/arch/ia32/src/entry.S	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
+++ uspace/lib/c/arch/ia32/src/entry.S	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2005 Martin Decky
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+INTEL_CPUID_STANDARD = 1
+INTEL_SEP = 11
+
+.section .init, "ax"
+
+.org 0
+
+.globl __entry
+
+## User-space task entry point
+#
+# %edi contains the PCB pointer
+#
+__entry:
+	mov %ss, %ax
+	mov %ax, %ds
+	mov %ax, %es
+	mov %ax, %fs
+	# Do not set %gs, it contains descriptor that can see TLS
+
+#ifndef PROCESSOR_i486	
+	# Detect the mechanism used for making syscalls
+	movl $(INTEL_CPUID_STANDARD), %eax
+	cpuid
+	bt $(INTEL_SEP), %edx
+	jnc 0f
+	leal __syscall_fast_func, %eax
+	movl $__syscall_fast, (%eax)
+0:
+#endif
+	#
+	# Create the first stack frame.
+	#
+	pushl $0
+	movl %esp, %ebp
+	
+	# Pass the PCB pointer to __main as the first argument
+	pushl %edi
+	call __main
Index: pace/lib/c/arch/ia32/src/entry.s
===================================================================
--- uspace/lib/c/arch/ia32/src/entry.s	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ 	(revision )
@@ -1,65 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-INTEL_CPUID_STANDARD = 1
-INTEL_SEP = 11
-
-.section .init, "ax"
-
-.org 0
-
-.globl __entry
-
-## User-space task entry point
-#
-# %edi contains the PCB pointer
-#
-__entry:
-	mov %ss, %ax
-	mov %ax, %ds
-	mov %ax, %es
-	mov %ax, %fs
-	# Do not set %gs, it contains descriptor that can see TLS
-	
-	# Detect the mechanism used for making syscalls
-	movl $(INTEL_CPUID_STANDARD), %eax
-	cpuid
-	bt $(INTEL_SEP), %edx
-	jnc 0f
-	leal __syscall_fast_func, %eax
-	movl $__syscall_fast, (%eax)
-0:
-	#
-	# Create the first stack frame.
-	#
-	pushl $0
-	movl %esp, %ebp
-	
-	# Pass the PCB pointer to __main as the first argument
-	pushl %edi
-	call __main
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/lib/c/generic/devman.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2007 Josef Cejka
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * Copyright (c) 2010 Lenka Trochtova
  * All rights reserved.
@@ -342,5 +342,5 @@
 }
 
-int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
+int devman_fun_get_handle(const char *pathname, devman_handle_t *handle,
     unsigned int flags)
 {
@@ -383,5 +383,132 @@
 }
 
-int devman_get_device_path(devman_handle_t handle, char *path, size_t path_size)
+static int devman_get_str_internal(sysarg_t method, sysarg_t arg1, char *buf,
+    size_t buf_size)
+{
+	async_exch_t *exch;
+	ipc_call_t dreply;
+	size_t act_size;
+	sysarg_t dretval;
+	
+	exch = devman_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	aid_t dreq = async_data_read(exch, buf, buf_size - 1, &dreply);
+	async_wait_for(dreq, &dretval);
+	
+	devman_exchange_end(exch);
+	
+	if (dretval != EOK) {
+		async_wait_for(req, NULL);
+		return dretval;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK)
+		return retval;
+	
+	act_size = IPC_GET_ARG2(dreply);
+	assert(act_size <= buf_size - 1);
+	buf[act_size] = '\0';
+	
+	return EOK;
+}
+
+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);
+}
+
+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);
+}
+
+static int devman_get_handles_once(sysarg_t method, sysarg_t arg1,
+    devman_handle_t *handle_buf, size_t buf_size, size_t *act_size)
+{
+	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	int rc = async_data_read_start(exch, handle_buf, buf_size);
+	
+	devman_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return rc;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		return retval;
+	}
+	
+	*act_size = IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Get list of handles.
+ *
+ * Returns an allocated array of handles.
+ *
+ * @param method	IPC method
+ * @param arg1		IPC argument 1
+ * @param data		Place to store pointer to array of handles
+ * @param count		Place to store number of handles
+ * @return 		EOK on success or negative error code
+ */
+static int devman_get_handles_internal(sysarg_t method, sysarg_t arg1,
+    devman_handle_t **data, size_t *count)
+{
+	devman_handle_t *handles;
+	size_t act_size;
+	size_t alloc_size;
+	int rc;
+
+	*data = NULL;
+	act_size = 0;	/* silence warning */
+
+	rc = devman_get_handles_once(method, arg1, NULL, 0,
+	    &act_size);
+	if (rc != EOK)
+		return rc;
+
+	alloc_size = act_size;
+	handles = malloc(alloc_size);
+	if (handles == NULL)
+		return ENOMEM;
+
+	while (true) {
+		rc = devman_get_handles_once(method, arg1, handles, alloc_size,
+		    &act_size);
+		if (rc != EOK)
+			return rc;
+
+		if (act_size <= alloc_size)
+			break;
+
+		alloc_size *= 2;
+		free(handles);
+
+		handles = malloc(alloc_size);
+		if (handles == NULL)
+			return ENOMEM;
+	}
+
+	*count = act_size / sizeof(devman_handle_t);
+	*data = handles;
+	return EOK;
+}
+
+int devman_fun_get_child(devman_handle_t funh, devman_handle_t *devh)
 {
 	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
@@ -389,45 +516,16 @@
 		return ENOMEM;
 	
-	ipc_call_t answer;
-	aid_t req = async_send_1(exch, DEVMAN_DEVICE_GET_DEVICE_PATH,
-	    handle, &answer);
-	
-	ipc_call_t data_request_call;
-	aid_t data_request = async_data_read(exch, path, path_size,
-	    &data_request_call);
-	
-	devman_exchange_end(exch);
-	
-	if (data_request == 0) {
-		async_wait_for(req, NULL);
-		return ENOMEM;
-	}
-	
-	sysarg_t data_request_rc;
-	async_wait_for(data_request, &data_request_rc);
-	
-	sysarg_t opening_request_rc;
-	async_wait_for(req, &opening_request_rc);
-	
-	if (data_request_rc != EOK) {
-		/* Prefer the return code of the opening request. */
-		if (opening_request_rc != EOK)
-			return (int) opening_request_rc;
-		else
-			return (int) data_request_rc;
-	}
-	
-	if (opening_request_rc != EOK)
-		return (int) opening_request_rc;
-	
-	/* To be on the safe-side. */
-	path[path_size - 1] = 0;
-	size_t transferred_size = IPC_GET_ARG2(data_request_call);
-	if (transferred_size >= path_size)
-		return ELIMIT;
-	
-	/* Terminate the string (trailing 0 not send over IPC). */
-	path[transferred_size] = 0;
-	return EOK;
+	sysarg_t retval = async_req_1_1(exch, DEVMAN_FUN_GET_CHILD,
+	    funh, devh);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
+}
+
+int devman_dev_get_functions(devman_handle_t devh, devman_handle_t **funcs,
+    size_t *count)
+{
+	return devman_get_handles_internal(DEVMAN_DEV_GET_FUNCTIONS,
+	    devh, funcs, count);
 }
 
Index: uspace/lib/c/generic/io/printf_core.c
===================================================================
--- uspace/lib/c/generic/io/printf_core.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/lib/c/generic/io/printf_core.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -206,5 +206,5 @@
 	}
 	
-	return (int) (counter + 1);
+	return (int) (counter);
 }
 
@@ -244,5 +244,5 @@
 	}
 	
-	return (int) (counter + 1);
+	return (int) (counter);
 }
 
Index: uspace/lib/c/include/devman.h
===================================================================
--- uspace/lib/c/include/devman.h	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/lib/c/include/devman.h	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -56,7 +56,11 @@
     unsigned int);
 
-extern int devman_device_get_handle(const char *, devman_handle_t *,
+extern int devman_fun_get_handle(const char *, devman_handle_t *,
     unsigned int);
-extern int devman_get_device_path(devman_handle_t, char *, size_t);
+extern int devman_fun_get_child(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_name(devman_handle_t, char *, size_t);
+extern int devman_fun_get_path(devman_handle_t, char *, size_t);
 
 extern int devman_add_device_to_category(devman_handle_t, const char *);
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/lib/c/include/ipc/devman.h	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -149,5 +149,8 @@
 typedef enum {
 	DEVMAN_DEVICE_GET_HANDLE = IPC_FIRST_USER_METHOD,
-	DEVMAN_DEVICE_GET_DEVICE_PATH,
+	DEVMAN_DEV_GET_FUNCTIONS,
+	DEVMAN_FUN_GET_CHILD,
+	DEVMAN_FUN_GET_NAME,
+	DEVMAN_FUN_GET_PATH,
 	DEVMAN_FUN_SID_TO_HANDLE
 } client_to_devman_t;
Index: uspace/lib/usb/src/resolve.c
===================================================================
--- uspace/lib/usb/src/resolve.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/lib/usb/src/resolve.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -152,5 +152,5 @@
 		if (str_length(func_start) > 0) {
 			char tmp_path[MAX_DEVICE_PATH ];
-			rc = devman_get_device_path(dev_handle,
+			rc = devman_fun_get_path(dev_handle,
 			    tmp_path, MAX_DEVICE_PATH);
 			if (rc != EOK) {
@@ -173,5 +173,5 @@
 
 	/* First try to get the device handle. */
-	rc = devman_device_get_handle(path, &dev_handle, 0);
+	rc = devman_fun_get_handle(path, &dev_handle, 0);
 	if (rc != EOK) {
 		free(path);
@@ -184,5 +184,5 @@
 		/* Get device handle first. */
 		devman_handle_t tmp_handle;
-		rc = devman_device_get_handle(path, &tmp_handle, 0);
+		rc = devman_fun_get_handle(path, &tmp_handle, 0);
 		if (rc != EOK) {
 			free(path);
Index: uspace/lib/usbvirt/src/device.c
===================================================================
--- uspace/lib/usbvirt/src/device.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/lib/usbvirt/src/device.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -87,5 +87,5 @@
 	
 	devman_handle_t handle;
-	int rc = devman_device_get_handle(vhc_path, &handle, 0);
+	int rc = devman_fun_get_handle(vhc_path, &handle, 0);
 	if (rc != EOK)
 		return rc;
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/srv/devman/devman.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -920,4 +920,35 @@
 }
 
+/** 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 */
 
@@ -1145,5 +1176,5 @@
 	char *rel_path = path;
 	char *next_path_elem = NULL;
-	bool cont = true;
+	bool cont = (rel_path[1] != '\0');
 	
 	while (cont && fun != NULL) {
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/srv/devman/devman.h	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -253,4 +253,6 @@
 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);
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 36b16bc4049fcc40e8ec4b5d1fcbcf9f46a96553)
+++ uspace/srv/devman/main.c	(revision 7a2f7ecd439305a8c51439cedcfd1798290493a0)
@@ -497,7 +497,6 @@
 }
 
-/** Find device path by its handle. */
-static void devman_get_device_path_by_handle(ipc_callid_t iid,
-    ipc_call_t *icall)
+/** 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);
@@ -523,4 +522,41 @@
 	}
 
+	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);
+
+	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);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
 	size_t sent_length = str_size(fun->pathname);
 	if (sent_length > data_len) {
@@ -532,4 +568,78 @@
 
 	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) {
+		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(&device_tree, IPC_GET_ARG1(*icall));
+	if (fun == NULL) {
+		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);
 }
 
@@ -566,6 +676,15 @@
 			devman_function_get_handle(callid, &call);
 			break;
-		case DEVMAN_DEVICE_GET_DEVICE_PATH:
-			devman_get_device_path_by_handle(callid, &call);
+		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_PATH:
+			devman_fun_get_path(callid, &call);
 			break;
 		case DEVMAN_FUN_SID_TO_HANDLE:
