Index: .bzrignore
===================================================================
--- .bzrignore	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ .bzrignore	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -52,4 +52,5 @@
 ./uspace/app/ping/ping
 ./uspace/app/redir/redir
+./uspace/app/sysinfo/sysinfo
 ./uspace/app/sbi/sbi
 ./uspace/app/stats/stats
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ boot/Makefile.common	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -144,4 +144,5 @@
 	$(USPACE_PATH)/app/ping/ping \
 	$(USPACE_PATH)/app/stats/stats \
+	$(USPACE_PATH)/app/sysinfo/sysinfo \
 	$(USPACE_PATH)/app/tasks/tasks \
 	$(USPACE_PATH)/app/top/top \
Index: kernel/arch/amd64/src/amd64.c
===================================================================
--- kernel/arch/amd64/src/amd64.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/amd64/src/amd64.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -199,4 +199,10 @@
 void arch_post_smp_init(void)
 {
+	/* Currently the only supported platform for amd64 is 'pc'. */
+	static const char *platform = "pc";
+
+	sysinfo_set_item_data("platform", NULL, (void *) platform,
+	    str_size(platform));
+
 #ifdef CONFIG_PC_KBD
 	/*
Index: kernel/arch/arm32/include/mach/integratorcp/integratorcp.h
===================================================================
--- kernel/arch/arm32/include/mach/integratorcp/integratorcp.h	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/arm32/include/mach/integratorcp/integratorcp.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -106,4 +106,5 @@
 extern void icp_frame_init(void);
 extern size_t icp_get_irq_count(void);
+extern const char *icp_get_platform_name(void);
 
 extern struct arm_machine_ops icp_machine_ops;
Index: kernel/arch/arm32/include/mach/testarm/testarm.h
===================================================================
--- kernel/arch/arm32/include/mach/testarm/testarm.h	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/arm32/include/mach/testarm/testarm.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -74,4 +74,5 @@
 extern void gxemul_frame_init(void);
 extern size_t gxemul_get_irq_count(void);
+extern const char *gxemul_get_platform_name(void);
 
 extern struct arm_machine_ops gxemul_machine_ops;
Index: kernel/arch/arm32/include/machine_func.h
===================================================================
--- kernel/arch/arm32/include/machine_func.h	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/arm32/include/machine_func.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -56,4 +56,5 @@
 	void (*machine_input_init)(void);
 	size_t (*machine_get_irq_count)(void);
+	const char *(*machine_get_platform_name)(void);
 };
 
Index: kernel/arch/arm32/src/mach/gta02/gta02.c
===================================================================
--- kernel/arch/arm32/src/mach/gta02/gta02.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -71,4 +71,5 @@
 static void gta02_input_init(void);
 static size_t gta02_get_irq_count(void);
+static const char *gta02_get_platform_name(void);
 
 static void gta02_timer_irq_init(void);
@@ -92,5 +93,6 @@
 	gta02_output_init,
 	gta02_input_init,
-	gta02_get_irq_count
+	gta02_get_irq_count,
+	gta02_get_platform_name
 };
 
@@ -235,4 +237,9 @@
 }
 
+const char *gta02_get_platform_name(void)
+{
+	return "gta02";
+}
+
 static void gta02_timer_irq_init(void)
 {
Index: kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
===================================================================
--- kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -65,5 +65,6 @@
 	icp_output_init,
 	icp_input_init,
-	icp_get_irq_count
+	icp_get_irq_count,
+	icp_get_platform_name
 };
 
@@ -342,4 +343,9 @@
 }
 
+const char *icp_get_platform_name(void)
+{
+	return "integratorcp";
+}
+
 /** @}
  */
Index: kernel/arch/arm32/src/mach/testarm/testarm.c
===================================================================
--- kernel/arch/arm32/src/mach/testarm/testarm.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/arm32/src/mach/testarm/testarm.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -65,5 +65,6 @@
 	gxemul_output_init,
 	gxemul_input_init,
-	gxemul_get_irq_count
+	gxemul_get_irq_count,
+	gxemul_get_platform_name
 };
 
@@ -132,4 +133,9 @@
 }
 
+const char *gxemul_get_platform_name(void)
+{
+	return "gxemul";
+}
+
 /** Starts gxemul Real Time Clock device, which asserts regular interrupts.
  *
Index: kernel/arch/ia32/src/ia32.c
===================================================================
--- kernel/arch/ia32/src/ia32.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/ia32/src/ia32.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -157,4 +157,10 @@
 void arch_post_smp_init(void)
 {
+	/* Currently the only supported platform for ia32 is 'pc'. */
+	static const char *platform = "pc";
+
+	sysinfo_set_item_data("platform", NULL, (void *) platform,
+	    str_size(platform));
+
 #ifdef CONFIG_PC_KBD
 	/*
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/ia64/src/ia64.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -147,4 +147,16 @@
 void arch_post_smp_init(void)
 {
+	static const char *platform;
+
+	/* Set platform name. */
+#ifdef MACHINE_ski
+	platform = "pc";
+#endif
+#ifdef MACHINE_i460GX
+	platform = "i460GX";
+#endif
+	sysinfo_set_item_data("platform", NULL, (void *) platform,
+	    str_size(platform));
+
 #ifdef MACHINE_ski
 	ski_instance_t *ski_instance = skiin_init();
Index: kernel/arch/mips32/src/mips32.c
===================================================================
--- kernel/arch/mips32/src/mips32.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/mips32/src/mips32.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -168,4 +168,19 @@
 void arch_post_smp_init(void)
 {
+	static const char *platform;
+
+	/* Set platform name. */
+#ifdef MACHINE_msim
+	platform = "msim";
+#endif
+#ifdef MACHINE_bgxemul
+	platform = "gxemul";
+#endif
+#ifdef MACHINE_lgxemul
+	platform = "gxemul";
+#endif
+	sysinfo_set_item_data("platform", NULL, (void *) platform,
+	    str_size(platform));
+
 #ifdef CONFIG_MIPS_KBD
 	/*
Index: kernel/arch/ppc32/src/ppc32.c
===================================================================
--- kernel/arch/ppc32/src/ppc32.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/ppc32/src/ppc32.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -249,4 +249,10 @@
 void arch_post_smp_init(void)
 {
+	/* Currently the only supported platform for ppc32 is 'mac'. */
+	static const char *platform = "mac";
+
+	sysinfo_set_item_data("platform", NULL, (void *) platform,
+	    str_size(platform));
+
 	ofw_tree_walk_by_device_type("mac-io", macio_register, NULL);
 }
Index: kernel/arch/sparc64/src/sun4u/sparc64.c
===================================================================
--- kernel/arch/sparc64/src/sun4u/sparc64.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/sparc64/src/sun4u/sparc64.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -50,4 +50,5 @@
 #include <ddi/irq.h>
 #include <str.h>
+#include <sysinfo/sysinfo.h>
 
 memmap_t memmap;
@@ -111,4 +112,10 @@
 void arch_post_smp_init(void)
 {
+	/* Currently the only supported platform for sparc64/sun4u is 'sun4u'. */
+	static const char *platform = "sun4u";
+
+	sysinfo_set_item_data("platform", NULL, (void *) platform,
+	    str_size(platform));
+
 	standalone_sparc64_console_init();
 }
Index: kernel/arch/sparc64/src/sun4v/sparc64.c
===================================================================
--- kernel/arch/sparc64/src/sun4v/sparc64.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/arch/sparc64/src/sun4v/sparc64.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -52,4 +52,5 @@
 #include <str.h>
 #include <arch/drivers/niagara.h>
+#include <sysinfo/sysinfo.h>
 
 memmap_t memmap;
@@ -109,4 +110,10 @@
 void arch_post_smp_init(void)
 {
+	/* Currently the only supported platform for sparc64/sun4v is 'sun4v'. */
+	static const char *platform = "sun4v";
+
+	sysinfo_set_item_data("platform", NULL, (void *) platform,
+	    str_size(platform));
+
 	niagarain_init();
 }
Index: kernel/generic/include/ddi/irq.h
===================================================================
--- kernel/generic/include/ddi/irq.h	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/generic/include/ddi/irq.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -189,4 +189,6 @@
 extern hash_table_t irq_uspace_hash_table;
 
+extern inr_t last_inr;
+
 extern void irq_init(size_t, size_t);
 extern void irq_initialize(irq_t *);
Index: kernel/generic/src/ddi/irq.c
===================================================================
--- kernel/generic/src/ddi/irq.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/generic/src/ddi/irq.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -136,4 +136,7 @@
 static size_t buckets;
 
+/** Last valid INR. */
+inr_t last_inr = 0;
+
 /** Initialize IRQ subsystem.
  *
@@ -145,4 +148,6 @@
 {
 	buckets = chains;
+	last_inr = inrs - 1;
+
 	/*
 	 * Be smart about the choice of the hash table operations.
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ kernel/generic/src/ipc/irq.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -131,12 +131,11 @@
 /** Register an answerbox as a receiving end for IRQ notifications.
  *
- * @param box     Receiving answerbox.
- * @param inr     IRQ number.
- * @param devno   Device number.
- * @param imethod Interface and method to be associated
- *                with the notification.
- * @param ucode   Uspace pointer to top-half pseudocode.
- *
- * @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success.
+ * @param box		Receiving answerbox.
+ * @param inr		IRQ number.
+ * @param devno		Device number.
+ * @param imethod	Interface and method to be associated with the
+ *			notification.
+ * @param ucode		Uspace pointer to top-half pseudocode.
+ * @return		EOK on success or a negative error code.
  *
  */
@@ -148,4 +147,7 @@
 		(sysarg_t) devno
 	};
+
+	if ((inr < 0) || (inr > last_inr))
+		return ELIMIT;
 	
 	irq_code_t *code;
@@ -208,8 +210,8 @@
 /** Unregister task from IRQ notification.
  *
- * @param box   Answerbox associated with the notification.
- * @param inr   IRQ number.
- * @param devno Device number.
- *
+ * @param box		Answerbox associated with the notification.
+ * @param inr		IRQ number.
+ * @param devno		Device number.
+ * @return		EOK on success or a negative error code.
  */
 int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)
@@ -219,4 +221,7 @@
 		(sysarg_t) devno
 	};
+
+	if ((inr < 0) || (inr > last_inr))
+		return ELIMIT;
 	
 	irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -55,4 +55,5 @@
 	app/nettest2 \
 	app/ping \
+	app/sysinfo \
 	srv/clip \
 	srv/devmap \
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/app/init/init.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -57,6 +57,6 @@
 #define DEVFS_MOUNT_POINT  "/dev"
 
-#define SCRATCH_FS_TYPE      "tmpfs"
-#define SCRATCH_MOUNT_POINT  "/scratch"
+#define TMPFS_FS_TYPE      "tmpfs"
+#define TMPFS_MOUNT_POINT  "/tmp"
 
 #define DATA_FS_TYPE      "fat"
@@ -235,9 +235,9 @@
 }
 
-static bool mount_scratch(void)
-{
-	int rc = mount(SCRATCH_FS_TYPE, SCRATCH_MOUNT_POINT, "", "", 0);
-	return mount_report("Scratch filesystem", SCRATCH_MOUNT_POINT,
-	    SCRATCH_FS_TYPE, NULL, rc);
+static bool mount_tmpfs(void)
+{
+	int rc = mount(TMPFS_FS_TYPE, TMPFS_MOUNT_POINT, "", "", 0);
+	return mount_report("Temporary filesystem", TMPFS_MOUNT_POINT,
+	    TMPFS_FS_TYPE, NULL, rc);
 }
 
@@ -271,5 +271,5 @@
 	}
 	
-	mount_scratch();
+	mount_tmpfs();
 	
 	spawn("/srv/fhc");
Index: uspace/app/sysinfo/Makefile
===================================================================
--- uspace/app/sysinfo/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/app/sysinfo/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2010 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 = ../..
+EXTRA_CFLAGS = -Iinclude
+BINARY = sysinfo
+
+SOURCES = \
+	sysinfo.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/sysinfo/sysinfo.c
===================================================================
--- uspace/app/sysinfo/sysinfo.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
+++ uspace/app/sysinfo/sysinfo.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2010 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 sysinfo
+ * @{
+ */
+/** @file sysinfo.c
+ * @brief Print value of item from sysinfo tree.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <sysinfo.h>
+#include <sys/types.h>
+
+static int print_item_val(char *ipath);
+static int print_item_data(char *ipath);
+
+static void dump_bytes_hex(char *data, size_t size);
+static void dump_bytes_text(char *data, size_t size);
+
+static void print_syntax(void);
+
+int main(int argc, char *argv[])
+{
+	int rc;
+	char *ipath;
+	sysinfo_item_tag_t tag;
+
+	if (argc != 2) {
+		print_syntax();
+		return 1;
+	}
+
+	ipath = argv[1];
+
+	tag = sysinfo_get_tag(ipath);
+
+	/* Silence warning */
+	rc = EOK;
+
+	switch (tag) {
+	case SYSINFO_VAL_UNDEFINED:
+		printf("Error: Sysinfo item '%s' not defined.\n", ipath);
+		rc = 2;
+		break;
+	case SYSINFO_VAL_VAL:
+		rc = print_item_val(ipath);
+		break;
+	case SYSINFO_VAL_DATA:
+		rc = print_item_data(ipath);
+		break;
+	}
+
+	return rc;
+}
+
+static int print_item_val(char *ipath)
+{
+	sysarg_t value;
+	int rc;
+
+	rc = sysinfo_get_value(ipath, &value);
+	if (rc != EOK) {
+		printf("Error reading item '%s'.\n", ipath);
+		return rc;
+	}
+
+	printf("%s -> %" PRIu64 " (0x%" PRIx64 ")\n", ipath,
+	    (uint64_t) value, (uint64_t) value);
+
+	return EOK;
+}
+
+static int print_item_data(char *ipath)
+{
+	void *data;
+	size_t size;
+
+	data = sysinfo_get_data(ipath, &size);
+	if (data == NULL) {
+		printf("Error reading item '%s'.\n", ipath);
+		return -1;
+	}
+
+	printf("%s -> ", ipath);
+	dump_bytes_hex(data, size);
+	fputs(" ('", stdout);
+	dump_bytes_text(data, size);
+	fputs("')\n", stdout);
+
+	return EOK;
+}
+
+static void dump_bytes_hex(char *data, size_t size)
+{
+	size_t i;
+
+	for (i = 0; i < size; ++i) {
+		if (i > 0) putchar(' ');
+		printf("0x%02x", (uint8_t) data[i]);
+	}
+}
+
+static void dump_bytes_text(char *data, size_t size)
+{
+	wchar_t c;
+	size_t offset;
+
+	offset = 0;
+
+	while (offset < size) {
+		c = str_decode(data, &offset, size);
+		printf("%lc", (wint_t) c);
+	}
+}
+
+
+static void print_syntax(void)
+{
+	printf("Syntax: sysinfo <item_path>\n");
+}
+
+/** @}
+ */
Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/app/tester/Makefile	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -51,6 +51,4 @@
 	vfs/vfs1.c \
 	ipc/ping_pong.c \
-	ipc/register.c \
-	ipc/connect.c \
 	loop/loop1.c \
 	mm/malloc1.c \
Index: pace/app/tester/ipc/connect.c
===================================================================
--- uspace/app/tester/ipc/connect.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ 	(revision )
@@ -1,73 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * 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 <stdio.h>
-#include <unistd.h>
-#include <atomic.h>
-#include "../tester.h"
-
-static atomic_t finish;
-
-static void callback(void *priv, int retval, ipc_call_t *data)
-{
-	atomic_set(&finish, 1);
-}
-
-const char *test_connect(void)
-{
-	TPRINTF("Connecting to %u...", IPC_TEST_SERVICE);
-	int phone = ipc_connect_me_to(PHONE_NS, IPC_TEST_SERVICE, 0, 0);
-	if (phone > 0) {
-		TPRINTF("phoneid %d\n", phone);
-	} else {
-		TPRINTF("\n");
-		return "ipc_connect_me_to() failed";
-	}
-	
-	printf("Sending synchronous message...\n");
-	int retval = ipc_call_sync_0_0(phone, IPC_TEST_METHOD);
-	TPRINTF("Received response to synchronous message\n");
-	
-	TPRINTF("Sending asynchronous message...\n");
-	atomic_set(&finish, 0);
-	ipc_call_async_0(phone, IPC_TEST_METHOD, NULL, callback, 1);
-	while (atomic_get(&finish) != 1)
-		TPRINTF(".");
-	TPRINTF("Received response to asynchronous message\n");
-	
-	TPRINTF("Hanging up...");
-	retval = ipc_hangup(phone);
-	if (retval == 0) {
-		TPRINTF("OK\n");
-	} else {
-		TPRINTF("\n");
-		return "ipc_hangup() failed";
-	}
-	
-	return NULL;
-}
Index: pace/app/tester/ipc/connect.def
===================================================================
--- uspace/app/tester/ipc/connect.def	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"connect",
-	"IPC connection test (connect to other service)",
-	&test_connect,
-	true
-},
Index: pace/app/tester/ipc/register.c
===================================================================
--- uspace/app/tester/ipc/register.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ 	(revision )
@@ -1,90 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * 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 <inttypes.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <async.h>
-#include <errno.h>
-#include "../tester.h"
-
-#define MAX_CONNECTIONS  50
-
-static int connections[MAX_CONNECTIONS];
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	unsigned int i;
-	
-	TPRINTF("Connected phone %" PRIun " accepting\n", icall->in_phone_hash);
-	ipc_answer_0(iid, EOK);
-	for (i = 0; i < MAX_CONNECTIONS; i++) {
-		if (!connections[i]) {
-			connections[i] = icall->in_phone_hash;
-			break;
-		}
-	}
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		int retval;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			TPRINTF("Phone %" PRIun " hung up\n", icall->in_phone_hash);
-			retval = 0;
-			break;
-		case IPC_TEST_METHOD:
-			TPRINTF("Received well known message from %" PRIun ": %" PRIun "\n",
-			    icall->in_phone_hash, callid);
-			ipc_answer_0(callid, EOK);
-			break;
-		default:
-			TPRINTF("Received unknown message from %" PRIun ": %" PRIun "\n",
-			    icall->in_phone_hash, callid);
-			ipc_answer_0(callid, ENOENT);
-			break;
-		}
-	}
-}
-
-const char *test_register(void)
-{
-	async_set_client_connection(client_connection);
-	
-	sysarg_t phonead;
-	int res = ipc_connect_to_me(PHONE_NS, IPC_TEST_SERVICE, 0, 0, &phonead);
-	if (res != 0)
-		return "Failed registering IPC service";
-	
-	TPRINTF("Registered as service %u, accepting connections\n", IPC_TEST_SERVICE);
-	async_manager();
-	
-	return NULL;
-}
Index: pace/app/tester/ipc/register.def
===================================================================
--- uspace/app/tester/ipc/register.def	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"register",
-	"IPC registration test",
-	&test_register,
-	true
-},
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/app/tester/tester.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -60,6 +60,4 @@
 #include "vfs/vfs1.def"
 #include "ipc/ping_pong.def"
-#include "ipc/register.def"
-#include "ipc/connect.def"
 #include "loop/loop1.def"
 #include "mm/malloc1.def"
Index: uspace/app/tester/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/app/tester/tester.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -77,6 +77,4 @@
 extern const char *test_vfs1(void);
 extern const char *test_ping_pong(void);
-extern const char *test_register(void);
-extern const char *test_connect(void);
 extern const char *test_loop1(void);
 extern const char *test_malloc1(void);
Index: uspace/app/tester/vfs/vfs1.c
===================================================================
--- uspace/app/tester/vfs/vfs1.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/app/tester/vfs/vfs1.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -40,10 +40,5 @@
 #include "../tester.h"
 
-#define FS_TYPE      "tmpfs"
-#define MOUNT_POINT  "/tmp"
-#define OPTIONS      ""
-#define FLAGS        0
-
-#define TEST_DIRECTORY  MOUNT_POINT "/testdir"
+#define TEST_DIRECTORY  "/tmp/testdir"
 #define TEST_FILE       TEST_DIRECTORY "/testfile"
 #define TEST_FILE2      TEST_DIRECTORY "/nextfile"
@@ -75,23 +70,9 @@
 const char *test_vfs1(void)
 {
-	if (mkdir(MOUNT_POINT, 0) != 0)
+	int rc;
+	if ((rc = mkdir(TEST_DIRECTORY, 0)) != 0) {
+		TPRINTF("rc=%d\n", rc);
 		return "mkdir() failed";
-	TPRINTF("Created directory %s\n", MOUNT_POINT);
-	
-	int rc = mount(FS_TYPE, MOUNT_POINT, "", OPTIONS, FLAGS);
-	switch (rc) {
-	case EOK:
-		TPRINTF("Mounted %s on %s\n", FS_TYPE, MOUNT_POINT);
-		break;
-	case EBUSY:
-		TPRINTF("(INFO) Filesystem already mounted on %s\n", MOUNT_POINT);
-		break;
-	default:
-		TPRINTF("(ERR) IPC returned errno %d (is tmpfs loaded?)\n", rc);
-		return "mount() failed";
 	}
-	
-	if (mkdir(TEST_DIRECTORY, 0) != 0)
-		return "mkdir() failed";
 	TPRINTF("Created directory %s\n", TEST_DIRECTORY);
 	
Index: uspace/drv/ns8250/ns8250.c
===================================================================
--- uspace/drv/ns8250/ns8250.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/drv/ns8250/ns8250.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -342,13 +342,13 @@
 		printf(NAME ": failed to connect to the parent driver of the "
 		    "device %s.\n", dev->name);
-		ret = EPARTY;	/* FIXME: use another EC */
+		ret = dev->parent_phone;
 		goto failed;
 	}
 	
 	/* Get hw resources. */
-	if (!get_hw_resources(dev->parent_phone, &hw_resources)) {
+	ret = get_hw_resources(dev->parent_phone, &hw_resources);
+	if (ret != EOK) {
 		printf(NAME ": failed to get hw resources for the device "
 		    "%s.\n", dev->name);
-		ret = EPARTY;	/* FIXME: use another EC */
 		goto failed;
 	}
@@ -374,5 +374,5 @@
 				printf(NAME ": i/o range assigned to the device "
 				    "%s is too small.\n", dev->name);
-				ret = EPARTY;	/* FIXME: use another EC */
+				ret = ELIMIT;
 				goto failed;
 			}
@@ -390,5 +390,5 @@
 		printf(NAME ": missing hw resource(s) for the device %s.\n",
 		    dev->name);
-		ret = EPARTY;	/* FIXME: use another EC */
+		ret = ENOENT;
 		goto failed;
 	}
Index: uspace/drv/pciintel/pci.c
===================================================================
--- uspace/drv/pciintel/pci.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/drv/pciintel/pci.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -452,4 +452,6 @@
 static int pci_add_device(device_t *dev)
 {
+	int rc;
+
 	printf(NAME ": pci_add_device\n");
 	
@@ -466,15 +468,16 @@
 		    "parent's driver.\n");
 		delete_pci_bus_data(bus_data);
-		return EPARTY;	/* FIXME: use another EC */
+		return dev->parent_phone;
 	}
 	
 	hw_resource_list_t hw_resources;
 	
-	if (!get_hw_resources(dev->parent_phone, &hw_resources)) {
+	rc = get_hw_resources(dev->parent_phone, &hw_resources);
+	if (rc != EOK) {
 		printf(NAME ": pci_add_device failed to get hw resources for "
 		    "the device.\n");
 		delete_pci_bus_data(bus_data);
 		ipc_hangup(dev->parent_phone);
-		return EPARTY;	/* FIXME: use another EC */
+		return rc;
 	}	
 	
Index: uspace/drv/root/root.c
===================================================================
--- uspace/drv/root/root.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/drv/root/root.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -47,4 +47,5 @@
 #include <macros.h>
 #include <inttypes.h>
+#include <sysinfo.h>
 
 #include <driver.h>
@@ -55,5 +56,5 @@
 
 #define PLATFORM_DEVICE_NAME "hw"
-#define PLATFORM_DEVICE_MATCH_ID STRING(UARCH)
+#define PLATFORM_DEVICE_MATCH_ID_FMT "platform/%s"
 #define PLATFORM_DEVICE_MATCH_SCORE 100
 
@@ -100,11 +101,41 @@
 static int add_platform_child(device_t *parent)
 {
+	char *match_id;
+	char *platform;
+	size_t platform_size;
+	int res;
+
+	/* Get platform name from sysinfo. */
+
+	platform = sysinfo_get_data("platform", &platform_size);
+	if (platform == NULL) {
+		printf(NAME ": Failed to obtain platform name.\n");
+		return ENOENT;
+	}
+
+	/* Null-terminate string. */
+	platform = realloc(platform, platform_size + 1);
+	if (platform == NULL) {
+		printf(NAME ": Memory allocation failed.\n");
+		return ENOMEM;
+	}
+
+	platform[platform_size] = '\0';
+
+	/* Construct match ID. */
+
+	if (asprintf(&match_id, PLATFORM_DEVICE_MATCH_ID_FMT, platform) == -1) {
+		printf(NAME ": Memory allocation failed.\n");
+		return ENOMEM;
+	}
+
+	/* Add child. */
+
 	printf(NAME ": adding new child for platform device.\n");
 	printf(NAME ":   device node is `%s' (%d %s)\n", PLATFORM_DEVICE_NAME,
-	    PLATFORM_DEVICE_MATCH_SCORE, PLATFORM_DEVICE_MATCH_ID);
-	
-	int res = child_device_register_wrapper(parent, PLATFORM_DEVICE_NAME,
-	    PLATFORM_DEVICE_MATCH_ID, PLATFORM_DEVICE_MATCH_SCORE,
-	    NULL);
+	    PLATFORM_DEVICE_MATCH_SCORE, match_id);
+
+	res = child_device_register_wrapper(parent, PLATFORM_DEVICE_NAME,
+	    match_id, PLATFORM_DEVICE_MATCH_SCORE, NULL);
 
 	return res;
Index: uspace/drv/rootpc/rootpc.c
===================================================================
--- uspace/drv/rootpc/rootpc.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/drv/rootpc/rootpc.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -28,6 +28,6 @@
 
 /**
- * @defgroup root_pc Root HW device driver for ia32 and amd64 platform.
- * @brief HelenOS root HW device driver for ia32 and amd64 platform.
+ * @defgroup root_pc PC platform driver.
+ * @brief HelenOS PC platform driver.
  * @{
  */
@@ -182,6 +182,5 @@
 	/* Register child devices. */
 	if (!rootpc_add_children(dev)) {
-		printf(NAME ": failed to add child devices for platform "
-		    "ia32.\n");
+		printf(NAME ": failed to add child devices for PC platform.\n");
 	}
 	
@@ -196,5 +195,5 @@
 int main(int argc, char *argv[])
 {
-	printf(NAME ": HelenOS rootpc device driver\n");
+	printf(NAME ": HelenOS PC platform driver\n");
 	root_pc_init();
 	return driver_main(&rootpc_driver);
Index: uspace/drv/rootpc/rootpc.ma
===================================================================
--- uspace/drv/rootpc/rootpc.ma	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/drv/rootpc/rootpc.ma	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -1,2 +1,1 @@
-10 ia32
-10 amd64
+10 platform/pc
Index: uspace/drv/usbkbd/main.c
===================================================================
--- uspace/drv/usbkbd/main.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/drv/usbkbd/main.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -29,4 +29,7 @@
 #include <driver.h>
 #include <ipc/driver.h>
+#include <ipc/kbd.h>
+#include <io/keycode.h>
+#include <io/console.h>
 #include <errno.h>
 #include <fibril.h>
@@ -41,4 +44,49 @@
 #define GUESSED_POLL_ENDPOINT 1
 
+static void default_connection_handler(device_t *, ipc_callid_t, ipc_call_t *);
+static device_ops_t keyboard_ops = {
+	.default_handler = default_connection_handler
+};
+
+static int console_callback_phone = -1;
+
+/** Default handler for IPC methods not handled by DDF.
+ *
+ * @param dev Device handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+void default_connection_handler(device_t *dev,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (console_callback_phone != -1) {
+			ipc_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		console_callback_phone = callback;
+		ipc_answer_0(icallid, EOK);
+		return;
+	}
+
+	ipc_answer_0(icallid, EINVAL);
+}
+
+static void send_key(int key, int type, wchar_t c) {
+	async_msg_4(console_callback_phone, KBD_EVENT, type, key,
+	    KM_NUM_LOCK, c);
+}
+
+static void send_alnum(int key, wchar_t c) {
+	printf(NAME ": sending key '%lc' to console\n", (wint_t) c);
+	send_key(key, KEY_PRESS, c);
+	send_key(key, KEY_RELEASE, c);
+}
+
 /*
  * Callbacks for parser
@@ -183,4 +231,13 @@
 		sizeof(usb_hid_report_in_callbacks_t));
 	callbacks->keyboard = usbkbd_process_keycodes;
+
+	if (console_callback_phone != -1) {
+		static size_t counter = 0;
+		counter++;
+		if (counter > 3) {
+			counter = 0;
+			send_alnum(KC_A, L'a');
+		}
+	}
 
 	usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks, 
@@ -289,4 +346,8 @@
 	fibril_add_ready(fid);
 
+	dev->ops = &keyboard_ops;
+
+	add_device_to_class(dev, "keyboard");
+
 	/*
 	 * Hurrah, device is initialized.
Index: uspace/drv/vhc/hcd.c
===================================================================
--- uspace/drv/vhc/hcd.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/drv/vhc/hcd.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -72,9 +72,4 @@
 
 	/*
-	 * Initialize address management.
-	 */
-	address_init();
-
-	/*
 	 * Initialize our hub and announce its presence.
 	 */
@@ -108,6 +103,17 @@
 	printf(NAME ": virtual USB host controller driver.\n");
 
+	/*
+	 * Initialize address management.
+	 */
+	address_init();
+
+	/*
+	 * Run the transfer scheduler.
+	 */
 	hc_manager();
 
+	/*
+	 * We are also a driver within devman framework.
+	 */
 	return driver_main(&vhc_driver);
 }
Index: uspace/lib/c/generic/async_rel.c
===================================================================
--- uspace/lib/c/generic/async_rel.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/lib/c/generic/async_rel.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -239,5 +239,5 @@
 		 */
 retry:
-		rel_phone = ipc_connect_me_to(key_phone, 0, 0, 0);
+		rel_phone = async_connect_me_to(key_phone, 0, 0, 0);
 		if (rel_phone >= 0) {
 			/* success, do nothing */
Index: uspace/lib/c/generic/device/hw_res.c
===================================================================
--- uspace/lib/c/generic/device/hw_res.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/lib/c/generic/device/hw_res.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -38,27 +38,25 @@
 #include <malloc.h>
 
-bool get_hw_resources(int dev_phone, hw_resource_list_t *hw_resources)
+int get_hw_resources(int dev_phone, hw_resource_list_t *hw_resources)
 {
 	sysarg_t count = 0;
 	int rc = async_req_1_1(dev_phone, DEV_IFACE_ID(HW_RES_DEV_IFACE), GET_RESOURCE_LIST, &count);
 	hw_resources->count = count;
-	if (EOK != rc) {
-		return false;
-	}
+	if (rc != EOK)
+		return rc;
 	
 	size_t size = count * sizeof(hw_resource_t);
 	hw_resources->resources = (hw_resource_t *)malloc(size);
-	if (NULL == hw_resources->resources) {
-		return false;
-	}
+	if (!hw_resources->resources)
+		return ENOMEM;
 	
 	rc = async_data_read_start(dev_phone, hw_resources->resources, size);
-	if (EOK != rc) {
+	if (rc != EOK) {
 		free(hw_resources->resources);
 		hw_resources->resources = NULL;
-		return false;
+		return rc;
 	}
 	 	 
-	return true;	 
+	return EOK;
 }
 
Index: uspace/lib/c/generic/devmap.c
===================================================================
--- uspace/lib/c/generic/devmap.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/lib/c/generic/devmap.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -279,8 +279,8 @@
 	
 	if (flags & IPC_FLAG_BLOCKING) {
-		phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
+		phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
 		    DEVMAP_CONNECT_TO_DEVICE, handle);
 	} else {
-		phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
+		phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
 		    DEVMAP_CONNECT_TO_DEVICE, handle);
 	}
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/lib/c/generic/fibril_synch.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -139,5 +139,4 @@
 static void _fibril_mutex_unlock_unsafe(fibril_mutex_t *fm)
 {
-	assert(fm->counter <= 0);
 	if (fm->counter++ < 0) {
 		link_t *tmp;
@@ -165,7 +164,20 @@
 void fibril_mutex_unlock(fibril_mutex_t *fm)
 {
+	assert(fibril_mutex_is_locked(fm));
 	futex_down(&async_futex);
 	_fibril_mutex_unlock_unsafe(fm);
 	futex_up(&async_futex);
+}
+
+bool fibril_mutex_is_locked(fibril_mutex_t *fm)
+{
+	bool locked = false;
+	
+	futex_down(&async_futex);
+	if (fm->counter <= 0) 
+		locked = true;
+	futex_up(&async_futex);
+	
+	return locked;
 }
 
@@ -230,5 +242,4 @@
 {
 	futex_down(&async_futex);
-	assert(frw->readers || (frw->writers == 1));
 	if (frw->readers) {
 		if (--frw->readers) {
@@ -296,4 +307,5 @@
 void fibril_rwlock_read_unlock(fibril_rwlock_t *frw)
 {
+	assert(fibril_rwlock_is_read_locked(frw));
 	_fibril_rwlock_common_unlock(frw);
 }
@@ -301,5 +313,38 @@
 void fibril_rwlock_write_unlock(fibril_rwlock_t *frw)
 {
+	assert(fibril_rwlock_is_write_locked(frw));
 	_fibril_rwlock_common_unlock(frw);
+}
+
+bool fibril_rwlock_is_read_locked(fibril_rwlock_t *frw)
+{
+	bool locked = false;
+
+	futex_down(&async_futex);
+	if (frw->readers)
+		locked = true;
+	futex_up(&async_futex);
+
+	return locked;
+}
+
+bool fibril_rwlock_is_write_locked(fibril_rwlock_t *frw)
+{
+	bool locked = false;
+
+	futex_down(&async_futex);
+	if (frw->writers) {
+		assert(frw->writers == 1);
+		locked = true;
+	}
+	futex_up(&async_futex);
+
+	return locked;
+}
+
+bool fibril_rwlock_is_locked(fibril_rwlock_t *frw)
+{
+	return fibril_rwlock_is_read_locked(frw) ||
+	    fibril_rwlock_is_write_locked(frw);
 }
 
@@ -314,4 +359,6 @@
 {
 	awaiter_t wdata;
+
+	assert(fibril_mutex_is_locked(fm));
 
 	if (timeout < 0)
Index: uspace/lib/c/include/device/hw_res.h
===================================================================
--- uspace/lib/c/include/device/hw_res.h	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/lib/c/include/device/hw_res.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -95,7 +95,6 @@
 
 
-bool get_hw_resources(int dev_phone, hw_resource_list_t *hw_resources);
-
-bool enable_interrupt(int dev_phone);
+extern int get_hw_resources(int, hw_resource_list_t *);
+extern bool enable_interrupt(int);
 
 
Index: uspace/lib/c/include/fibril_synch.h
===================================================================
--- uspace/lib/c/include/fibril_synch.h	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/lib/c/include/fibril_synch.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -105,4 +105,5 @@
 extern bool fibril_mutex_trylock(fibril_mutex_t *);
 extern void fibril_mutex_unlock(fibril_mutex_t *);
+extern bool fibril_mutex_is_locked(fibril_mutex_t *);
 
 extern void fibril_rwlock_initialize(fibril_rwlock_t *);
@@ -111,4 +112,7 @@
 extern void fibril_rwlock_read_unlock(fibril_rwlock_t *);
 extern void fibril_rwlock_write_unlock(fibril_rwlock_t *);
+extern bool fibril_rwlock_is_read_locked(fibril_rwlock_t *);
+extern bool fibril_rwlock_is_write_locked(fibril_rwlock_t *);
+extern bool fibril_rwlock_is_locked(fibril_rwlock_t *);
 
 extern void fibril_condvar_initialize(fibril_condvar_t *);
Index: uspace/lib/c/include/ipc/kbd.h
===================================================================
--- uspace/lib/c/include/ipc/kbd.h	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/lib/c/include/ipc/kbd.h	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -39,7 +39,8 @@
 
 #include <ipc/ipc.h>
+#include <ipc/dev_iface.h>
 
 typedef enum {
-	KBD_YIELD = IPC_FIRST_USER_METHOD,
+	KBD_YIELD = DEV_FIRST_CUSTOM_METHOD,
 	KBD_RECLAIM
 } kbd_request_t;
Index: uspace/lib/packet/generic/packet_server.c
===================================================================
--- uspace/lib/packet/generic/packet_server.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/lib/packet/generic/packet_server.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -135,6 +135,4 @@
 /** Creates a new packet of dimensions at least as given.
  *
- * Should be used only when the global data are locked.
- *
  * @param[in] length	The total length of the packet, including the header,
  *			the addresses and the data of the packet.
@@ -153,4 +151,6 @@
 	packet_t *packet;
 	int rc;
+
+	assert(fibril_mutex_is_locked(&ps_globals.lock));
 
 	// already locked
@@ -233,6 +233,4 @@
 /** Release the packet and returns it to the appropriate free packet queue.
  *
- * Should be used only when the global data are locked.
- *
  * @param[in] packet	The packet to be released.
  *
@@ -242,4 +240,6 @@
 	int index;
 	int result;
+
+	assert(fibril_mutex_is_locked(&ps_globals.lock));
 
 	for (index = 0; (index < FREE_QUEUES_COUNT - 1) &&
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/srv/devman/devman.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -392,4 +392,5 @@
 	printf(NAME ": create_root_node\n");
 
+	fibril_rwlock_write_lock(&tree->rwlock);
 	node = create_dev_node();
 	if (node != NULL) {
@@ -401,4 +402,5 @@
 		tree->root_node = node;
 	}
+	fibril_rwlock_write_unlock(&tree->rwlock);
 
 	return node != NULL;
@@ -463,6 +465,4 @@
 /** Start a driver
  *
- * The driver's mutex is assumed to be locked.
- *
  * @param drv		The driver's structure.
  * @return		True if the driver's task is successfully spawned, false
@@ -473,4 +473,6 @@
 	int rc;
 
+	assert(fibril_mutex_is_locked(&drv->driver_mutex));
+	
 	printf(NAME ": start_driver '%s'\n", drv->name);
 	
@@ -867,6 +869,4 @@
 /** Find the device node structure of the device witch has the specified handle.
  *
- * Device tree's rwlock should be held at least for reading.
- *
  * @param tree		The device tree where we look for the device node.
  * @param handle	The handle of the device.
@@ -876,5 +876,9 @@
 {
 	unsigned long key = handle;
-	link_t *link = hash_table_find(&tree->devman_devices, &key);
+	link_t *link;
+	
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+	
+	link = hash_table_find(&tree->devman_devices, &key);
 	return hash_table_get_instance(link, node_t, devman_link);
 }
@@ -932,7 +936,4 @@
 /** Insert new device into device tree.
  *
- * The device tree's rwlock should be already held exclusively when calling this
- * function.
- *
  * @param tree		The device tree.
  * @param node		The newly added device node. 
@@ -949,4 +950,5 @@
 	assert(tree != NULL);
 	assert(dev_name != NULL);
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
 	
 	node->name = dev_name;
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/srv/devmap/devmap.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -46,4 +46,5 @@
 #include <str.h>
 #include <ipc/devmap.h>
+#include <assert.h>
 
 #define NAME          "devmap"
@@ -208,13 +209,11 @@
 }
 
-/** Find namespace with given name.
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Find namespace with given name. */
 static devmap_namespace_t *devmap_namespace_find_name(const char *name)
 {
 	link_t *item;
+	
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+	
 	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
 		devmap_namespace_t *namespace =
@@ -229,7 +228,4 @@
 /** Find namespace with given handle.
  *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
  * @todo: use hash table
  *
@@ -238,4 +234,7 @@
 {
 	link_t *item;
+	
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+	
 	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
 		devmap_namespace_t *namespace =
@@ -248,14 +247,12 @@
 }
 
-/** Find device with given name.
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Find device with given name. */
 static devmap_device_t *devmap_device_find_name(const char *ns_name,
     const char *name)
 {
 	link_t *item;
+	
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+	
 	for (item = devices_list.next; item != &devices_list; item = item->next) {
 		devmap_device_t *device =
@@ -271,7 +268,4 @@
 /** Find device with given handle.
  *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
  * @todo: use hash table
  *
@@ -280,4 +274,7 @@
 {
 	link_t *item;
+	
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+	
 	for (item = devices_list.next; item != &devices_list; item = item->next) {
 		devmap_device_t *device =
@@ -290,13 +287,12 @@
 }
 
-/** Create a namespace (if not already present)
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Create a namespace (if not already present). */
 static devmap_namespace_t *devmap_namespace_create(const char *ns_name)
 {
-	devmap_namespace_t *namespace = devmap_namespace_find_name(ns_name);
+	devmap_namespace_t *namespace;
+	
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+	
+	namespace = devmap_namespace_find_name(ns_name);
 	if (namespace != NULL)
 		return namespace;
@@ -323,12 +319,9 @@
 }
 
-/** Destroy a namespace (if it is no longer needed)
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Destroy a namespace (if it is no longer needed). */
 static void devmap_namespace_destroy(devmap_namespace_t *namespace)
 {
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+
 	if (namespace->refcnt == 0) {
 		list_remove(&(namespace->namespaces));
@@ -339,37 +332,28 @@
 }
 
-/** Increase namespace reference count by including device
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Increase namespace reference count by including device. */
 static void devmap_namespace_addref(devmap_namespace_t *namespace,
     devmap_device_t *device)
 {
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+
 	device->namespace = namespace;
 	namespace->refcnt++;
 }
 
-/** Decrease namespace reference count
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Decrease namespace reference count. */
 static void devmap_namespace_delref(devmap_namespace_t *namespace)
 {
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+
 	namespace->refcnt--;
 	devmap_namespace_destroy(namespace);
 }
 
-/** Unregister device and free it
- *
- * The devices_list_mutex should be already held when
- * calling this function.
- *
- */
+/** Unregister device and free it. */
 static void devmap_device_unregister_core(devmap_device_t *device)
 {
+	assert(fibril_mutex_is_locked(&devices_list_mutex));
+
 	devmap_namespace_delref(device->namespace);
 	list_remove(&(device->devices));
Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -60,7 +60,8 @@
 typedef struct {
 	devmap_handle_t handle;
-	int phone;
+	int phone;		/**< When < 0, the structure is incomplete. */
 	size_t refcount;
 	link_t link;
+	fibril_condvar_t cv;	/**< Broadcast when completed. */
 } device_t;
 
@@ -227,7 +228,9 @@
 			[DEVICES_KEY_HANDLE] = (unsigned long) node->handle
 		};
-		
+		link_t *lnk;
+
 		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
+restart:
+		lnk = hash_table_find(&devices, key);
 		if (lnk == NULL) {
 			device_t *dev = (device_t *) malloc(sizeof(device_t));
@@ -237,18 +240,60 @@
 			}
 			
+			dev->handle = node->handle;
+			dev->phone = -1;	/* mark as incomplete */
+			dev->refcount = 1;
+			fibril_condvar_initialize(&dev->cv);
+
+			/*
+			 * Insert the incomplete device structure so that other
+			 * fibrils will not race with us when we drop the mutex
+			 * below.
+			 */
+			hash_table_insert(&devices, key, &dev->link);
+
+			/*
+			 * Drop the mutex to allow recursive devfs requests.
+			 */
+			fibril_mutex_unlock(&devices_mutex);
+
 			int phone = devmap_device_connect(node->handle, 0);
+
+			fibril_mutex_lock(&devices_mutex);
+
+			/*
+			 * Notify possible waiters about this device structure
+			 * being completed (or destroyed).
+			 */
+			fibril_condvar_broadcast(&dev->cv);
+
 			if (phone < 0) {
+				/*
+				 * Connecting failed, need to remove the
+				 * entry and free the device structure.
+				 */
+				hash_table_remove(&devices, key, DEVICES_KEYS);
 				fibril_mutex_unlock(&devices_mutex);
+
 				free(dev);
 				return ENOENT;
 			}
 			
-			dev->handle = node->handle;
+			/* Set the correct phone. */
 			dev->phone = phone;
-			dev->refcount = 1;
-			
-			hash_table_insert(&devices, key, &dev->link);
 		} else {
 			device_t *dev = hash_table_get_instance(lnk, device_t, link);
+
+			if (dev->phone < 0) {
+				/*
+				 * Wait until the device structure is completed
+				 * and start from the beginning as the device
+				 * structure might have entirely disappeared
+				 * while we were not holding the mutex in
+				 * fibril_condvar_wait().
+				 */
+				fibril_condvar_wait(&dev->cv, &devices_mutex);
+				goto restart;
+			}
+
 			dev->refcount++;
 		}
@@ -564,4 +609,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		
 		ipc_callid_t callid;
@@ -627,4 +673,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		
 		ipc_callid_t callid;
@@ -696,4 +743,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		dev->refcount--;
 		
@@ -743,4 +791,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		
 		/* Make a request at the driver */
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/srv/hid/console/console.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -317,6 +317,7 @@
 static void change_console(console_t *cons)
 {
-	if (cons == active_console)
+	if (cons == active_console) {
 		return;
+	}
 	
 	fb_pending_flush();
@@ -458,6 +459,7 @@
 			if (IPC_GET_ARG1(call) == 1) {
 				int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
-				if (newcon != -1)
+				if (newcon != -1) {
 					change_console(&consoles[newcon]);
+				}
 			}
 			retval = 0;
@@ -710,28 +712,81 @@
 }
 
-static bool console_init(char *input)
-{
-	/* Connect to input device */
-	int input_fd = open(input, O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": Failed opening %s\n", input);
-		return false;
-	}
-	
-	kbd_phone = fd_phone(input_fd);
-	if (kbd_phone < 0) {
+static int connect_keyboard(char *path)
+{
+	int fd = open(path, O_RDONLY);
+	if (fd < 0) {
+		return fd;
+	}
+	
+	int phone = fd_phone(fd);
+	if (phone < 0) {
 		printf(NAME ": Failed to connect to input device\n");
-		return false;
+		return phone;
 	}
 	
 	/* NB: The callback connection is slotted for removal */
 	sysarg_t phonehash;
-	if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
+	int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, SERVICE_CONSOLE,
+	    0, 0, NULL, NULL, NULL, NULL, &phonehash);
+	if (rc != EOK) {
 		printf(NAME ": Failed to create callback from input device\n");
+		return rc;
+	}
+	
+	async_new_connection(phonehash, 0, NULL, keyboard_events);
+
+	printf(NAME ": we got a hit (new keyboard \"%s\").\n", path);
+
+	return phone;
+}
+
+
+static int check_new_keyboards(void *arg)
+{
+	char *class_name = (char *) arg;
+
+	int index = 1;
+
+	while (true) {
+		async_usleep(1 * 500 * 1000);
+		char *path;
+		int rc = asprintf(&path, "/dev/class/%s\\%d", class_name, index);
+		if (rc < 0) {
+			continue;
+		}
+		rc = 0;
+		rc = connect_keyboard(path);
+		if (rc > 0) {
+			/* We do not allow unplug. */
+			index++;
+		}
+
+		free(path);
+	}
+
+	return EOK;
+}
+
+
+/** Start a fibril monitoring hot-plugged keyboards.
+ */
+static void check_new_keyboards_in_background()
+{
+	fid_t fid = fibril_create(check_new_keyboards, (void *)"keyboard");
+	if (!fid) {
+		printf(NAME ": failed to create hot-plug-watch fibril.\n");
+		return;
+	}
+	fibril_add_ready(fid);
+}
+
+static bool console_init(char *input)
+{
+	/* Connect to input device */
+	kbd_phone = connect_keyboard(input);
+	if (kbd_phone < 0) {
 		return false;
 	}
-	
-	async_new_connection(phonehash, 0, NULL, keyboard_events);
-	
+
 	/* Connect to mouse device */
 	mouse_phone = -1;
@@ -749,4 +804,5 @@
 	}
 	
+	sysarg_t phonehash;
 	if (ipc_connect_to_me(mouse_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
 		printf(NAME ": Failed to create callback from mouse device\n");
@@ -841,4 +897,7 @@
 	async_set_interrupt_received(interrupt_received);
 	
+	/* Start fibril for checking on hot-plugged keyboards. */
+	check_new_keyboards_in_background();
+
 	return true;
 }
@@ -860,5 +919,5 @@
 	if (!console_init(argv[1]))
 		return -1;
-	
+
 	printf(NAME ": Accepting connections\n");
 	async_manager();
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -2085,6 +2085,7 @@
 	if (!fibril) {
 		free(operation_timeout);
-		return EPARTY;	/* FIXME: use another EC */
-	}
+		return ENOMEM;
+	}
+
 //      fibril_mutex_lock(&socket_data->operation.mutex);
 	/* Start the timeout fibril */
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision e0803324eab9f3efacade7afd1697112f2705f6e)
+++ uspace/srv/vfs/vfs_lookup.c	(revision 5f7d96e3d9361dc779580070cbfc7c3e0707b35f)
@@ -179,6 +179,9 @@
 	fibril_mutex_unlock(&plb_mutex);
 	
-	if (((int) rc < EOK) || (!result))
+	if ((int) rc < EOK)
 		return (int) rc;
+
+	if (!result)
+		return EOK;
 	
 	result->triplet.fs_handle = (fs_handle_t) rc;
