Index: .gitignore
===================================================================
--- .gitignore	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ .gitignore	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -22,4 +22,8 @@
 /config.h
 /cscope.out
+doxygen/doxygen.cfg
+doxygen/doxygen.cfg.gen
+doxygen/html/
+doxygen/latex/
 /hdisk.img
 /image.iso
@@ -248,4 +252,5 @@
 uspace/dist/logo.tga
 uspace/dist/srv/cdfs
+uspace/dist/srv/chardev-test
 uspace/dist/srv/clipboard
 uspace/dist/srv/compositor
@@ -420,4 +425,19 @@
 uspace/srv/ns/ns
 uspace/srv/taskmon/taskmon
+uspace/srv/test/chardev-test/chardev-test
 uspace/srv/vfs/vfs
 uspace/srv/volsrv/volsrv
+tools/amd64-unknown-elf
+tools/arm-linux-gnueabi
+tools/i686-pc-linux-gnu
+tools/ia64-pc-linux-gnu
+tools/mips-linux-gnu
+tools/mips64el-linux-gnu
+tools/mipsel-linux-gnu
+tools/ppc-linux-gnu
+tools/ppc64-linux-gnu
+tools/riscv64-unknown-linux-gnu
+tools/sparc64-linux-gnu
+tools/binutils-*.tar.bz2
+tools/gcc-*.tar.bz2
+tools/gdb-*.tar.gz
Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ HelenOS.config	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -397,7 +397,4 @@
 ! [PLATFORM=sparc64] CONFIG_VIRT_IDX_DCACHE (y/n)
 
-% Simics SMP Hack
-! [PROCESSOR=sun4v&CONFIG_SMP=y] CONFIG_SIMICS_SMP_HACK (n/y)
-
 % Support for userspace debuggers
 ! CONFIG_UDEBUG (y/n)
Index: Makefile
===================================================================
--- Makefile	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -73,4 +73,7 @@
 	find abi kernel boot uspace -type f -regex '^.*\.[ch]$$' | xargs $(FORMAT) -i -sort-includes -style=file
 
+doxy:
+	$(MAKE) -r -C doxygen
+
 # Pre-integration build check
 check: $(CHECK)
@@ -120,4 +123,5 @@
 	$(MAKE) -r -C uspace clean
 	$(MAKE) -r -C boot clean
+	$(MAKE) -r -C doxygen clean
 
 -include Makefile.local
Index: abi/include/abi/cap.h
===================================================================
--- abi/include/abi/cap.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ abi/include/abi/cap.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_CAP_H_
+#define ABI_CAP_H_
+
+#define CAP_NIL		0
+
+typedef int cap_handle_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/abi/errno.h
===================================================================
--- abi/include/abi/errno.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ abi/include/abi/errno.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,11 +41,12 @@
  */
 
-#define EOK             0   /* No error */
-#define ENOENT         -1   /* No such entry */
-#define ENOMEM         -2   /* Not enough memory */
-#define ELIMIT         -3   /* Limit exceeded */
-#define EREFUSED       -4   /* Connection refused */
-#define EFORWARD       -5   /* Forward error */
-#define EPERM          -6   /* Permission denied */
+typedef enum {
+	EOK           =  0,   /* No error */
+	ENOENT        = -1,   /* No such entry */
+	ENOMEM        = -2,   /* Not enough memory */
+	ELIMIT        = -3,   /* Limit exceeded */
+	EREFUSED      = -4,   /* Connection refused */
+	EFORWARD      = -5,   /* Forward error */
+	EPERM         = -6,   /* Permission denied */
 
 /*
@@ -54,5 +55,5 @@
  * Used by answerbox to close the connection.
  */
-#define EHANGUP        -7
+	EHANGUP       = -7,
 
 /*
@@ -60,15 +61,47 @@
  * receiving the call.
  */
-#define EPARTY         -8
+	EPARTY        = -8,
 
-#define EEXIST         -9   /* Entry already exists */
-#define EBADMEM        -10  /* Bad memory pointer */
-#define ENOTSUP        -11  /* Not supported */
-#define EADDRNOTAVAIL  -12  /* Address not available. */
-#define ETIMEOUT       -13  /* Timeout expired */
-#define EINVAL         -14  /* Invalid value */
-#define EBUSY          -15  /* Resource is busy */
-#define EOVERFLOW      -16  /* The result does not fit its size. */
-#define EINTR          -17  /* Operation was interrupted. */
+	EEXIST        = -9,   /* Entry already exists */
+	EBADMEM       = -10,  /* Bad memory pointer */
+	ENOTSUP       = -11,  /* Not supported */
+	EADDRNOTAVAIL = -12,  /* Address not available. */
+	ETIMEOUT      = -13,  /* Timeout expired */
+	EINVAL        = -14,  /* Invalid value */
+	EBUSY         = -15,  /* Resource is busy */
+	EOVERFLOW     = -16,  /* The result does not fit its size. */
+	EINTR         = -17,  /* Operation was interrupted. */
+
+	EMFILE        = -18,
+	ENAMETOOLONG  = -256,
+	EISDIR        = -257,
+	ENOTDIR       = -258,
+	ENOSPC        = -259,
+	ENOTEMPTY     = -261,
+	EBADF         = -262,
+	EDOM          = -263,
+	ERANGE        = -264,
+	EXDEV         = -265,
+	EIO           = -266,
+	EMLINK        = -267,
+	ENXIO         = -268,
+	ENOFS         = -269,
+
+/** Bad checksum. */
+	EBADCHECKSUM  = -300,
+
+/** USB: stalled operation. */
+	ESTALL        = -301,
+
+/** Empty resource (no data). */
+	EEMPTY        = -302,
+
+/** Negative acknowledgment. */
+	ENAK          = -303,
+
+/** The requested operation was not performed. Try again later. */
+	EAGAIN        = -11002,
+} errno_t;
+
 
 #endif
Index: abi/include/abi/ipc/ipc.h
===================================================================
--- abi/include/abi/ipc/ipc.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ abi/include/abi/ipc/ipc.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,5 +38,5 @@
 /** Length of data being transfered with IPC call
  *
- * The uspace may not be able to utilize full length
+ * The uspace may not be able to utilize the full length
  *
  */
@@ -49,5 +49,5 @@
 
 /** This is answer to a call */
-#define IPC_CALL_ANSWERED  (1 << 0)
+#define IPC_CALL_ANSWERED        (1 << 0)
 
 /** Answer will not be passed to userspace, will be discarded */
@@ -55,8 +55,8 @@
 
 /** Call was forwarded */
-#define IPC_CALL_FORWARDED  (1 << 2)
+#define IPC_CALL_FORWARDED       (1 << 2)
 
 /** Interrupt notification */
-#define IPC_CALL_NOTIF  (1 << 3)
+#define IPC_CALL_NOTIF           (1 << 3)
 
 /**
@@ -65,21 +65,4 @@
  */
 #define DATA_XFER_LIMIT  (64 * 1024)
-
-
-/** Bits used in call hashes.
- *
- * The addresses are aligned at least to 4 that is why we can use the 2 least
- * significant bits of the call address.
- *
- */
-
-/** Type of this call is 'answer' */
-#define IPC_CALLID_ANSWERED  1
-
-/** Type of this call is 'notification' */
-#define IPC_CALLID_NOTIFICATION  2
-
-/* Return values from sys_ipc_call_async(). */
-#define IPC_CALLRET_FATAL      -1
 
 /* Macros for manipulating calling data */
Index: abi/include/abi/ipc/methods.h
===================================================================
--- abi/include/abi/ipc/methods.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ abi/include/abi/ipc/methods.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,6 +36,8 @@
 #define ABI_IPC_METHODS_H_
 
+#include <abi/cap.h>
+
 /* Well known phone descriptors */
-#define PHONE_NS  0
+#define PHONE_NS  (CAP_NIL + 1)
 
 /** Kernel IPC interfaces
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ boot/Makefile.common	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -123,4 +123,5 @@
 	$(USPACE_PATH)/srv/net/udp/udp \
 	$(USPACE_PATH)/srv/taskmon/taskmon \
+	$(USPACE_PATH)/srv/test/chardev-test/chardev-test \
 	$(USPACE_PATH)/srv/volsrv/volsrv
 
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ boot/arch/amd64/Makefile.inc	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,4 +35,5 @@
 	intctl/i8259 \
 	platform/pc \
+	block/ata_bd \
 	bus/pci/pciintel \
 	bus/isa \
Index: contrib/qemu/build-from-scratch.sh
===================================================================
--- contrib/qemu/build-from-scratch.sh	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ contrib/qemu/build-from-scratch.sh	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -29,5 +29,5 @@
 #
 
-VERSION=2.10.0
+VERSION=2.11.0
 BASENAME=qemu-${VERSION}
 BASENAME_MASTER=qemu-master
@@ -36,5 +36,5 @@
 URL=http://wiki.qemu-project.org/download/${TARBALL}
 REPO=git://git.qemu.org/qemu.git
-MD5="ca73441de73a9b52c6c49c97190d2185"
+MD5="335994a755bc655e88a87aeb36bfc0b9"
 
 OPENSPARC_TARBALL="OpenSPARCT1_Arch.1.5.tar.bz2"
Index: doxygen/Makefile
===================================================================
--- doxygen/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ doxygen/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2017 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.
+#
+
+cfg_file = doxygen.cfg
+gen_cfg = doxygen.cfg.gen
+patch_file = doxygen.cfg.diff
+output_dirs = latex html
+
+all: doxygen.cfg
+	doxygen $^
+
+clean:
+	rm -f $(gen_cfg) $(cfg_file)
+	rm -rf $(output_dirs)
+
+$(cfg_file): $(gen_cfg)
+	cp $^ $@
+	patch $@ $(patch_file)
+
+$(gen_cfg):
+	doxygen -g $@
Index: doxygen/doxygen.cfg.diff
===================================================================
--- doxygen/doxygen.cfg.diff	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ doxygen/doxygen.cfg.diff	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,38 @@
+--- doxygen.cfg.gen	2017-11-30 15:25:41.038184899 +0100
++++ doxygen.cfg	2017-11-30 15:31:19.536034077 +0100
+@@ -32,7 +32,7 @@
+ # title of most generated pages and in a few other places.
+ # The default value is: My Project.
+ 
+-PROJECT_NAME           = "My Project"
++PROJECT_NAME           = "HelenOS"
+ 
+ # The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+ # could be handy for archiving the generated documentation or if some version
+@@ -44,7 +44,7 @@
+ # for a project that appears at the top of each page and should give viewer a
+ # quick idea about the purpose of the project. Keep the description short.
+ 
+-PROJECT_BRIEF          =
++PROJECT_BRIEF          = " HelenOS is a portable microkernel-based multiserver operating system designed and implemented from scratch."
+ 
+ # With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+ # in the documentation. The maximum height of the logo should not exceed 55
+@@ -790,7 +790,7 @@
+ # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+ # Note: If this tag is empty the current directory is searched.
+ 
+-INPUT                  =
++INPUT                  = ..
+ 
+ # This tag can be used to specify the character encoding of the source files
+ # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+@@ -864,7 +864,7 @@
+ # be searched for input files as well.
+ # The default value is: NO.
+ 
+-RECURSIVE              = NO
++RECURSIVE              = YES
+ 
+ # The EXCLUDE tag can be used to specify files and/or directories that should be
+ # excluded from the INPUT source files. This way you can easily exclude a
Index: kernel/arch/ia32/src/smp/mps.c
===================================================================
--- kernel/arch/ia32/src/smp/mps.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/arch/ia32/src/smp/mps.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -91,5 +91,5 @@
 		return false;
 	
-	return (bool) ((processor_entries[i].cpu_flags & 0x01) == 0x01);
+	return ((processor_entries[i].cpu_flags & 0x01) == 0x01);
 }
 
@@ -98,5 +98,5 @@
 	assert(i < processor_entry_cnt);
 	
-	return (bool) ((processor_entries[i].cpu_flags & 0x02) == 0x02);
+	return ((processor_entries[i].cpu_flags & 0x02) == 0x02);
 }
 
Index: kernel/arch/sparc64/include/arch/drivers/niagara_buf.h
===================================================================
--- kernel/arch/sparc64/include/arch/drivers/niagara_buf.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ kernel/arch/sparc64/include/arch/drivers/niagara_buf.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2008 Pavel Rimsky
+ * Copyright (c) 2017 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 sparc64
+ * @{
+ */
+/**
+ * @file
+ * @brief Niagara input/output buffer shared between kernel and user space
+ */
+
+#ifdef KERNEL
+#include <mm/as.h>
+#else
+#include <as.h>
+#endif
+
+#include <stdint.h>
+
+#define OUTPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
+
+typedef struct {
+	uint64_t read_ptr;
+	uint64_t write_ptr;
+	char data[OUTPUT_BUFFER_SIZE];
+} __attribute__ ((packed)) niagara_output_buffer_t;
+
+#define INPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
+
+typedef struct {
+	uint64_t write_ptr;
+	uint64_t read_ptr;
+	char data[INPUT_BUFFER_SIZE];
+} __attribute__ ((packed)) niagara_input_buffer_t;
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/drivers/niagara.c
===================================================================
--- kernel/arch/sparc64/src/drivers/niagara.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/arch/sparc64/src/drivers/niagara.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -42,4 +42,5 @@
 #include <arch.h>
 #include <mm/slab.h>
+#include <arch/drivers/niagara_buf.h>
 #include <arch/drivers/kbd.h>
 #include <arch/sun4v/hypercall.h>
@@ -81,11 +82,6 @@
  * buffer definition follows.
  */
-#define OUTPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
-
-static volatile struct {
-	uint64_t read_ptr;
-	uint64_t write_ptr;
-	char data[OUTPUT_BUFFER_SIZE];
-} __attribute__ ((packed)) __attribute__ ((aligned(PAGE_SIZE))) output_buffer;
+static volatile niagara_output_buffer_t __attribute__ ((aligned(PAGE_SIZE)))
+    output_buffer;
 
 static parea_t outbuf_parea;
@@ -94,11 +90,6 @@
  * Analogous to the output_buffer, see the previous definition.
  */
-#define INPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
-
-static volatile struct {
-	uint64_t write_ptr;
-	uint64_t read_ptr;
-	char data[INPUT_BUFFER_SIZE];
-} __attribute__ ((packed)) __attribute__ ((aligned(PAGE_SIZE))) input_buffer;
+static volatile niagara_input_buffer_t __attribute__ ((aligned(PAGE_SIZE)))
+    input_buffer;
 
 static parea_t inbuf_parea;
Index: kernel/arch/sparc64/src/smp/sun4v/smp.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4v/smp.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/arch/sparc64/src/smp/sun4v/smp.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -81,66 +81,4 @@
 unsigned int max_core_strands = 0;
 
-#ifdef CONFIG_SIMICS_SMP_HACK
-/**
- * Copies a piece of HelenOS code to the place where OBP had its IPI handler.
- * By sending an IPI by the BSP to the AP the code will be executed.
- * The code will jump to the first instruction of the kernel. This is
- * a workaround how to make APs execute HelenOS code on Simics.
- */
-static void simics_smp_hack_init(void) {
-	asm volatile (
-		"setx temp_cpu_mondo_handler, %g4, %g6 \n"
-		"setx 0x80200f80, %g4, %g7 \n"
-
-		"ldx [%g6], %g4 \n"
-		"stxa %g4, [%g7] 0x14 \n"
-		"membar #Sync \n"
-
-		"add %g7, 0x8, %g7 \n"
-		"ldx [%g6 + 0x8], %g4 \n"
-		"stxa %g4, [%g7] 0x14 \n"
-		"membar #Sync \n"
-
-		"add %g7, 0x8, %g7 \n"
-		"ldx [%g6 + 0x10], %g4 \n"
-		"stxa %g4, [%g7] 0x14 \n"
-		"membar #Sync \n"
-
-		"add %g7, 0x8, %g7 \n"
-		"ldx [%g6 + 0x18], %g4 \n"
-		"stxa %g4, [%g7] 0x14 \n"
-		"membar #Sync \n"
-
-		"add %g7, 0x8, %g7 \n"
-		"ldx [%g6 + 0x20], %g4 \n"
-		"stxa %g4, [%g7] 0x14 \n"
-		"membar #Sync \n"
-
-		"add %g7, 0x8, %g7 \n"
-		"ldx [%g6 + 0x28], %g4 \n"
-		"stxa %g4, [%g7] 0x14 \n"
-		"membar #Sync \n"
-
-		"add %g7, 0x8, %g7 \n"
-		"ldx [%g6 + 0x30], %g4 \n"
-		"stxa %g4, [%g7] 0x14 \n"
-		"membar #Sync \n"
-
-		"add %g7, 0x8, %g7 \n"
-		"ldx [%g6 + 0x38], %g4 \n"
-		"stxa %g4, [%g7] 0x14 \n"
-		"membar #Sync \n"
-
-		"add %g7, 0x8, %g7 \n"
-		"ldx [%g6 + 0x40], %g4 \n"
-		"stxa %g4, [%g7] 0x14 \n"
-		"membar #Sync \n"
-
-		"flush %i7"
-
-		);
-}
-#endif
-
 #if 0
 /**
@@ -372,7 +310,4 @@
 {
 	detect_execution_units();
-#ifdef CONFIG_SIMICS_SMP_HACK
-	simics_smp_hack_init();
-#endif
 }
 
Index: kernel/arch/sparc64/src/sun4v/start.S
===================================================================
--- kernel/arch/sparc64/src/sun4v/start.S	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/arch/sparc64/src/sun4v/start.S	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -309,21 +309,4 @@
 	ba,a %xcc, 0b
 
-.align 8
-SYMBOL(temp_cpu_mondo_handler)
-
-	set 0x3c, %o0
-	set 0x15, %o5
-	ta 0x80
-
-	mov 0, %o0
-	setx before_ap_boots, %g1, %o1
-	setx 0x80400000, %g1, %o2
-	add %o1, %o2, %o1
-	__HYPERCALL_FAST(MMU_ENABLE)
-
-before_ap_boots:
-	setx 0x80400000, %g1, %o0
-	ba,a %xcc, kernel_image_start
-
 .section K_DATA_START, "aw", @progbits
 
Index: kernel/generic/include/cap/cap.h
===================================================================
--- kernel/generic/include/cap/cap.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/include/cap/cap.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,4 +36,5 @@
 #define KERN_CAP_H_
 
+#include <abi/cap.h>
 #include <typedefs.h>
 #include <adt/list.h>
@@ -44,6 +45,4 @@
 #include <atomic.h>
 
-typedef int cap_handle_t;
-
 typedef enum {
 	CAP_STATE_FREE,
@@ -53,12 +52,15 @@
 
 typedef enum {
+	KOBJECT_TYPE_CALL,
+	KOBJECT_TYPE_IRQ,
 	KOBJECT_TYPE_PHONE,
-	KOBJECT_TYPE_IRQ,
 	KOBJECT_TYPE_MAX
 } kobject_type_t;
 
 struct task;
+
+struct call;
+struct irq;
 struct phone;
-struct irq;
 
 struct kobject;
@@ -79,6 +81,7 @@
 	union {
 		void *raw;
+		struct call *call;
+		struct irq *irq;
 		struct phone *phone;
-		struct irq *irq;
 	};
 } kobject_t;
Index: kernel/generic/include/ddi/irq.h
===================================================================
--- kernel/generic/include/ddi/irq.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/include/ddi/irq.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -132,5 +132,5 @@
 extern hash_table_t irq_uspace_hash_table;
 
-extern slab_cache_t *irq_slab;
+extern slab_cache_t *irq_cache;
 
 extern inr_t last_inr;
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/include/ipc/ipc.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -106,7 +106,15 @@
 	/** Phone which made or last masqueraded this call. */
 	phone_t *phone;
+	/** Flags */
+	unsigned flags;
+	/** User-defined label */
+	sysarg_t label;
+	/** Capability handle */
+	cap_handle_t cap_handle;
 } ipc_data_t;
 
-typedef struct {
+typedef struct call {
+	kobject_t *kobject;
+
 	/**
 	 * Task link.
@@ -115,6 +123,4 @@
 	 */
 	link_t ta_link;
-
-	atomic_t refcnt;
 
 	/** Answerbox link. */
@@ -169,5 +175,5 @@
 } call_t;
 
-extern slab_cache_t *phone_slab;
+extern slab_cache_t *phone_cache;
 
 extern answerbox_t *ipc_phone_0;
Index: kernel/generic/include/ipc/ipcrsc.h
===================================================================
--- kernel/generic/include/ipc/ipcrsc.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/include/ipc/ipcrsc.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,5 +40,4 @@
 #include <cap/cap.h>
 
-extern call_t *get_call(sysarg_t);
 extern cap_handle_t phone_alloc(task_t *);
 extern bool phone_connect(cap_handle_t, answerbox_t *);
Index: kernel/generic/include/ipc/irq.h
===================================================================
--- kernel/generic/include/ipc/irq.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/include/ipc/irq.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -51,5 +51,6 @@
 extern void ipc_irq_top_half_handler(irq_t *);
 
-extern int ipc_irq_subscribe(answerbox_t *, inr_t, sysarg_t, irq_code_t *);
+extern int ipc_irq_subscribe(answerbox_t *, inr_t, sysarg_t, irq_code_t *,
+    cap_handle_t *);
 extern int ipc_irq_unsubscribe(answerbox_t *, int);
 
Index: kernel/generic/include/ipc/kbox.h
===================================================================
--- kernel/generic/include/ipc/kbox.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/include/ipc/kbox.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -50,5 +50,5 @@
 } kbox_t;
 
-extern int ipc_connect_kbox(task_id_t);
+extern int ipc_connect_kbox(task_id_t, cap_handle_t *);
 extern void ipc_kbox_cleanup(void);
 
Index: kernel/generic/include/ipc/sysipc.h
===================================================================
--- kernel/generic/include/ipc/sysipc.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/include/ipc/sysipc.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,5 +44,5 @@
 extern sysarg_t sys_ipc_call_async_fast(sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, sysarg_t);
-extern sysarg_t sys_ipc_call_async_slow(sysarg_t, ipc_data_t *);
+extern sysarg_t sys_ipc_call_async_slow(sysarg_t, ipc_data_t *, sysarg_t);
 extern sysarg_t sys_ipc_answer_fast(sysarg_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t);
@@ -56,18 +56,8 @@
 extern sysarg_t sys_ipc_hangup(sysarg_t);
 
-extern sysarg_t sys_ipc_irq_subscribe(inr_t, sysarg_t, irq_code_t *);
+extern sysarg_t sys_ipc_irq_subscribe(inr_t, sysarg_t, irq_code_t *, cap_handle_t *);
 extern sysarg_t sys_ipc_irq_unsubscribe(sysarg_t);
 
-#ifdef __32_BITS__
-
-extern sysarg_t sys_ipc_connect_kbox(sysarg64_t *);
-
-#endif  /* __32_BITS__ */
-
-#ifdef __64_BITS__
-
-extern sysarg_t sys_ipc_connect_kbox(sysarg_t);
-
-#endif  /* __64_BITS__ */
+extern sysarg_t sys_ipc_connect_kbox(task_id_t *, cap_handle_t *);
 
 #endif
Index: kernel/generic/include/log.h
===================================================================
--- kernel/generic/include/log.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/include/log.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -52,5 +52,5 @@
 
 extern sysarg_t sys_klog(sysarg_t, void *buf, size_t size,
-    sysarg_t level);
+    sysarg_t level, size_t *uspace_nread);
 
 #endif /* KERN_LOG_H_ */
Index: kernel/generic/include/proc/thread.h
===================================================================
--- kernel/generic/include/proc/thread.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/include/proc/thread.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -272,5 +272,5 @@
 
 /** Fpu context slab cache. */
-extern slab_cache_t *fpu_context_slab;
+extern slab_cache_t *fpu_context_cache;
 
 /* Thread syscall prototypes. */
Index: kernel/generic/include/udebug/udebug_ops.h
===================================================================
--- kernel/generic/include/udebug/udebug_ops.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/include/udebug/udebug_ops.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,6 +37,9 @@
 
 #include <ipc/ipc.h>
+#include <proc/thread.h>
+#include <stdbool.h>
+#include <stddef.h>
 
-int udebug_begin(call_t *call);
+int udebug_begin(call_t *call, bool *active);
 int udebug_end(void);
 int udebug_set_evmask(udebug_evmask_t mask);
Index: kernel/generic/src/adt/btree.c
===================================================================
--- kernel/generic/src/adt/btree.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/adt/btree.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -55,5 +55,5 @@
 #include <trace.h>
 
-static slab_cache_t *btree_node_slab;
+static slab_cache_t *btree_node_cache;
 
 #define ROOT_NODE(n)   (!(n)->parent)
@@ -71,5 +71,5 @@
 void btree_init(void)
 {
-	btree_node_slab = slab_cache_create("btree_node_t",
+	btree_node_cache = slab_cache_create("btree_node_t",
 	    sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED);
 }
@@ -109,5 +109,5 @@
 {
 	list_initialize(&t->leaf_list);
-	t->root = (btree_node_t *) slab_alloc(btree_node_slab, 0);
+	t->root = (btree_node_t *) slab_alloc(btree_node_cache, 0);
 	node_initialize(t->root);
 	list_append(&t->root->leaf_link, &t->leaf_list);
@@ -130,5 +130,5 @@
 	}
 	
-	slab_free(btree_node_slab, root);
+	slab_free(btree_node_cache, root);
 }
 
@@ -516,5 +516,5 @@
 	 * Allocate and initialize new right sibling.
 	 */
-	rnode = (btree_node_t *) slab_alloc(btree_node_slab, 0);
+	rnode = (btree_node_t *) slab_alloc(btree_node_cache, 0);
 	node_initialize(rnode);
 	rnode->parent = node->parent;
@@ -595,5 +595,5 @@
 			 * We split the root node. Create new root.
 			 */
-			t->root = (btree_node_t *) slab_alloc(btree_node_slab, 0);
+			t->root = (btree_node_t *) slab_alloc(btree_node_cache, 0);
 			node->parent = t->root;
 			rnode->parent = t->root;
@@ -779,5 +779,5 @@
 			t->root = node->subtree[0];
 			t->root->parent = NULL;
-			slab_free(btree_node_slab, node);
+			slab_free(btree_node_cache, node);
 		} else {
 			/*
@@ -838,5 +838,5 @@
 		idx = find_key_by_subtree(parent, rnode, true);
 		assert((int) idx != -1);
-		slab_free(btree_node_slab, rnode);
+		slab_free(btree_node_cache, rnode);
 		_btree_remove(t, parent->key[idx], parent);
 	}
Index: kernel/generic/src/cap/cap.c
===================================================================
--- kernel/generic/src/cap/cap.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/cap/cap.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,4 +41,5 @@
  * A kernel object (kobject_t) encapsulates one of the following raw objects:
  *
+ * - IPC call
  * - IPC phone
  * - IRQ object
@@ -73,4 +74,5 @@
 
 #include <cap/cap.h>
+#include <abi/cap.h>
 #include <proc/task.h>
 #include <synch/mutex.h>
@@ -81,7 +83,9 @@
 #include <stdint.h>
 
-#define MAX_CAPS	INT_MAX
-
-static slab_cache_t *cap_slab;
+#define CAPS_START	(CAP_NIL + 1)
+#define CAPS_SIZE	(INT_MAX - CAPS_START)
+#define CAPS_LAST	(CAPS_SIZE - 1)
+
+static slab_cache_t *cap_cache;
 
 static size_t caps_hash(const ht_link_t *item)
@@ -112,5 +116,5 @@
 void caps_init(void)
 {
-	cap_slab = slab_cache_create("cap_t", sizeof(cap_t), 0, NULL,
+	cap_cache = slab_cache_create("cap_t", sizeof(cap_t), 0, NULL,
 	    NULL, 0);
 }
@@ -129,5 +133,5 @@
 	if (!task->cap_info->handles)
 		goto error_handles;
-	if (!ra_span_add(task->cap_info->handles, 0, MAX_CAPS))
+	if (!ra_span_add(task->cap_info->handles, CAPS_START, CAPS_SIZE))
 		goto error_span;
 	if (!hash_table_create(&task->cap_info->caps, 0, 0, &caps_ops))
@@ -220,5 +224,5 @@
 	assert(mutex_locked(&task->cap_info->lock));
 
-	if ((handle < 0) || (handle >= MAX_CAPS))
+	if ((handle < CAPS_START) || (handle > CAPS_LAST))
 		return NULL;
 	ht_link_t *link = hash_table_find(&task->cap_info->caps, &handle);
@@ -273,5 +277,5 @@
 	 */
 	if (!cap) {
-		cap = slab_alloc(cap_slab, FRAME_ATOMIC);
+		cap = slab_alloc(cap_cache, FRAME_ATOMIC);
 		if (!cap) {
 			mutex_unlock(&task->cap_info->lock);
@@ -280,5 +284,5 @@
 		uintptr_t hbase;
 		if (!ra_alloc(task->cap_info->handles, 1, 1, &hbase)) {
-			slab_free(cap_slab, cap);
+			slab_free(cap_cache, cap);
 			mutex_unlock(&task->cap_info->lock);
 			return ENOMEM;
@@ -357,6 +361,6 @@
 void cap_free(task_t *task, cap_handle_t handle)
 {
-	assert(handle >= 0);
-	assert(handle < MAX_CAPS);
+	assert(handle >= CAPS_START);
+	assert(handle <= CAPS_LAST);
 
 	mutex_lock(&task->cap_info->lock);
@@ -367,5 +371,5 @@
 	hash_table_remove_item(&task->cap_info->caps, &cap->caps_link);
 	ra_free(task->cap_info->handles, handle, 1);
-	slab_free(cap_slab, cap);
+	slab_free(cap_cache, cap);
 	mutex_unlock(&task->cap_info->lock);
 }
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/console/cmd.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -497,9 +497,9 @@
 };
 
-static int cmd_slabs(cmd_arg_t *argv);
-static cmd_info_t slabs_info = {
-	.name = "slabs",
+static int cmd_caches(cmd_arg_t *argv);
+static cmd_info_t caches_info = {
+	.name = "caches",
 	.description = "List slab caches.",
-	.func = cmd_slabs,
+	.func = cmd_caches,
 	.argc = 0
 };
@@ -605,4 +605,5 @@
 	&call0_info,
 	&mcall0_info,
+	&caches_info,
 	&call1_info,
 	&call2_info,
@@ -620,5 +621,4 @@
 	&sched_info,
 	&set4_info,
-	&slabs_info,
 	&symaddr_info,
 	&sysinfo_info,
@@ -1214,11 +1214,11 @@
 }
 
-/** Command for listings SLAB caches
- *
- * @param argv Ignores
+/** Command for listing slab allocator caches
+ *
+ * @param argv Ignored
  *
  * @return Always 1
  */
-int cmd_slabs(cmd_arg_t *argv)
+int cmd_caches(cmd_arg_t *argv)
 {
 	slab_print_list();
Index: kernel/generic/src/ddi/irq.c
===================================================================
--- kernel/generic/src/ddi/irq.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/ddi/irq.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -50,5 +50,5 @@
 #include <arch.h>
 
-slab_cache_t *irq_slab = NULL;
+slab_cache_t *irq_cache = NULL;
 
 /** Spinlock protecting the kernel IRQ hash table
@@ -97,7 +97,7 @@
 	last_inr = inrs - 1;
 
-	irq_slab = slab_cache_create("irq_t", sizeof(irq_t), 0, NULL, NULL,
+	irq_cache = slab_cache_create("irq_t", sizeof(irq_t), 0, NULL, NULL,
 	    FRAME_ATOMIC);
-	assert(irq_slab);
+	assert(irq_cache);
 
 	hash_table_create(&irq_uspace_hash_table, chains, 0, &irq_ht_ops);
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/ipc/ipc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -66,8 +66,8 @@
 answerbox_t *ipc_phone_0 = NULL;
 
-static slab_cache_t *call_slab;
-static slab_cache_t *answerbox_slab;
-
-slab_cache_t *phone_slab = NULL; 
+static slab_cache_t *call_cache;
+static slab_cache_t *answerbox_cache;
+
+slab_cache_t *phone_cache = NULL; 
 
 /** Initialize a call structure.
@@ -87,19 +87,18 @@
 }
 
-void ipc_call_hold(call_t *call)
-{
-	atomic_inc(&call->refcnt);
-}
-
-void ipc_call_release(call_t *call)
-{
-	if (atomic_predec(&call->refcnt) == 0) {
-		if (call->buffer)
-			free(call->buffer);
-		if (call->caller_phone)
-			kobject_put(call->caller_phone->kobject);
-		slab_free(call_slab, call);
-	}
-}
+static void call_destroy(void *arg)
+{
+	call_t *call = (call_t *) arg;
+
+	if (call->buffer)
+		free(call->buffer);
+	if (call->caller_phone)
+		kobject_put(call->caller_phone->kobject);
+	slab_free(call_cache, call);
+}
+
+static kobject_ops_t call_kobject_ops = {
+	.destroy = call_destroy
+};
 
 /** Allocate and initialize a call structure.
@@ -116,21 +115,18 @@
 call_t *ipc_call_alloc(unsigned int flags)
 {
-	call_t *call = slab_alloc(call_slab, flags);
-	if (call) {
-		_ipc_call_init(call);
-		ipc_call_hold(call);
-	}
+	call_t *call = slab_alloc(call_cache, flags);
+	if (!call)
+		return NULL;
+	kobject_t *kobj = (kobject_t *) malloc(sizeof(kobject_t), flags);
+	if (!kobj) {
+		slab_free(call_cache, call);
+		return NULL;
+	}
+
+	_ipc_call_init(call);
+	kobject_initialize(kobj, KOBJECT_TYPE_CALL, call, &call_kobject_ops);
+	call->kobject = kobj;
 	
 	return call;
-}
-
-/** Deallocate a call structure.
- *
- * @param call Call structure to be freed.
- *
- */
-void ipc_call_free(call_t *call)
-{
-	ipc_call_release(call);
 }
 
@@ -214,5 +210,5 @@
 int ipc_call_sync(phone_t *phone, call_t *request)
 {
-	answerbox_t *mybox = slab_alloc(answerbox_slab, 0);
+	answerbox_t *mybox = slab_alloc(answerbox_cache, 0);
 	ipc_answerbox_init(mybox, TASK);
 	
@@ -222,5 +218,5 @@
 	int rc = ipc_call(phone, request);
 	if (rc != EOK) {
-		slab_free(answerbox_slab, mybox);
+		slab_free(answerbox_cache, mybox);
 		return rc;
 	}
@@ -269,5 +265,5 @@
 	assert(!answer || request == answer);
 	
-	slab_free(answerbox_slab, mybox);
+	slab_free(answerbox_cache, mybox);
 	return rc;
 }
@@ -290,5 +286,5 @@
 		/* This is a forgotten call and call->sender is not valid. */
 		spinlock_unlock(&call->forget_lock);
-		ipc_call_free(call);
+		kobject_put(call->kobject);
 		return;
 	} else {
@@ -705,5 +701,5 @@
 	 * must hold a reference to it.
 	 */
-	ipc_call_hold(call);
+	kobject_add_ref(call->kobject);
 
 	spinlock_unlock(&call->forget_lock);
@@ -714,5 +710,5 @@
 	SYSIPC_OP(request_forget, call);
 
-	ipc_call_release(call);
+	kobject_put(call->kobject);
 }
 
@@ -822,5 +818,5 @@
 	SYSIPC_OP(answer_process, call);
 
-	ipc_call_free(call);
+	kobject_put(call->kobject);
 	goto restart;
 }
@@ -839,4 +835,17 @@
 {
 	ipc_irq_unsubscribe(&TASK->answerbox, cap->handle);
+	return true;
+}
+
+static bool call_cap_cleanup_cb(cap_t *cap, void *arg)
+{
+	/*
+	 * Here we just free the capability and release the kobject.
+	 * The kernel answers the remaining calls elsewhere in ipc_cleanup().
+	 */
+	kobject_t *kobj = cap_unpublish(cap->task, cap->handle,
+	    KOBJECT_TYPE_CALL);
+	kobject_put(kobj);
+	cap_free(cap->task, cap->handle);
 	return true;
 }
@@ -878,4 +887,8 @@
 	ipc_kbox_cleanup();
 #endif
+
+	/* Destroy all call capabilities */
+	caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_CALL, call_cap_cleanup_cb,
+	    NULL);
 	
 	/* Answer all messages in 'calls' and 'dispatched_calls' queues */
@@ -893,9 +906,9 @@
 void ipc_init(void)
 {
-	call_slab = slab_cache_create("call_t", sizeof(call_t), 0, NULL,
+	call_cache = slab_cache_create("call_t", sizeof(call_t), 0, NULL,
 	    NULL, 0);
-	phone_slab = slab_cache_create("phone_t", sizeof(phone_t), 0, NULL,
+	phone_cache = slab_cache_create("phone_t", sizeof(phone_t), 0, NULL,
 	    NULL, 0);
-	answerbox_slab = slab_cache_create("answerbox_t", sizeof(answerbox_t),
+	answerbox_cache = slab_cache_create("answerbox_t", sizeof(answerbox_t),
 	    0, NULL, NULL, 0);
 }
Index: kernel/generic/src/ipc/ipcrsc.c
===================================================================
--- kernel/generic/src/ipc/ipcrsc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/ipc/ipcrsc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -137,31 +137,4 @@
 #include <mm/slab.h>
 
-/** Find call_t * in call table according to callid.
- *
- * @todo Some speedup (hash table?)
- *
- * @param callid Userspace hash of the call. Currently it is the call structure
- *               kernel address.
- *
- * @return NULL on not found, otherwise pointer to the call structure.
- *
- */
-call_t *get_call(sysarg_t callid)
-{
-	call_t *result = NULL;
-	
-	irq_spinlock_lock(&TASK->answerbox.lock, true);
-	
-	list_foreach(TASK->answerbox.dispatched_calls, ab_link, call_t, call) {
-		if ((sysarg_t) call == callid) {
-			result = call;
-			break;
-		}
-	}
-	
-	irq_spinlock_unlock(&TASK->answerbox.lock, true);
-	return result;
-}
-
 static bool phone_reclaim(kobject_t *kobj)
 {
@@ -180,5 +153,5 @@
 {
 	phone_t *phone = (phone_t *) arg;
-	slab_free(phone_slab, phone);
+	slab_free(phone_cache, phone);
 }
 
@@ -200,5 +173,5 @@
 	cap_handle_t handle = cap_alloc(task);
 	if (handle >= 0) {
-		phone_t *phone = slab_alloc(phone_slab, FRAME_ATOMIC);
+		phone_t *phone = slab_alloc(phone_cache, FRAME_ATOMIC);
 		if (!phone) {
 			cap_free(TASK, handle);
@@ -208,5 +181,5 @@
 		if (!kobject) {
 			cap_free(TASK, handle);
-			slab_free(phone_slab, phone);
+			slab_free(phone_cache, phone);
 			return ENOMEM;
 		}
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/ipc/irq.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -294,5 +294,5 @@
 	/* Free up the IRQ code and associated structures. */
 	code_free(irq->notif_cfg.code);
-	slab_free(irq_slab, irq);
+	slab_free(irq_cache, irq);
 }
 
@@ -308,10 +308,11 @@
  * @param ucode   Uspace pointer to top-half IRQ code.
  *
- * @return  IRQ capability handle.
- * @return  Negative error code.
+ * @param[out] uspace_handle  Uspace pointer to IRQ capability handle
+ *
+ * @return  Error code.
  *
  */
 int ipc_irq_subscribe(answerbox_t *box, inr_t inr, sysarg_t imethod,
-    irq_code_t *ucode)
+    irq_code_t *ucode, cap_handle_t *uspace_handle)
 {
 	if ((inr < 0) || (inr > last_inr))
@@ -333,5 +334,11 @@
 		return handle;
 	
-	irq_t *irq = (irq_t *) slab_alloc(irq_slab, FRAME_ATOMIC);
+	int rc = copy_to_uspace(uspace_handle, &handle, sizeof(cap_handle_t));
+	if (rc != EOK) {
+		cap_free(TASK, handle);
+		return rc;
+	}
+
+	irq_t *irq = (irq_t *) slab_alloc(irq_cache, FRAME_ATOMIC);
 	if (!irq) {
 		cap_free(TASK, handle);
@@ -342,5 +349,5 @@
 	if (!kobject) {
 		cap_free(TASK, handle);
-		slab_free(irq_slab, irq);
+		slab_free(irq_cache, irq);
 		return ENOMEM;
 	}
@@ -371,5 +378,5 @@
 	cap_publish(TASK, handle, kobject);
 	
-	return handle;
+	return EOK;
 }
 
Index: kernel/generic/src/ipc/kbox.c
===================================================================
--- kernel/generic/src/ipc/kbox.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/ipc/kbox.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -206,8 +206,9 @@
  * cleanup code.
  *
- * @return Phone capability handle on success, or negative error code.
- *
- */
-int ipc_connect_kbox(task_id_t taskid)
+ * @param[out] out_phone  Phone capability handle on success.
+ * @return Error code.
+ *
+ */
+int ipc_connect_kbox(task_id_t taskid, cap_handle_t *out_phone)
 {
 	irq_spinlock_lock(&tasks_lock, true);
@@ -231,9 +232,24 @@
 	}
 	
-	if (task->kb.finished != false) {
+	if (task->kb.finished) {
 		mutex_unlock(&task->kb.cleanup_lock);
 		return EINVAL;
 	}
 	
+	/* Create a kbox thread if necessary. */
+	if (task->kb.thread == NULL) {
+		thread_t *kb_thread = thread_create(kbox_thread_proc, NULL, task,
+		    THREAD_FLAG_NONE, "kbox");
+		
+		if (!kb_thread) {
+			mutex_unlock(&task->kb.cleanup_lock);
+			return ENOMEM;
+		}
+		
+		task->kb.thread = kb_thread;
+		thread_ready(kb_thread);
+	}
+	
+	/* Allocate a new phone. */
 	cap_handle_t phone_handle = phone_alloc(TASK);
 	if (phone_handle < 0) {
@@ -248,23 +264,7 @@
 	(void) ipc_phone_connect(phone_obj->phone, &task->kb.box);
 	
-	if (task->kb.thread != NULL) {
-		mutex_unlock(&task->kb.cleanup_lock);
-		return phone_handle;
-	}
-	
-	/* Create a kbox thread */
-	thread_t *kb_thread = thread_create(kbox_thread_proc, NULL, task,
-	    THREAD_FLAG_NONE, "kbox");
-	if (!kb_thread) {
-		mutex_unlock(&task->kb.cleanup_lock);
-		return ENOMEM;
-	}
-	
-	task->kb.thread = kb_thread;
-	thread_ready(kb_thread);
-	
 	mutex_unlock(&task->kb.cleanup_lock);
-	
-	return phone_handle;
+	*out_phone = phone_handle;
+	return EOK;
 }
 
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/ipc/sysipc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -53,4 +53,5 @@
 #include <print.h>
 #include <macros.h>
+#include <cap/cap.h>
 
 #define STRUCT_TO_USPACE(dst, src)  copy_to_uspace((dst), (src), sizeof(*(src)))
@@ -286,10 +287,10 @@
 #endif
 
-		ipc_call_hold(call);
+		kobject_add_ref(call->kobject);
 		rc = ipc_call_sync(kobj->phone, call);
 		spinlock_lock(&call->forget_lock);
 		bool forgotten = call->forget;
 		spinlock_unlock(&call->forget_lock);
-		ipc_call_release(call);
+		kobject_put(call->kobject);
 
 #ifdef CONFIG_UDEBUG
@@ -306,5 +307,5 @@
 				 * deallocation.
 				 */
-				ipc_call_free(call);
+				kobject_put(call->kobject);
 			} else {
 				/*
@@ -323,5 +324,5 @@
 	
 	memcpy(data->args, call->data.args, sizeof(data->args));
-	ipc_call_free(call);
+	kobject_put(call->kobject);
 	kobject_put(kobj);
 	
@@ -347,5 +348,5 @@
 /** Make a fast asynchronous call over IPC.
  *
- * This function can only handle four arguments of payload, but is faster than
+ * This function can only handle three arguments of payload, but is faster than
  * the generic function sys_ipc_call_async_slow().
  *
@@ -355,20 +356,20 @@
  * @param arg2     Service-defined payload argument.
  * @param arg3     Service-defined payload argument.
- * @param arg4     Service-defined payload argument.
- *
- * @return Call hash on success.
- * @return IPC_CALLRET_FATAL in case of a fatal error.
+ * @param label    User-defined label.
+ *
+ * @return EOK on success.
+ * @return Negative error code on error.
  *
  */
 sysarg_t sys_ipc_call_async_fast(sysarg_t handle, sysarg_t imethod,
-    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t label)
 {
 	kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
 	if (!kobj)
-		return IPC_CALLRET_FATAL;
+		return ENOENT;
 	
 	if (check_call_limit(kobj->phone)) {
 		kobject_put(kobj);
-		return IPC_CALLRET_FATAL;
+		return ELIMIT;
 	}
 	
@@ -378,5 +379,4 @@
 	IPC_SET_ARG2(call->data, arg2);
 	IPC_SET_ARG3(call->data, arg3);
-	IPC_SET_ARG4(call->data, arg4);
 	
 	/*
@@ -385,4 +385,7 @@
 	 */
 	IPC_SET_ARG5(call->data, 0);
+
+	/* Set the user-defined label */
+	call->data.label = label;
 	
 	int res = request_preprocess(call, kobj->phone);
@@ -394,5 +397,5 @@
 	
 	kobject_put(kobj);
-	return (sysarg_t) call;
+	return EOK;
 }
 
@@ -401,17 +404,19 @@
  * @param handle  Phone capability for the call.
  * @param data    Userspace address of call data with the request.
+ * @param label   User-defined label.
  *
  * @return See sys_ipc_call_async_fast().
  *
  */
-sysarg_t sys_ipc_call_async_slow(sysarg_t handle, ipc_data_t *data)
+sysarg_t sys_ipc_call_async_slow(sysarg_t handle, ipc_data_t *data,
+    sysarg_t label)
 {
 	kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
 	if (!kobj)
-		return IPC_CALLRET_FATAL;
+		return ENOENT;
 
 	if (check_call_limit(kobj->phone)) {
 		kobject_put(kobj);
-		return IPC_CALLRET_FATAL;
+		return ELIMIT;
 	}
 
@@ -420,8 +425,11 @@
 	    sizeof(call->data.args));
 	if (rc != 0) {
-		ipc_call_free(call);
+		kobject_put(call->kobject);
 		kobject_put(kobj);
 		return (sysarg_t) rc;
 	}
+
+	/* Set the user-defined label */
+	call->data.label = label;
 	
 	int res = request_preprocess(call, kobj->phone);
@@ -433,5 +441,5 @@
 	
 	kobject_put(kobj);
-	return (sysarg_t) call;
+	return EOK;
 }
 
@@ -440,6 +448,6 @@
  * Common code for both the fast and the slow version.
  *
- * @param callid   Hash of the call to forward.
- * @param handle   Phone capability to use for forwarding.
+ * @param chandle  Call handle of the forwarded call.
+ * @param phandle  Phone handle to use for forwarding.
  * @param imethod  New interface and method to use for the forwarded call.
  * @param arg1     New value of the first argument for the forwarded call.
@@ -458,12 +466,14 @@
  *
  */
-static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t handle,
+static sysarg_t sys_ipc_forward_common(sysarg_t chandle, sysarg_t phandle,
     sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
     sysarg_t arg4, sysarg_t arg5, unsigned int mode, bool slow)
 {
-	call_t *call = get_call(callid);
-	if (!call)
+	kobject_t *ckobj = cap_unpublish(TASK, chandle, KOBJECT_TYPE_CALL);
+	if (!ckobj)
 		return ENOENT;
 	
+	call_t *call = ckobj->call;
+
 	ipc_data_t old;
 	bool need_old = answer_need_old(call);
@@ -474,6 +484,6 @@
 	int rc;
 
-	kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
-	if (!kobj) {
+	kobject_t *pkobj = kobject_get(TASK, phandle, KOBJECT_TYPE_PHONE);
+	if (!pkobj) {
 		rc = ENOENT;
 		goto error;
@@ -521,5 +531,5 @@
 	}
 	
-	rc = ipc_forward(call, kobj->phone, &TASK->answerbox, mode);
+	rc = ipc_forward(call, pkobj->phone, &TASK->answerbox, mode);
 	if (rc != EOK) {
 		after_forward = true;
@@ -527,5 +537,7 @@
 	}
 
-	kobject_put(kobj);
+	cap_free(TASK, chandle);
+	kobject_put(ckobj);
+	kobject_put(pkobj);
 	return EOK;
 
@@ -538,6 +550,9 @@
 		ipc_answer(&TASK->answerbox, call);
 
-	if (kobj)
-		kobject_put(kobj);
+	/* Republish the capability so that the call does not get lost. */
+	cap_publish(TASK, chandle, ckobj);
+
+	if (pkobj)
+		kobject_put(pkobj);
 	return rc;
 }
@@ -552,6 +567,6 @@
  * arguments are not set and these values are ignored.
  *
- * @param callid   Hash of the call to forward.
- * @param handle   Phone handle to use for forwarding.
+ * @param chandle  Call handle of the call to forward.
+ * @param phandle  Phone handle to use for forwarding.
  * @param imethod  New interface and method to use for the forwarded call.
  * @param arg1     New value of the first argument for the forwarded call.
@@ -562,9 +577,9 @@
  *
  */
-sysarg_t sys_ipc_forward_fast(sysarg_t callid, sysarg_t handle,
+sysarg_t sys_ipc_forward_fast(sysarg_t chandle, sysarg_t phandle,
     sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
 {
-	return sys_ipc_forward_common(callid, handle, imethod, arg1, arg2, 0, 0,
-	    0, mode, false); 
+	return sys_ipc_forward_common(chandle, phandle, imethod, arg1, arg2, 0,
+	    0, 0, mode, false);
 }
 
@@ -578,13 +593,13 @@
  * and arg5, respectively, to ARG3, ARG4 and ARG5, respectively.
  *
- * @param callid  Hash of the call to forward.
- * @param handle  Phone handle to use for forwarding.
- * @param data    Userspace address of the new IPC data.
- * @param mode    Flags that specify mode of the forward operation.
+ * @param chandle  Call handle of the call to forward.
+ * @param phandle  Phone handle to use for forwarding.
+ * @param data     Userspace address of the new IPC data.
+ * @param mode     Flags that specify mode of the forward operation.
  *
  * @return 0 on succes, otherwise an error code.
  *
  */
-sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t handle,
+sysarg_t sys_ipc_forward_slow(sysarg_t chandle, sysarg_t phandle,
     ipc_data_t *data, unsigned int mode)
 {
@@ -595,8 +610,8 @@
 		return (sysarg_t) rc;
 	
-	return sys_ipc_forward_common(callid, handle,
+	return sys_ipc_forward_common(chandle, phandle,
 	    IPC_GET_IMETHOD(newdata), IPC_GET_ARG1(newdata),
 	    IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata),
-	    IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true); 
+	    IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true);
 }
 
@@ -606,25 +621,23 @@
  * than the generic sys_ipc_answer().
  *
- * @param callid Hash of the call to be answered.
- * @param retval Return value of the answer.
- * @param arg1   Service-defined return value.
- * @param arg2   Service-defined return value.
- * @param arg3   Service-defined return value.
- * @param arg4   Service-defined return value.
+ * @param chandle  Call handle to be answered.
+ * @param retval   Return value of the answer.
+ * @param arg1     Service-defined return value.
+ * @param arg2     Service-defined return value.
+ * @param arg3     Service-defined return value.
+ * @param arg4     Service-defined return value.
  *
  * @return 0 on success, otherwise an error code.
  *
  */
-sysarg_t sys_ipc_answer_fast(sysarg_t callid, sysarg_t retval,
-    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
-{
-	/* Do not answer notification callids */
-	if (callid & IPC_CALLID_NOTIFICATION)
-		return 0;
-	
-	call_t *call = get_call(callid);
-	if (!call)
+sysarg_t sys_ipc_answer_fast(sysarg_t chandle, sysarg_t retval, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
+{
+	kobject_t *kobj = cap_unpublish(TASK, chandle, KOBJECT_TYPE_CALL);
+	if (!kobj)
 		return ENOENT;
 	
+	call_t *call = kobj->call;
+
 	ipc_data_t saved_data;
 	bool saved;
@@ -650,4 +663,8 @@
 	
 	ipc_answer(&TASK->answerbox, call);
+
+	kobject_put(kobj);
+	cap_free(TASK, chandle);
+
 	return rc;
 }
@@ -655,20 +672,18 @@
 /** Answer an IPC call.
  *
- * @param callid Hash of the call to be answered.
- * @param data   Userspace address of call data with the answer.
+ * @param chandle Call handle to be answered.
+ * @param data    Userspace address of call data with the answer.
  *
  * @return 0 on success, otherwise an error code.
  *
  */
-sysarg_t sys_ipc_answer_slow(sysarg_t callid, ipc_data_t *data)
-{
-	/* Do not answer notification callids */
-	if (callid & IPC_CALLID_NOTIFICATION)
-		return 0;
-	
-	call_t *call = get_call(callid);
-	if (!call)
+sysarg_t sys_ipc_answer_slow(sysarg_t chandle, ipc_data_t *data)
+{
+	kobject_t *kobj = cap_unpublish(TASK, chandle, KOBJECT_TYPE_CALL);
+	if (!kobj)
 		return ENOENT;
 	
+	call_t *call = kobj->call;
+
 	ipc_data_t saved_data;
 	bool saved;
@@ -682,10 +697,19 @@
 	int rc = copy_from_uspace(&call->data.args, &data->args, 
 	    sizeof(call->data.args));
-	if (rc != 0)
+	if (rc != 0) {
+		/*
+		 * Republish the capability so that the call does not get lost.
+		 */
+		cap_publish(TASK, chandle, kobj);
 		return rc;
+	}
 	
 	rc = answer_preprocess(call, saved ? &saved_data : NULL);
 	
 	ipc_answer(&TASK->answerbox, call);
+
+	kobject_put(kobj);
+	cap_free(TASK, chandle);
+
 	return rc;
 }
@@ -720,9 +744,5 @@
  *                 for explanation.
  *
- * @return Hash of the call.
- *         If IPC_CALLID_NOTIFICATION bit is set in the hash, the
- *         call is a notification. IPC_CALLID_ANSWERED denotes an
- *         answer.
- *
+ * @return Negative error code on error.
  */
 sysarg_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec,
@@ -743,7 +763,11 @@
 	udebug_stoppable_end();
 #endif
-	
-	if (!call)
-		return 0;
+
+	if (!call) {
+		ipc_data_t data = {0};
+		data.cap_handle = CAP_NIL;
+		STRUCT_TO_USPACE(calldata, &data);
+		return EOK;
+	}
 	
 	if (call->flags & IPC_CALL_NOTIF) {
@@ -751,9 +775,11 @@
 		call->data.phone = (void *) call->priv;
 		
+		call->data.flags = IPC_CALL_NOTIF;
+		call->data.cap_handle = CAP_NIL;
+
 		STRUCT_TO_USPACE(calldata, &call->data);
+		kobject_put(call->kobject);
 		
-		ipc_call_free(call);
-		
-		return ((sysarg_t) call) | IPC_CALLID_NOTIFICATION;
+		return EOK;
 	}
 	
@@ -762,12 +788,15 @@
 		
 		if (call->flags & IPC_CALL_DISCARD_ANSWER) {
-			ipc_call_free(call);
+			kobject_put(call->kobject);
 			goto restart;
 		}
+
+		call->data.flags = IPC_CALL_ANSWERED;
+		call->data.cap_handle = CAP_NIL;
 		
 		STRUCT_TO_USPACE(calldata, &call->data);
-		ipc_call_free(call);
+		kobject_put(call->kobject);
 		
-		return ((sysarg_t) call) | IPC_CALLID_ANSWERED;
+		return EOK;
 	}
 	
@@ -775,27 +804,47 @@
 		goto restart;
 	
-	/* Include phone address('id') of the caller in the request,
-	 * copy whole call->data, not only call->data.args */
-	if (STRUCT_TO_USPACE(calldata, &call->data)) {
-		/*
-		 * The callee will not receive this call and no one else has
-		 * a chance to answer it. Reply with the EPARTY error code.
-		 */
-		ipc_data_t saved_data;
-		bool saved;
-		
-		if (answer_need_old(call)) {
-			memcpy(&saved_data, &call->data, sizeof(call->data));
-			saved = true;
-		} else
-			saved = false;
-		
-		IPC_SET_RETVAL(call->data, EPARTY);
-		(void) answer_preprocess(call, saved ? &saved_data : NULL);
-		ipc_answer(&TASK->answerbox, call);
-		return 0;
-	}
-	
-	return (sysarg_t) call;
+	int rc;
+	cap_handle_t handle = cap_alloc(TASK);
+	if (handle < 0) {
+		rc = handle;
+		goto error;
+	}
+	
+	call->data.cap_handle = handle;
+
+	/*
+	 * Include phone hash of the caller in the request, copy the whole
+	 * call->data, not only call->data.args.
+	 */
+	rc = STRUCT_TO_USPACE(calldata, &call->data);
+	if (rc != EOK)
+		goto error;
+
+	kobject_add_ref(call->kobject);
+	cap_publish(TASK, handle, call->kobject);
+	return EOK;
+
+error:
+	if (handle >= 0)
+		cap_free(TASK, handle);
+
+	/*
+	 * The callee will not receive this call and no one else has a chance to
+	 * answer it. Reply with the EPARTY error code.
+	 */
+	ipc_data_t saved_data;
+	bool saved;
+
+	if (answer_need_old(call)) {
+		memcpy(&saved_data, &call->data, sizeof(call->data));
+		saved = true;
+	} else
+		saved = false;
+
+	IPC_SET_RETVAL(call->data, EPARTY);
+	(void) answer_preprocess(call, saved ? &saved_data : NULL);
+	ipc_answer(&TASK->answerbox, call);
+
+	return rc;
 }
 
@@ -815,15 +864,17 @@
  * @param ucode   Uspace pointer to the top-half pseudocode.
  *
- * @return IRQ kernel object capability
+ * @param[out] uspace_handle  Uspace pointer to IRQ kernel object capability
+ *
  * @return EPERM
  * @return Error code returned by ipc_irq_subscribe().
  *
  */
-sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode)
+sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode,
+	cap_handle_t *uspace_handle)
 {
 	if (!(perm_get(TASK) & PERM_IRQ_REG))
 		return EPERM;
 	
-	return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode);
+	return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode, uspace_handle);
 }
 
@@ -846,20 +897,29 @@
 }
 
-#ifdef __32_BITS__
-
-/** Syscall connect to a task by ID (32 bits)
- *
- * @return Phone id on success, or negative error code.
- *
- */
-sysarg_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid)
+/** Syscall connect to a task by ID
+ *
+ * @return Error code.
+ *
+ */
+sysarg_t sys_ipc_connect_kbox(task_id_t *uspace_taskid, cap_handle_t *uspace_phone)
 {
 #ifdef CONFIG_UDEBUG
-	sysarg64_t taskid;
-	int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(sysarg64_t));
-	if (rc != 0)
-		return (sysarg_t) rc;
-	
-	return ipc_connect_kbox((task_id_t) taskid);
+	task_id_t taskid;
+	cap_handle_t phone;
+	
+	int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(task_id_t));
+	if (rc == EOK) {
+		rc = ipc_connect_kbox((task_id_t) taskid, &phone);
+	}
+	
+	if (rc == EOK) {
+		rc = copy_to_uspace(uspace_phone, &phone, sizeof(cap_handle_t));
+		if (rc != EOK) {
+			// Clean up the phone on failure.
+			sys_ipc_hangup(phone);
+		}
+	}
+	
+	return (sysarg_t) rc;
 #else
 	return (sysarg_t) ENOTSUP;
@@ -867,24 +927,4 @@
 }
 
-#endif  /* __32_BITS__ */
-
-#ifdef __64_BITS__
-
-/** Syscall connect to a task by ID (64 bits)
- *
- * @return Phone id on success, or negative error code.
- *
- */
-sysarg_t sys_ipc_connect_kbox(sysarg_t taskid)
-{
-#ifdef CONFIG_UDEBUG
-	return ipc_connect_kbox((task_id_t) taskid);
-#else
-	return (sysarg_t) ENOTSUP;
-#endif
-}
-
-#endif  /* __64_BITS__ */
-
 /** @}
  */
Index: kernel/generic/src/log/log.c
===================================================================
--- kernel/generic/src/log/log.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/log/log.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -294,5 +294,5 @@
  */
 sysarg_t sys_klog(sysarg_t operation, void *buf, size_t size,
-    sysarg_t level)
+    sysarg_t level, size_t *uspace_nread)
 {
 	char *data;
@@ -376,5 +376,6 @@
 				return (sysarg_t) rc;
 			
-			return copied;
+			return copy_to_uspace(uspace_nread, &copied, sizeof(copied));
+			return EOK;
 		default:
 			return (sysarg_t) ENOTSUP;
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/mm/as.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -90,5 +90,5 @@
  *
  */
-static slab_cache_t *as_slab;
+static slab_cache_t *as_cache;
 
 /** ASID subsystem lock.
@@ -131,5 +131,5 @@
 	as_arch_init();
 	
-	as_slab = slab_cache_create("as_t", sizeof(as_t), 0,
+	as_cache = slab_cache_create("as_t", sizeof(as_t), 0,
 	    as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
 	
@@ -153,5 +153,5 @@
 as_t *as_create(unsigned int flags)
 {
-	as_t *as = (as_t *) slab_alloc(as_slab, 0);
+	as_t *as = (as_t *) slab_alloc(as_cache, 0);
 	(void) as_create_arch(as, 0);
 	
@@ -254,5 +254,5 @@
 #endif
 	
-	slab_free(as_slab, as);
+	slab_free(as_cache, as);
 }
 
@@ -833,5 +833,5 @@
 			    btree_node_t, leaf_link);
 			
-			if ((cond = (bool) node->keys)) {
+			if ((cond = (node->keys != 0))) {
 				uintptr_t ptr = node->key[node->keys - 1];
 				size_t node_size =
Index: kernel/generic/src/mm/slab.c
===================================================================
--- kernel/generic/src/mm/slab.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/mm/slab.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -818,10 +818,8 @@
 }
 
-/* Print list of slabs
- *
- */
+/* Print list of caches */
 void slab_print_list(void)
 {
-	printf("[slab name       ] [size  ] [pages ] [obj/pg] [slabs ]"
+	printf("[cache name      ] [size  ] [pages ] [obj/pg] [slabs ]"
 	    " [cached] [alloc ] [ctl]\n");
 	
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/proc/scheduler.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -163,5 +163,5 @@
 			irq_spinlock_unlock(&CPU->lock, false);
 			THREAD->saved_fpu_context =
-			    (fpu_context_t *) slab_alloc(fpu_context_slab, 0);
+			    (fpu_context_t *) slab_alloc(fpu_context_cache, 0);
 			
 			/* We may have switched CPUs during slab_alloc */
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/proc/task.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -79,5 +79,5 @@
 static task_id_t task_counter = 0;
 
-static slab_cache_t *task_slab;
+static slab_cache_t *task_cache;
 
 /* Forward declarations. */
@@ -93,5 +93,5 @@
 	TASK = NULL;
 	avltree_create(&tasks_tree);
-	task_slab = slab_cache_create("task_t", sizeof(task_t), 0,
+	task_cache = slab_cache_create("task_t", sizeof(task_t), 0,
 	    tsk_constructor, tsk_destructor, 0);
 }
@@ -206,5 +206,5 @@
 task_t *task_create(as_t *as, const char *name)
 {
-	task_t *task = (task_t *) slab_alloc(task_slab, 0);
+	task_t *task = (task_t *) slab_alloc(task_cache, 0);
 	task_create_arch(task);
 	
@@ -295,5 +295,5 @@
 	as_release(task->as);
 	
-	slab_free(task_slab, task);
+	slab_free(task_cache, task);
 }
 
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/proc/thread.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -103,8 +103,8 @@
 static thread_id_t last_tid = 0;
 
-static slab_cache_t *thread_slab;
+static slab_cache_t *thread_cache;
 
 #ifdef CONFIG_FPU
-slab_cache_t *fpu_context_slab;
+slab_cache_t *fpu_context_cache;
 #endif
 
@@ -169,5 +169,5 @@
 	thread->saved_fpu_context = NULL;
 #else /* CONFIG_FPU_LAZY */
-	thread->saved_fpu_context = slab_alloc(fpu_context_slab, kmflags);
+	thread->saved_fpu_context = slab_alloc(fpu_context_cache, kmflags);
 	if (!thread->saved_fpu_context)
 		return -1;
@@ -199,5 +199,5 @@
 #ifdef CONFIG_FPU
 		if (thread->saved_fpu_context)
-			slab_free(fpu_context_slab, thread->saved_fpu_context);
+			slab_free(fpu_context_cache, thread->saved_fpu_context);
 #endif
 		return -1;
@@ -225,5 +225,5 @@
 #ifdef CONFIG_FPU
 	if (thread->saved_fpu_context)
-		slab_free(fpu_context_slab, thread->saved_fpu_context);
+		slab_free(fpu_context_cache, thread->saved_fpu_context);
 #endif
 	
@@ -241,9 +241,9 @@
 	
 	atomic_set(&nrdy, 0);
-	thread_slab = slab_cache_create("thread_t", sizeof(thread_t), 0,
+	thread_cache = slab_cache_create("thread_t", sizeof(thread_t), 0,
 	    thr_constructor, thr_destructor, 0);
 	
 #ifdef CONFIG_FPU
-	fpu_context_slab = slab_cache_create("fpu_context_t",
+	fpu_context_cache = slab_cache_create("fpu_context_t",
 	    sizeof(fpu_context_t), FPU_CONTEXT_ALIGN, NULL, NULL, 0);
 #endif
@@ -341,5 +341,5 @@
     thread_flags_t flags, const char *name)
 {
-	thread_t *thread = (thread_t *) slab_alloc(thread_slab, 0);
+	thread_t *thread = (thread_t *) slab_alloc(thread_cache, 0);
 	if (!thread)
 		return NULL;
@@ -457,5 +457,5 @@
 	 */
 	task_release(thread->task);
-	slab_free(thread_slab, thread);
+	slab_free(thread_cache, thread);
 }
 
@@ -974,5 +974,5 @@
 				 * We can safely deallocate it.
 				 */
-				slab_free(thread_slab, thread);
+				slab_free(thread_cache, thread);
 				free(kernel_uarg);
 				
Index: kernel/generic/src/sysinfo/sysinfo.c
===================================================================
--- kernel/generic/src/sysinfo/sysinfo.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/sysinfo/sysinfo.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -53,5 +53,5 @@
 
 /** Sysinfo SLAB cache */
-static slab_cache_t *sysinfo_item_slab;
+static slab_cache_t *sysinfo_item_cache;
 
 /** Sysinfo lock */
@@ -98,5 +98,5 @@
 void sysinfo_init(void)
 {
-	sysinfo_item_slab = slab_cache_create("sysinfo_item_t",
+	sysinfo_item_cache = slab_cache_create("sysinfo_item_t",
 	    sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
 	    sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
@@ -204,5 +204,5 @@
 		
 		*psubtree =
-		    (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
+		    (sysinfo_item_t *) slab_alloc(sysinfo_item_cache, 0);
 		assert(*psubtree);
 		
@@ -268,5 +268,5 @@
 			
 			sysinfo_item_t *item =
-			    (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
+			    (sysinfo_item_t *) slab_alloc(sysinfo_item_cache, 0);
 			assert(item);
 			
Index: kernel/generic/src/udebug/udebug_ipc.c
===================================================================
--- kernel/generic/src/udebug/udebug_ipc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/udebug/udebug_ipc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -72,7 +72,8 @@
 {
 	int rc;
-
-	rc = udebug_begin(call);
-	if (rc < 0) {
+	bool active;
+
+	rc = udebug_begin(call, &active);
+	if (rc != EOK) {
 		IPC_SET_RETVAL(call->data, rc);
 		ipc_answer(&TASK->kb.box, call);
@@ -84,6 +85,6 @@
 	 * send a reply.
 	 */
-	if (rc != 0) {
-		IPC_SET_RETVAL(call->data, 0);
+	if (active) {
+		IPC_SET_RETVAL(call->data, EOK);
 		ipc_answer(&TASK->kb.box, call);
 	}
Index: kernel/generic/src/udebug/udebug_ops.c
===================================================================
--- kernel/generic/src/udebug/udebug_ops.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ kernel/generic/src/udebug/udebug_ops.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -46,4 +46,5 @@
 #include <errno.h>
 #include <print.h>
+#include <stdbool.h>
 #include <str.h>
 #include <syscall/copy.h>
@@ -157,18 +158,21 @@
  *
  * Initiates a debugging session for the current task (and its threads).
- * When the debugging session has started a reply will be sent to the
+ * When the debugging session has started a reply should be sent to the
  * UDEBUG_BEGIN call. This may happen immediately in this function if
  * all the threads in this task are stoppable at the moment and in this
- * case the function returns 1.
- *
- * Otherwise the function returns 0 and the reply will be sent as soon as
- * all the threads become stoppable (i.e. they can be considered stopped).
+ * case the function sets @a *active to @c true.
+ *
+ * Otherwise the function sets @a *active to false and the resonse should
+ * be sent as soon as all the threads become stoppable (i.e. they can be
+ * considered stopped).
  *
  * @param call The BEGIN call we are servicing.
- *
- * @return 0 (OK, but not done yet), 1 (done) or negative error code.
- *
- */
-int udebug_begin(call_t *call)
+ * @param active Place to store @c true iff we went directly to active state,
+ *               @c false if we only went to beginning state
+ *
+ * @return EOK on success, EBUSY if the task is already has an active
+ *         debugging session.
+ */
+int udebug_begin(call_t *call, bool *active)
 {
 	LOG("Debugging task %" PRIu64, TASK->taskid);
@@ -185,12 +189,10 @@
 	TASK->udebug.debugger = call->sender;
 	
-	int reply;
-	
 	if (TASK->udebug.not_stoppable_count == 0) {
 		TASK->udebug.dt_state = UDEBUG_TS_ACTIVE;
 		TASK->udebug.begin_call = NULL;
-		reply = 1;  /* immediate reply */
+		*active = true;  /* directly to active state */
 	} else
-		reply = 0;  /* no reply */
+		*active = false;  /* only in beginning state */
 	
 	/* Set udebug.active on all of the task's userspace threads. */
@@ -207,5 +209,5 @@
 	
 	mutex_unlock(&TASK->udebug.lock);
-	return reply;
+	return EOK;
 }
 
Index: release/Makefile
===================================================================
--- release/Makefile	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ release/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -43,4 +43,5 @@
 	ia64/ski \
 	mips32/malta-be \
+	mips32/malta-le \
 	mips32/msim \
 	ppc32 \
@@ -48,5 +49,5 @@
 	sparc64/ultra
 
-BZR = bzr
+GIT = git
 TAR = tar
 
@@ -91,5 +92,5 @@
 	rm -rf $(EXPORT_DIR)
 	mkdir -p $(EXPORT_DIR)
-	$(BZR) export $(EXPORT_DIR) ../
+	(cd ..; $(GIT) archive master) | $(TAR) -x -C $(EXPORT_DIR)
 
 src_rel $(SRC_ARCHIVE): export
Index: tools/grub/grub-update.sh
===================================================================
--- tools/grub/grub-update.sh	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ tools/grub/grub-update.sh	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -59,5 +59,5 @@
 	rm -f "$helenosdir"/boot/"$gdir"/"$platform"/*.image || exit 1
 	rm -f "$helenosdir"/boot/"$gdir"/"$platform"/*.module || exit 1
-	bzr add "$helenosdir"/boot/"$gdir"/"$platform" || exit 1
+	git add "$helenosdir"/boot/"$gdir"/"$platform" || exit 1
 }
 
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -136,4 +136,5 @@
 	srv/hw/char/s3c24xx_uart \
 	srv/hid/rfb \
+	srv/test/chardev-test \
 	drv/audio/hdaudio \
 	drv/audio/sb16 \
Index: uspace/app/barber/barber.c
===================================================================
--- uspace/app/barber/barber.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/barber/barber.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,5 @@
 #include <errno.h>
 #include <stdio.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <task.h>
 #include <loc.h>
Index: uspace/app/bdsh/cmds/modules/cat/cat.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -180,10 +180,12 @@
     off64_t head, off64_t tail, bool tail_first)
 {
-	int fd, bytes = 0, count = 0, reads = 0;
+	int fd, count = 0, reads = 0;
+	size_t bytes;
 	char *buff = NULL;
-	int i;
+	size_t i;
 	size_t offset = 0, copied_bytes = 0;
 	off64_t file_size = 0, length = 0;
 	aoff64_t pos = 0;
+	int rc;
 
 	bool reading_stdin = dash_represents_stdin && (str_cmp(fname, "-") == 0);
@@ -193,6 +195,10 @@
 		/* Allow storing the whole UTF-8 character. */
 		blen = STR_BOUNDS(1);
-	} else
-		fd = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ);
+	} else {
+		int rc = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ, &fd);
+		if (rc != EOK) {
+			fd = -1;
+		}
+	}
 	
 	if (fd < 0) {
@@ -250,8 +256,9 @@
 		}
 		
-		bytes = vfs_read(fd, &pos, buff + copied_bytes, bytes_to_read);
+		rc = vfs_read(fd, &pos, buff + copied_bytes, bytes_to_read,
+		    &bytes);
 		copied_bytes = 0;
 
-		if (bytes > 0) {
+		if (rc == EOK && bytes > 0) {
 			buff[bytes] = '\0';
 			offset = 0;
@@ -284,8 +291,8 @@
 		if (reading_stdin)
 			fflush(stdout);
-	} while (bytes > 0 && !should_quit && (count < length || length == CAT_FULL_FILE));
+	} while (rc == EOK && bytes > 0 && !should_quit && (count < length || length == CAT_FULL_FILE));
 
 	vfs_put(fd);
-	if (bytes == -1) {
+	if (rc != EOK) {
 		printf("Error reading %s\n", fname);
 		free(buff);
Index: uspace/app/bdsh/cmds/modules/cmp/cmp.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cmp/cmp.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/cmds/modules/cmp/cmp.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -72,15 +72,14 @@
 static int cmp_files(const char *fn0, const char *fn1)
 {
-	int rc = 0;
+	int rc = EOK;
 	const char *fn[2] = {fn0, fn1};
 	int fd[2] = {-1, -1};
 	char buffer[2][CMP_BUFLEN];
-	ssize_t offset[2];
+	size_t offset[2];
 	aoff64_t pos[2] = {};
 
 	for (int i = 0; i < 2; i++) {
-		fd[i] = vfs_lookup_open(fn[i], WALK_REGULAR, MODE_READ);
-		if (fd[i] < 0) {
-			rc = fd[i];
+		rc = vfs_lookup_open(fn[i], WALK_REGULAR, MODE_READ, &(fd[i]));
+		if (rc != EOK) {
 			printf("Unable to open %s\n", fn[i]);
 			goto end;
@@ -90,22 +89,16 @@
 	do {
 		for (int i = 0; i < 2; i++) {
-			offset[i] = 0;
-			ssize_t size;
-			do {
-				size = vfs_read(fd[i], &pos[i],
-				    buffer[i] + offset[i],
-				    CMP_BUFLEN - offset[i]);
-				if (size < 0) {
-					rc = size;
-					printf("Error reading from %s\n",
-					    fn[i]);
-					goto end;
-				}
-				offset[i] += size;
-			} while (size && offset[i] < CMP_BUFLEN);
+			rc = vfs_read(fd[i], &pos[i], buffer[i], CMP_BUFLEN,
+			    &offset[i]);
+			if (rc != EOK) {
+				printf("Error reading from %s\n",
+				    fn[i]);
+				goto end;
+			}
 		}
 
 		if (offset[0] != offset[1] ||
 		    memcmp(buffer[0], buffer[1], offset[0]) != 0) {
+			printf("Return 1\n");
 			rc = 1;
 			goto end;
@@ -149,5 +142,5 @@
 
 	rc = cmp_files(argv[optind], argv[optind + 1]);
-	if (rc)
+	if (rc != EOK)
 		return CMD_FAILURE;
 	else
Index: uspace/app/bdsh/cmds/modules/cp/cp.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cp/cp.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/cmds/modules/cp/cp.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -28,4 +28,5 @@
 
 #include <errno.h>
+#include <str_error.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -66,5 +67,5 @@
 } dentry_type_t;
 
-static int64_t copy_file(const char *src, const char *dest,
+static int copy_file(const char *src, const char *dest,
     size_t blen, int vb);
 
@@ -175,8 +176,8 @@
 }
 
-static int64_t do_copy(const char *src, const char *dest,
+static int do_copy(const char *src, const char *dest,
     size_t blen, int vb, int recursive, int force, int interactive)
 {
-	int r = -1;
+	int rc = EOK;
 	char dest_path[PATH_MAX];
 	char src_path[PATH_MAX];
@@ -217,4 +218,5 @@
 				printf("The dest directory %s does not exists",
 				    dest_path);
+				rc = ENOENT;
 				goto exit;
 			}
@@ -224,4 +226,5 @@
 			printf("Cannot overwrite existing directory %s\n",
 			    dest_path);
+			rc = EEXIST;
 			goto exit;
 		} else if (dest_type == TYPE_FILE) {
@@ -233,5 +236,6 @@
 			 */
 			if (force && !interactive) {
-				if (vfs_unlink_path(dest_path) != EOK) {
+				rc = vfs_unlink_path(dest_path);
+				if (rc != EOK) {
 					printf("Unable to remove %s\n",
 					    dest_path);
@@ -244,5 +248,6 @@
 				if (overwrite) {
 					printf("Overwriting file: %s\n", dest_path);
-					if (vfs_unlink_path(dest_path) != EOK) {
+					rc = vfs_unlink_path(dest_path);
+					if (rc != EOK) {
 						printf("Unable to remove %s\n", dest_path);
 						goto exit;
@@ -250,9 +255,10 @@
 				} else {
 					printf("Not overwriting file: %s\n", dest_path);
-					r = 0;
+					rc = EOK;
 					goto exit;
 				}
 			} else {
 				printf("File already exists: %s\n", dest_path);
+				rc = EEXIST;
 				goto exit;
 			}
@@ -260,5 +266,5 @@
 
 		/* call copy_file and exit */
-		r = (copy_file(src, dest_path, blen, vb) < 0);
+		rc = (copy_file(src, dest_path, blen, vb) < 0);
 
 	} else if (src_type == TYPE_DIR) {
@@ -268,7 +274,9 @@
 			printf("Cannot copy the %s directory without the "
 			    "-r option\n", src);
+			rc = EINVAL;
 			goto exit;
 		} else if (dest_type == TYPE_FILE) {
 			printf("Cannot overwrite a file with a directory\n");
+			rc = EEXIST;
 			goto exit;
 		}
@@ -293,6 +301,7 @@
 				merge_paths(dest_path, PATH_MAX, src_dirname);
 
-				if (vfs_link_path(dest_path, KIND_DIRECTORY,
-				    NULL) != EOK) {
+				rc = vfs_link_path(dest_path, KIND_DIRECTORY,
+				    NULL);
+				if (rc != EOK) {
 					printf("Unable to create "
 					    "dest directory %s\n", dest_path);
@@ -308,6 +317,6 @@
 			 * e.g. cp -r /src /data/new_dir_src
 			 */
-			if (vfs_link_path(dest_path, KIND_DIRECTORY,
-			    NULL) != EOK) {
+			rc = vfs_link_path(dest_path, KIND_DIRECTORY, NULL);
+			if (rc != EOK) {
 				printf("Unable to create "
 				    "dest directory %s\n", dest_path);
@@ -321,4 +330,5 @@
 			/* Something strange is happening... */
 			printf("Unable to open src %s directory\n", src);
+			rc = ENOENT;
 			goto exit;
 		}
@@ -348,4 +358,5 @@
 				printf("Cannot copy a directory "
 				    "into itself\n");
+				rc = EEXIST;
 				goto exit;
 			}
@@ -355,7 +366,7 @@
 
 			/* Recursively call do_copy() */
-			r = do_copy(src_dent, dest_dent, blen, vb, recursive,
+			rc = do_copy(src_dent, dest_dent, blen, vb, recursive,
 			    force, interactive);
-			if (r)
+			if (rc != EOK)
 				goto exit;
 
@@ -367,13 +378,14 @@
 	if (dir)
 		closedir(dir);
-	return r;
-}
-
-static int64_t copy_file(const char *src, const char *dest,
+	return rc;
+}
+
+static int copy_file(const char *src, const char *dest,
 	size_t blen, int vb)
 {
-	int fd1, fd2, bytes;
+	int fd1, fd2;
+	size_t rbytes, wbytes;
+	int rc;
 	off64_t total;
-	int64_t copied = 0;
 	char *buff = NULL;
 	aoff64_t posr = 0, posw = 0;
@@ -383,12 +395,12 @@
 		printf("Copying %s to %s\n", src, dest);
 
-	fd1 = vfs_lookup_open(src, WALK_REGULAR, MODE_READ);
-	if (fd1 < 0) {
+	rc = vfs_lookup_open(src, WALK_REGULAR, MODE_READ, &fd1);
+	if (rc != EOK) {
 		printf("Unable to open source file %s\n", src);
 		return -1;
 	}
 
-	fd2 = vfs_lookup_open(dest, WALK_REGULAR | WALK_MAY_CREATE, MODE_WRITE);
-	if (fd2 < 0) {
+	rc = vfs_lookup_open(dest, WALK_REGULAR | WALK_MAY_CREATE, MODE_WRITE, &fd2);
+	if (rc != EOK) {
 		printf("Unable to open destination file %s\n", dest);
 		vfs_put(fd1);
@@ -410,17 +422,17 @@
 		printf("Unable to allocate enough memory to read %s\n",
 		    src);
-		copied = -1;
+		rc = ENOMEM;
 		goto out;
 	}
 
-	while ((bytes = vfs_read(fd1, &posr, buff, blen)) > 0) {
-		if ((bytes = vfs_write(fd2, &posw, buff, bytes)) < 0)
-			break;
-		copied += bytes;
-	}
-
-	if (bytes < 0) {
-		printf("\nError copying %s, (%d)\n", src, bytes);
-		copied = bytes;
+	while ((rc = vfs_read(fd1, &posr, buff, blen, &rbytes)) == EOK &&
+	    rbytes > 0) {
+		if ((rc = vfs_write(fd2, &posw, buff, rbytes, &wbytes)) != EOK)
+			break;
+	}
+
+	if (rc != EOK) {
+		printf("\nError copying %s: %s\n", src, str_error(rc));
+		return rc;
 	}
 
@@ -430,5 +442,5 @@
 	if (buff)
 		free(buff);
-	return copied;
+	return rc;
 }
 
Index: uspace/app/bdsh/cmds/modules/ls/ls.c
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -32,4 +32,5 @@
 
 #include <errno.h>
+#include <str_error.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -184,5 +185,5 @@
 		if (rc != EOK) {
 			printf("ls: skipping bogus node %s\n", buff);
-			printf("error=%d\n", rc);
+			printf("error=%s\n", str_error_name(rc));
 			goto out;
 		}
Index: uspace/app/bdsh/cmds/modules/mkfile/mkfile.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mkfile/mkfile.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/cmds/modules/mkfile/mkfile.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -31,4 +31,5 @@
 #include <stdlib.h>
 #include <stdint.h>
+#include <str_error.h>
 #include <dirent.h>
 #include <macros.h>
@@ -85,17 +86,20 @@
  *
  * @param str	String containing the size specification.
- * @return	Non-negative size in bytes on success, -1 on failure.
+ * @param rsize	Place to store size in bytes
+ * @return	EOK on success or error code
  */
-static ssize_t read_size(const char *str)
+static int read_size(const char *str, size_t *rsize)
 {
-	ssize_t number, unit;
+	size_t number, unit;
 	char *ep;
 
 	number = strtol(str, &ep, 10);
-	if (ep[0] == '\0')
-		return number;
+	if (ep[0] == '\0') {
+		*rsize = number;
+		return EOK;
+	}
 
 	if (ep[1] != '\0')
-		    return -1;
+		    return EINVAL;
 
 	switch (tolower(ep[0])) {
@@ -103,8 +107,9 @@
 	case 'm': unit = 1024*1024; break;
 	case 'g': unit = 1024*1024*1024; break;
-	default: return -1;
-	}
-
-	return number * unit;
+	default: return EINVAL;
+	}
+
+	*rsize = number * unit;
+	return EOK;
 }
 
@@ -114,7 +119,9 @@
 	int c, opt_ind;
 	int fd;
-	ssize_t file_size;
-	ssize_t total_written;
-	ssize_t to_write, rc, rc2 = 0;
+	size_t file_size;
+	size_t total_written;
+	size_t to_write;
+	size_t nwritten;
+	int rc;
 	char *file_name;
 	void *buffer;
@@ -136,6 +143,6 @@
 			break;
 		case 's':
-			file_size = read_size(optarg);
-			if (file_size < 0) {
+			rc = read_size(optarg, &file_size);
+			if (rc != EOK) {
 				printf("%s: Invalid file size specification.\n",
 				    cmdname);
@@ -156,6 +163,6 @@
 	file_name = argv[optind];
 
-	fd = vfs_lookup_open(file_name, WALK_REGULAR | WALK_MUST_CREATE, MODE_WRITE);
-	if (fd < 0) {
+	rc = vfs_lookup_open(file_name, WALK_REGULAR | WALK_MUST_CREATE, MODE_WRITE, &fd);
+	if (rc != EOK) {
 		printf("%s: failed to create file %s.\n", cmdname, file_name);
 		return CMD_FAILURE;
@@ -166,6 +173,6 @@
 		
 		pos = file_size - 1;
-		rc2 = vfs_write(fd, &pos, &byte, sizeof(char));
-		if (rc2 < 0) {
+		rc = vfs_write(fd, &pos, &byte, sizeof(char), &nwritten);
+		if (rc != EOK) {
 			vfs_put(fd);
 			goto error;
@@ -183,12 +190,12 @@
 	while (total_written < file_size) {
 		to_write = min(file_size - total_written, BUFFER_SIZE);
-		rc = vfs_write(fd, &pos, buffer, to_write);
-		if (rc <= 0) {
-			printf("%s: Error writing file (%d).\n", cmdname, errno);
+		rc = vfs_write(fd, &pos, buffer, to_write, &nwritten);
+		if (rc != EOK) {
+			printf("%s: Error writing file (%s).\n", cmdname, str_error(errno));
 			vfs_put(fd);
 			free(buffer);
 			return CMD_FAILURE;
 		}
-		total_written += rc;
+		total_written += nwritten;
 	}
 
@@ -200,5 +207,5 @@
 	return CMD_SUCCESS;
 error:
-	printf("%s: Error writing file (%d).\n", cmdname, errno);
+	printf("%s: Error writing file (%s).\n", cmdname, str_error(errno));
 	return CMD_FAILURE;
 }
Index: uspace/app/bdsh/cmds/modules/mv/mv.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mv/mv.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/cmds/modules/mv/mv.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,4 +30,5 @@
 #include <stdlib.h>
 #include <errno.h>
+#include <str_error.h>
 #include <vfs/vfs.h>
 #include "config.h"
@@ -62,6 +63,6 @@
 	rc = vfs_rename_path(argv[1], argv[2]);
 	if (rc != EOK) {
-		printf("Unable to rename %s to %s (error=%d)\n",
-		    argv[1], argv[2], rc);
+		printf("Unable to rename %s to %s: %s)\n",
+		    argv[1], argv[2], str_error(rc));
 		return CMD_FAILURE;
 	}
Index: uspace/app/bdsh/cmds/modules/rm/rm.c
===================================================================
--- uspace/app/bdsh/cmds/modules/rm/rm.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/cmds/modules/rm/rm.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -149,6 +149,5 @@
 	}
 
-	fd = vfs_lookup(path, WALK_REGULAR);
-	if (fd >= 0) {
+	if (vfs_lookup(path, WALK_REGULAR, &fd) == EOK) {
 		vfs_put(fd);
 		return RM_FILE;
Index: uspace/app/bdsh/cmds/modules/sleep/sleep.c
===================================================================
--- uspace/app/bdsh/cmds/modules/sleep/sleep.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/cmds/modules/sleep/sleep.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -27,8 +27,8 @@
  */
 
+#include <async.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <thread.h>
 #include "config.h"
 #include "util.h"
@@ -131,5 +131,5 @@
 	}
 
-	(void) thread_usleep(duration);
+	async_usleep(duration);
 
 	return CMD_SUCCESS;
Index: uspace/app/bdsh/cmds/modules/touch/touch.c
===================================================================
--- uspace/app/bdsh/cmds/modules/touch/touch.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/cmds/modules/touch/touch.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -123,5 +123,8 @@
 		if ((!no_create) ||
 		    ((no_create) && (vfs_stat_path(buff, &file_stat) == EOK))) {
-			fd = vfs_lookup(buff, WALK_REGULAR | WALK_MAY_CREATE);
+			int rc = vfs_lookup(buff, WALK_REGULAR | WALK_MAY_CREATE, &fd);
+			if (rc != EOK) {
+				fd = -1;
+			}
 		}
 		
Index: uspace/app/bdsh/cmds/modules/unmount/unmount.c
===================================================================
--- uspace/app/bdsh/cmds/modules/unmount/unmount.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/cmds/modules/unmount/unmount.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -31,4 +31,5 @@
 #include <vfs/vfs.h>
 #include <errno.h>
+#include <str_error.h>
 #include "config.h"
 #include "util.h"
@@ -68,5 +69,5 @@
 	rc = vfs_unmount_path(argv[1]);
 	if (rc != EOK) {
-		printf("Unable to unmount %s (rc=%d)\n", argv[1], rc);
+		printf("Unable to unmount %s: %s\n", argv[1], str_error(rc));
 		return CMD_FAILURE;
 	}
Index: uspace/app/bdsh/exec.c
===================================================================
--- uspace/app/bdsh/exec.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/exec.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -58,6 +58,6 @@
 	int fd;
 
-	fd = vfs_lookup_open(f, WALK_REGULAR, MODE_READ);
-	if (fd >= 0) {
+	int rc = vfs_lookup_open(f, WALK_REGULAR, MODE_READ, &fd);
+	if (rc == EOK) {
 		vfs_put(fd);
 		return 0;
Index: uspace/app/bdsh/tok.c
===================================================================
--- uspace/app/bdsh/tok.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bdsh/tok.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -29,5 +29,4 @@
 #include <str.h>
 #include <assert.h>
-#include <malloc.h>
 #include <stdlib.h>
 #include <stddef.h>
Index: uspace/app/bnchmark/bnchmark.c
===================================================================
--- uspace/app/bnchmark/bnchmark.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/bnchmark/bnchmark.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,4 +41,5 @@
 #include <stdlib.h>
 #include <stdint.h>
+#include <str_error.h>
 #include <mem.h>
 #include <loc.h>
@@ -186,5 +187,5 @@
 		rc = measure(fn, path, &milliseconds_taken);
 		if (rc != EOK) {
-			fprintf(stderr, "Error %d\n", rc);
+			fprintf(stderr, "Error: %s\n", str_error(rc));
 			return 1;
 		}
Index: uspace/app/date/date.c
===================================================================
--- uspace/app/date/date.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/date/date.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -33,5 +33,5 @@
 #include <loc.h>
 #include <time.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <getopt.h>
 #include <ctype.h>
Index: uspace/app/devctl/devctl.c
===================================================================
--- uspace/app/devctl/devctl.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/devctl/devctl.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -324,5 +324,5 @@
 	rc = devman_driver_get_handle(drvname, &drvh);
 	if (rc != EOK) {
-		printf("Failed resolving driver '%s' (%d).\n", drvname, rc);
+		printf("Failed resolving driver '%s': %s.\n", drvname, str_error(rc));
 		return rc;
 	}
@@ -330,5 +330,5 @@
 	rc = devman_driver_load(drvh);
 	if (rc != EOK) {
-		printf("Failed loading driver '%s' (%d).\n", drvname, rc);
+		printf("Failed loading driver '%s': %s.\n", drvname, str_error(rc));
 		return rc;
 	}
@@ -344,5 +344,5 @@
 	rc = devman_driver_get_handle(drvname, &drvh);
 	if (rc != EOK) {
-		printf("Failed resolving driver '%s' (%d).\n", drvname, rc);
+		printf("Failed resolving driver '%s': %s.\n", drvname, str_error(rc));
 		return rc;
 	}
@@ -350,5 +350,5 @@
 	rc = devman_driver_unload(drvh);
 	if (rc != EOK) {
-		printf("Failed unloading driver '%s' (%d).\n", drvname, rc);
+		printf("Failed unloading driver '%s': %s.\n", drvname, str_error(rc));
 		return rc;
 	}
Index: uspace/app/df/df.c
===================================================================
--- uspace/app/df/df.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/df/df.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,4 +40,5 @@
 #include <stdlib.h>
 #include <stdint.h>
+#include <str_error.h>
 #include <getopt.h>
 #include <errno.h>
@@ -118,6 +119,6 @@
 				return 1;
 		} else {
-			fprintf(stderr, "Cannot get information for '%s' (%d).\n",
-			    mtab_ent->mp, errno);
+			fprintf(stderr, "Cannot get information for '%s' (%s).\n",
+			    mtab_ent->mp, str_error(errno));
 		}
 	}
Index: uspace/app/download/main.c
===================================================================
--- uspace/app/download/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/download/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -224,6 +224,6 @@
 		}
 		
-		int body_size;
-		while ((body_size = recv_buffer(&http->recv_buffer, buf, buf_size)) > 0) {
+		size_t body_size;
+		while ((rc = recv_buffer(&http->recv_buffer, buf, buf_size, &body_size)) == EOK && body_size > 0) {
 			fwrite(buf, 1, body_size, ofile != NULL ? ofile : stdout);
 		}
Index: uspace/app/edit/edit.c
===================================================================
--- uspace/app/edit/edit.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/edit/edit.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -955,4 +955,11 @@
 	coord_t coord;
 	int last_row;
+	char *fname;
+	char *p;
+	char *text;
+	size_t n;
+	int pos;
+	size_t nextra;
+	size_t fnw;
 
 	tag_get_pt(&pane.caret_pos, &caret_pt);
@@ -961,12 +968,71 @@
 	sheet_get_num_rows(doc.sh, &last_row);
 
-	const char *fname = (doc.file_name != NULL) ? doc.file_name : "<unnamed>";
+	if (doc.file_name != NULL) {
+		/* Remove directory component */
+		p = str_rchr(doc.file_name, '/');
+		if (p != NULL)
+			fname = str_dup(p + 1);
+		else
+			fname = str_dup(doc.file_name);
+	} else {
+		fname = str_dup("<unnamed>");
+	}
+
+	if (fname == NULL)
+		return;
 
 	console_set_pos(con, 0, scr_rows - 1);
 	console_set_style(con, STYLE_INVERTED);
-	int n = printf(" %d, %d (%d): File '%s'. Ctrl-Q Quit  Ctrl-S Save  "
-	    "Ctrl-E Save As", coord.row, coord.column, last_row, fname);
-	
-	int pos = scr_columns - 1 - n;
+
+	/*
+	 * Make sure the status fits on the screen. This loop should
+	 * be executed at most twice.
+	 */
+	while (true) {
+		int rc = asprintf(&text, " %d, %d (%d): File '%s'. Ctrl-Q Quit  Ctrl-S Save  "
+		    "Ctrl-E Save As", coord.row, coord.column, last_row, fname);
+		if (rc < 0) {
+			n = 0;
+			goto finish;
+		}
+
+		/* If it already fits, we're done */
+		n = str_width(text);
+		if (n <= scr_columns - 2)
+			break;
+
+		/* Compute number of excess characters */
+		nextra = n - (scr_columns - 2);
+		/** With of the file name part */
+		fnw = str_width(fname);
+
+		/*
+		 * If reducing file name to two characters '..' won't help,
+		 * just give up and print a blank status.
+		 */
+		if (nextra > fnw - 2)
+			goto finish;
+
+		/* Compute position where we overwrite with '..\0' */
+		if (fnw >= nextra + 2) {
+			p = fname + str_lsize(fname, fnw - nextra - 2);
+		} else {
+			p = fname;
+		}
+
+		/* Shorten the string */
+		p[0] = p[1] = '.';
+		p[2] = '\0';
+
+		/* Need to format the string once more. */
+		free(text);
+	}
+
+	printf("%s", text);
+	free(text);
+	free(fname);
+finish:
+	/* Fill the rest of the line */
+	pos = scr_columns - 1 - n;
 	printf("%*s", pos, "");
 	console_flush(con);
Index: uspace/app/fdisk/fdisk.c
===================================================================
--- uspace/app/fdisk/fdisk.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/fdisk/fdisk.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -269,4 +269,6 @@
 	return EOK;
 error:
+	assert(rc != EOK);
+	*rsvcid = 0;
 	if (devlist != NULL)
 		fdisk_dev_list_free(devlist);
Index: uspace/app/fontviewer/fontviewer.c
===================================================================
--- uspace/app/fontviewer/fontviewer.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/fontviewer/fontviewer.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,6 +36,7 @@
 #include <stdlib.h>
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <stdbool.h>
+#include <str_error.h>
 #include <window.h>
 #include <canvas.h>
@@ -97,5 +98,5 @@
 	int rc = draw();
 	if (rc != EOK) {
-		printf("Failed drawing: %d.\n", rc);
+		printf("Failed drawing: %s.\n", str_error(rc));
 		exit(1);
 	}
@@ -276,5 +277,5 @@
 	int rc = draw();
 	if (rc != EOK) {
-		printf("Failed drawing: %d.\n", rc);
+		printf("Failed drawing: %s.\n", str_error(rc));
 		return 2;
 	}
Index: uspace/app/getterm/getterm.c
===================================================================
--- uspace/app/getterm/getterm.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/getterm/getterm.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -65,12 +65,16 @@
 	*stream = NULL;
 	
-	int oldfd = vfs_lookup_open(path, WALK_REGULAR, mode);
-	if (oldfd < 0)
+	int oldfd;
+	int rc = vfs_lookup_open(path, WALK_REGULAR, mode, &oldfd);
+	if (rc != EOK)
 		return;
 	
 	if (oldfd != fd) {
-		if (vfs_clone(oldfd, fd, false) != fd)
+		int newfd;
+		if (vfs_clone(oldfd, fd, false, &newfd) != EOK)
 			return;
 		
+		assert(newfd == fd);
+
 		if (vfs_put(oldfd))
 			return;
Index: uspace/app/inet/inet.c
===================================================================
--- uspace/app/inet/inet.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/inet/inet.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -89,5 +89,5 @@
 	rc = loc_service_get_id(link_name, &link_id, 0);
 	if (rc != EOK) {
-		printf(NAME ": Service '%s' not found (%d).\n", link_name, rc);
+		printf(NAME ": Service '%s' not found: %s.\n", link_name, str_error(rc));
 		return ENOENT;
 	}
@@ -135,5 +135,6 @@
 	rc = loc_service_get_id(link_name, &link_id, 0);
 	if (rc != EOK) {
-		printf(NAME ": Service '%s' not found (%d).\n", link_name, rc);
+		printf(NAME ": Service '%s' not found: %s.\n", link_name,
+		    str_error(rc));
 		return ENOENT;
 	}
@@ -141,5 +142,6 @@
 	rc = inetcfg_addr_get_id(aobj_name, link_id, &addr_id);
 	if (rc != EOK) {
-		printf(NAME ": Address '%s' not found (%d).\n", aobj_name, rc);
+		printf(NAME ": Address '%s' not found: %s.\n", aobj_name,
+		    str_error(rc));
 		return ENOENT;
 	}
@@ -147,6 +149,6 @@
 	rc = inetcfg_addr_delete(addr_id);
 	if (rc != EOK) {
-		printf(NAME ": Failed deleting address '%s' (%d)\n", aobj_name,
-		    rc);
+		printf(NAME ": Failed deleting address '%s': %s\n", aobj_name,
+		    str_error(rc));
 		return EIO;
 	}
@@ -197,6 +199,6 @@
 	rc = inetcfg_sroute_create(route_name, &dest, &router, &sroute_id);
 	if (rc != EOK) {
-		printf(NAME ": Failed creating static route '%s' (%d)\n",
-		    route_name, rc);
+		printf(NAME ": Failed creating static route '%s': %s\n",
+		    route_name, str_error(rc));
 		return EIO;
 	}
@@ -227,6 +229,6 @@
 	rc = inetcfg_sroute_get_id(route_name, &sroute_id);
 	if (rc != EOK) {
-		printf(NAME ": Static route '%s' not found (%d).\n",
-		    route_name, rc);
+		printf(NAME ": Static route '%s' not found: %s.\n",
+		    route_name, str_error(rc));
 		return ENOENT;
 	}
@@ -234,6 +236,6 @@
 	rc = inetcfg_sroute_delete(sroute_id);
 	if (rc != EOK) {
-		printf(NAME ": Failed deleting static route '%s' (%d)\n",
-		    route_name, rc);
+		printf(NAME ": Failed deleting static route '%s': %s\n",
+		    route_name, str_error(rc));
 		return EIO;
 	}
@@ -486,6 +488,6 @@
 	rc = inetcfg_init();
 	if (rc != EOK) {
-		printf(NAME ": Failed connecting to internet service (%d).\n",
-		    rc);
+		printf(NAME ": Failed connecting to internet service: %s.\n",
+		    str_error(rc));
 		return 1;
 	}
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/init/init.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,5 +41,5 @@
 #include <errno.h>
 #include <task.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <macros.h>
 #include <str.h>
Index: uspace/app/killall/killall.c
===================================================================
--- uspace/app/killall/killall.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/killall/killall.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,5 +39,5 @@
 #include <stats.h>
 #include <str_error.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 #define NAME  "killall"
Index: uspace/app/kio/kio.c
===================================================================
--- uspace/app/kio/kio.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/kio/kio.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -43,5 +43,5 @@
 #include <io/kio.h>
 #include <sysinfo.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <fibril_synch.h>
 #include <adt/list.h>
@@ -144,11 +144,9 @@
  * Receives kernel kio notifications.
  *
- * @param callid IPC call ID
  * @param call   IPC call structure
  * @param arg    Local argument
  *
  */
-static void kio_notification_handler(ipc_callid_t callid, ipc_call_t *call,
-    void *arg)
+static void kio_notification_handler(ipc_call_t *call, void *arg)
 {
 	/*
Index: uspace/app/mkbd/main.c
===================================================================
--- uspace/app/mkbd/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/mkbd/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -237,4 +237,6 @@
 	rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
 	if (rc != EOK) {
+		printf(NAME ": failed to get path (handle %"
+		       PRIun "): %s.\n", dev_handle, str_error(errno));
 		return ENOMEM;
 	}
@@ -262,4 +264,5 @@
 	uint8_t *event = (uint8_t *)malloc(size);
 	if (event == NULL) {
+		printf("Out of memory.\n");
 		// TODO: hangup phone?
 		return ENOMEM;
Index: uspace/app/mkexfat/mkexfat.c
===================================================================
--- uspace/app/mkexfat/mkexfat.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/mkexfat/mkexfat.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -43,5 +43,5 @@
 #include <assert.h>
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <byteorder.h>
 #include <align.h>
Index: uspace/app/modplay/modplay.c
===================================================================
--- uspace/app/modplay/modplay.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/modplay/modplay.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,4 +40,5 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <str_error.h>
 #include <trackmod.h>
 
@@ -117,5 +118,5 @@
 	rc = hound_context_connect_target(hound, HOUND_DEFAULT_TARGET);
 	if (rc != EOK) {
-		printf("Error connecting default audio target (%d).\n", rc);
+		printf("Error connecting default audio target: %s.\n", str_error(rc));
 		return 1;
 	}
Index: uspace/app/netstart/self_test.c
===================================================================
--- uspace/app/netstart/self_test.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/netstart/self_test.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,5 +37,5 @@
 
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <stdio.h>
 
Index: uspace/app/nterm/conn.c
===================================================================
--- uspace/app/nterm/conn.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/nterm/conn.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -75,5 +75,5 @@
 		rc = tcp_conn_recv(conn, recv_buf, RECV_BUF_SIZE, &nrecv);
 		if (rc != EOK) {
-			printf("\n[Receive error %d]\n", rc);
+			printf("\n[Receive error: %s]\n", str_error_name(rc));
 			break;
 		}
Index: uspace/app/ping/ping.c
===================================================================
--- uspace/app/ping/ping.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/ping/ping.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -145,6 +145,6 @@
 	int rc = inetping_send(&sdu);
 	if (rc != EOK)
-		printf("Failed sending echo request: %s (%d).\n",
-		    str_error(rc), rc);
+		printf("Failed sending echo request: %s: %s.\n",
+		    str_error_name(rc), str_error(rc));
 	
 	return rc;
@@ -225,5 +225,5 @@
 	if (rc != EOK) {
 		printf("Failed connecting to internet ping service: "
-		    "%s (%d).\n", str_error(rc), rc);
+		    "%s: %s.\n", str_error_name(rc), str_error(rc));
 		goto error;
 	}
Index: uspace/app/rcutest/rcutest.c
===================================================================
--- uspace/app/rcutest/rcutest.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/rcutest/rcutest.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,4 +38,5 @@
 #include <stdlib.h>
 #include <stdint.h>
+#include <str_error.h>
 #include <mem.h>
 #include <errno.h>
@@ -780,5 +781,5 @@
 		int ret = thread_create(dummy_fibril, NULL, "urcu-test-worker", &tid);
 		if (EOK != ret) {
-			printf("Failed to create thread '%zu' (error: %d)\n", k + 1, ret);
+			printf("Failed to create thread '%zu' (error: %s)\n", k + 1, str_error_name(ret));
 			return false;
 		}
Index: uspace/app/redir/redir.c
===================================================================
--- uspace/app/redir/redir.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/redir/redir.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -59,12 +59,16 @@
 	*stream = NULL;
 	
-	int oldfd = vfs_lookup_open(path, WALK_REGULAR | flags, mode);
-	if (oldfd < 0)
+	int oldfd;
+	int rc = vfs_lookup_open(path, WALK_REGULAR | flags, mode, &oldfd);
+	if (rc != EOK)
 		return;
 	
 	if (oldfd != fd) {
-		if (vfs_clone(oldfd, fd, false) != fd)
+		int newfd;
+		if (vfs_clone(oldfd, fd, false, &newfd) != EOK)
 			return;
 		
+		assert(newfd == fd);
+
 		if (vfs_put(oldfd))
 			return;
Index: uspace/app/sportdmp/sportdmp.c
===================================================================
--- uspace/app/sportdmp/sportdmp.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/sportdmp/sportdmp.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -27,9 +27,10 @@
  */
 
-#include <char_dev_iface.h>
 #include <errno.h>
-#include <ipc/serial_ctl.h>
+#include <io/chardev.h>
+#include <io/serial.h>
 #include <loc.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #define BUF_SIZE 1
@@ -44,4 +45,7 @@
 	sysarg_t baud = 9600;
 	service_id_t svc_id;
+	chardev_t *chardev;
+	serial_t *serial;
+	size_t nread;
 
 	int arg = 1;
@@ -113,13 +117,22 @@
 	async_sess_t *sess = loc_service_connect(svc_id, INTERFACE_DDF,
 	    IPC_FLAG_BLOCKING);
-	if (!sess) {
+	if (sess == NULL) {
 		fprintf(stderr, "Failed connecting to service\n");
+		return 2;
 	}
 
-	async_exch_t *exch = async_exchange_begin(sess);
-	rc = async_req_4_0(exch, SERIAL_SET_COM_PROPS, baud,
-	    SERIAL_NO_PARITY, 8, 1);
-	async_exchange_end(exch);
+	rc = chardev_open(sess, &chardev);
+	if (rc != EOK) {
+		fprintf(stderr, "Failed opening character device\n");
+		return 2;
+	}
 
+	rc = serial_open(sess, &serial);
+	if (rc != EOK) {
+		fprintf(stderr, "Failed opening serial port\n");
+		return 2;
+	}
+
+	rc = serial_set_comm_props(serial, baud, SERIAL_NO_PARITY, 8, 1);
 	if (rc != EOK) {
 		fprintf(stderr, "Failed setting serial properties\n");
@@ -134,12 +147,11 @@
 
 	while (true) {
-		ssize_t read = char_dev_read(sess, buf, BUF_SIZE);
-		if (read < 0) {
-			fprintf(stderr, "Failed reading from serial device\n");
+		rc = chardev_read(chardev, buf, BUF_SIZE, &nread);
+		for (size_t i = 0; i < nread; i++) {
+			printf("%02hhx ", buf[i]);
+		}
+		if (rc != EOK) {
+			fprintf(stderr, "\nFailed reading from serial device\n");
 			break;
-		}
-		ssize_t i;
-		for (i = 0; i < read; i++) {
-			printf("%02hhx ", buf[i]);
 		}
 		fflush(stdout);
@@ -147,4 +159,7 @@
 
 	free(buf);
+	serial_close(serial);
+	chardev_close(chardev);
+	async_hangup(sess);
 	return 0;
 }
Index: uspace/app/stats/stats.c
===================================================================
--- uspace/app/stats/stats.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/stats/stats.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -42,5 +42,5 @@
 #include <errno.h>
 #include <stdlib.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <inttypes.h>
 #include <stdbool.h>
Index: uspace/app/sysinfo/sysinfo.c
===================================================================
--- uspace/app/sysinfo/sysinfo.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/sysinfo/sysinfo.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,5 +39,5 @@
 #include <stdint.h>
 #include <sysinfo.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 static void dump_bytes_hex(char *data, size_t size)
Index: uspace/app/sysinst/futil.c
===================================================================
--- uspace/app/sysinst/futil.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/sysinst/futil.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -57,5 +57,5 @@
 {
 	int sf, df;
-	ssize_t nr, nw;
+	size_t nr, nw;
 	int rc;
 	aoff64_t posr = 0, posw = 0;
@@ -63,31 +63,36 @@
 	printf("Copy '%s' to '%s'.\n", srcp, destp);
 
-	sf = vfs_lookup_open(srcp, WALK_REGULAR, MODE_READ);
-	if (sf < 0)
-		return EIO;
-
-	df = vfs_lookup_open(destp, WALK_REGULAR | WALK_MAY_CREATE, MODE_WRITE);
-	if (df < 0)
+	rc = vfs_lookup_open(srcp, WALK_REGULAR, MODE_READ, &sf);
+	if (rc != EOK)
+		return EIO;
+
+	rc = vfs_lookup_open(destp, WALK_REGULAR | WALK_MAY_CREATE, MODE_WRITE, &df);
+	if (rc != EOK)
 		return EIO;
 
 	do {
-		nr = vfs_read(sf, &posr, buf, BUF_SIZE);
+		rc = vfs_read(sf, &posr, buf, BUF_SIZE, &nr);
+		if (rc != EOK)
+			goto error;
 		if (nr == 0)
 			break;
-		if (nr < 0)
-			return EIO;
-
-		nw = vfs_write(df, &posw, buf, nr);
-		if (nw <= 0)
-			return EIO;
-	} while (true);
+
+		rc= vfs_write(df, &posw, buf, nr, &nw);
+		if (rc != EOK)
+			goto error;
+
+	} while (nr == BUF_SIZE);
 
 	(void) vfs_put(sf);
 
 	rc = vfs_put(df);
-	if (rc < 0)
+	if (rc != EOK)
 		return EIO;
 
 	return EOK;
+error:
+	vfs_put(sf);
+	vfs_put(df);
+	return rc;
 }
 
@@ -156,11 +161,12 @@
 {
 	int sf;
-	ssize_t nr;
+	size_t nr;
+	int rc;
 	size_t fsize;
 	char *data;
 	struct stat st;
 
-	sf = vfs_lookup_open(srcp, WALK_REGULAR, MODE_READ);
-	if (sf < 0)
+	rc = vfs_lookup_open(srcp, WALK_REGULAR, MODE_READ, &sf);
+	if (rc != EOK)
 		return ENOENT;
 
@@ -168,5 +174,5 @@
 		vfs_put(sf);
 		return EIO;
-	}	
+	}
 
 	fsize = st.size;
@@ -178,6 +184,6 @@
 	}
 
-	nr = vfs_read(sf, (aoff64_t []) { 0 }, data, fsize);
-	if (nr != (ssize_t)fsize) {
+	rc = vfs_read(sf, (aoff64_t []) { 0 }, data, fsize, &nr);
+	if (rc != EOK || nr != fsize) {
 		vfs_put(sf);
 		free(data);
Index: uspace/app/sysinst/sysinst.c
===================================================================
--- uspace/app/sysinst/sysinst.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/sysinst/sysinst.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,4 +44,5 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <str_error.h>
 #include <task.h>
 #include <vfs/vfs.h>
@@ -117,5 +118,5 @@
 	rc = fdisk_label_create(fdev, lt_mbr);
 	if (rc != EOK) {
-		printf("Error creating label (%d).\n", rc);
+		printf("Error creating label: %s.\n", str_error(rc));
 		return rc;
 	}
@@ -125,5 +126,5 @@
 	rc = fdisk_part_get_max_avail(fdev, spc_pri, &cap);
 	if (rc != EOK) {
-		printf("Error getting available capacity (%d).\n", rc);
+		printf("Error getting available capacity: %s.\n", str_error(rc));
 		return rc;
 	}
Index: uspace/app/taskdump/elf_core.c
===================================================================
--- uspace/app/taskdump/elf_core.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/taskdump/elf_core.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -55,4 +55,5 @@
 #include <stddef.h>
 #include <errno.h>
+#include <str_error.h>
 #include <mem.h>
 #include <as.h>
@@ -97,5 +98,6 @@
 
 	int fd;
-	ssize_t rc;
+	int rc;
+	size_t nwr;
 	unsigned int i;
 
@@ -122,8 +124,8 @@
 	}
 
-	fd = vfs_lookup_open(file_name, WALK_REGULAR | WALK_MAY_CREATE,
-	    MODE_WRITE);
-	if (fd < 0) {
-		printf("Failed opening file.\n");
+	rc = vfs_lookup_open(file_name, WALK_REGULAR | WALK_MAY_CREATE,
+	    MODE_WRITE, &fd);
+	if (rc != EOK) {
+		printf("Failed opening file '%s': %s.\n", file_name, str_error(rc));
 		free(p_hdr);
 		return ENOENT;
@@ -206,6 +208,6 @@
 	}
 
-	rc = vfs_write(fd, &pos, &elf_hdr, sizeof(elf_hdr));
-	if (rc != sizeof(elf_hdr)) {
+	rc = vfs_write(fd, &pos, &elf_hdr, sizeof(elf_hdr), &nwr);
+	if (rc != EOK) {
 		printf("Failed writing ELF header.\n");
 		free(p_hdr);
@@ -214,6 +216,6 @@
 
 	for (i = 0; i < n_ph; ++i) {
-		rc = vfs_write(fd, &pos, &p_hdr[i], sizeof(p_hdr[i]));
-		if (rc != sizeof(p_hdr[i])) {
+		rc = vfs_write(fd, &pos, &p_hdr[i], sizeof(p_hdr[i]), &nwr);
+		if (rc != EOK) {
 			printf("Failed writing program header.\n");
 			free(p_hdr);
@@ -231,6 +233,6 @@
 	note.type = NT_PRSTATUS;
 
-	rc = vfs_write(fd, &pos, &note, sizeof(elf_note_t));
-	if (rc != sizeof(elf_note_t)) {
+	rc = vfs_write(fd, &pos, &note, sizeof(elf_note_t), &nwr);
+	if (rc != EOK) {
 		printf("Failed writing note header.\n");
 		free(p_hdr);
@@ -238,6 +240,6 @@
 	}
 
-	rc = vfs_write(fd, &pos, "CORE", note.namesz);
-	if (rc != (ssize_t) note.namesz) {
+	rc = vfs_write(fd, &pos, "CORE", note.namesz, &nwr);
+	if (rc != EOK) {
 		printf("Failed writing note header.\n");
 		free(p_hdr);
@@ -247,6 +249,6 @@
 	pos = ALIGN_UP(pos, word_size);
 
-	rc = vfs_write(fd, &pos, &pr_status, sizeof(elf_prstatus_t));
-	if (rc != sizeof(elf_prstatus_t)) {
+	rc = vfs_write(fd, &pos, &pr_status, sizeof(elf_prstatus_t), &nwr);
+	if (rc != EOK) {
 		printf("Failed writing register data.\n");
 		free(p_hdr);
@@ -296,5 +298,6 @@
 	size_t total;
 	uintptr_t addr;
-	ssize_t rc;
+	int rc;
+	size_t nwr;
 
 	addr = area->start_addr;
@@ -309,6 +312,6 @@
 		}
 
-		rc = vfs_write(fd, pos, buffer, to_copy);
-		if (rc != (ssize_t) to_copy) {
+		rc = vfs_write(fd, pos, buffer, to_copy, &nwr);
+		if (rc != EOK) {
 			printf("Failed writing memory contents.\n");
 			return EIO;
Index: uspace/app/taskdump/symtab.c
===================================================================
--- uspace/app/taskdump/symtab.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/taskdump/symtab.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,4 +41,5 @@
 #include <stddef.h>
 #include <errno.h>
+#include <str_error.h>
 #include <vfs/vfs.h>
 
@@ -71,4 +72,5 @@
 	int fd;
 	int rc;
+	size_t nread;
 	int i;
 
@@ -81,13 +83,13 @@
 		return ENOMEM;
 
-	fd = vfs_lookup_open(file_name, WALK_REGULAR, MODE_READ);
-	if (fd < 0) {
-		printf("failed opening file\n");
+	rc = vfs_lookup_open(file_name, WALK_REGULAR, MODE_READ, &fd);
+	if (rc != EOK) {
+		printf("failed opening file '%s': %s\n", file_name, str_error(rc));
 		free(stab);
 		return ENOENT;
 	}
 
-	rc = vfs_read(fd, &pos, &elf_hdr, sizeof(elf_header_t));
-	if (rc != sizeof(elf_header_t)) {
+	rc = vfs_read(fd, &pos, &elf_hdr, sizeof(elf_header_t), &nread);
+	if (rc != EOK || nread != sizeof(elf_header_t)) {
 		printf("failed reading elf header\n");
 		free(stab);
@@ -304,8 +306,9 @@
 {
 	int rc;
+	size_t nread;
 	aoff64_t pos = elf_hdr->e_shoff + idx * sizeof(elf_section_header_t);
 
-	rc = vfs_read(fd, &pos, sec_hdr, sizeof(elf_section_header_t));
-	if (rc != sizeof(elf_section_header_t))
+	rc = vfs_read(fd, &pos, sec_hdr, sizeof(elf_section_header_t), &nread);
+	if (rc != EOK || nread != sizeof(elf_section_header_t))
 		return EIO;
 
@@ -326,5 +329,6 @@
 static int chunk_load(int fd, off64_t start, size_t size, void **ptr)
 {
-	ssize_t rc;
+	int rc;
+	size_t nread;
 	aoff64_t pos = start;
 
@@ -335,6 +339,6 @@
 	}
 
-	rc = vfs_read(fd, &pos, *ptr, size);
-	if (rc != (ssize_t) size) {
+	rc = vfs_read(fd, &pos, *ptr, size, &nread);
+	if (rc != EOK || nread != size) {
 		printf("failed reading chunk\n");
 		free(*ptr);
Index: uspace/app/taskdump/taskdump.c
===================================================================
--- uspace/app/taskdump/taskdump.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/taskdump/taskdump.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,4 +40,5 @@
 #include <stddef.h>
 #include <stdbool.h>
+#include <str_error.h>
 #include <errno.h>
 #include <udebug.h>
@@ -135,5 +136,5 @@
 		
 		printf("Error connecting\n");
-		printf("async_connect_kbox(%" PRIu64 ") -> %d ", task_id, errno);
+		printf("async_connect_kbox(%" PRIu64 ") -> %s", task_id, str_error_name(errno));
 		return errno;
 	}
@@ -141,5 +142,5 @@
 	int rc = udebug_begin(ksess);
 	if (rc < 0) {
-		printf("udebug_begin() -> %d\n", rc);
+		printf("udebug_begin() -> %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -223,5 +224,5 @@
 	rc = udebug_thread_read(sess, &dummy_buf, 0, &copied, &needed);
 	if (rc < 0) {
-		printf("udebug_thread_read() -> %d\n", rc);
+		printf("udebug_thread_read() -> %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -237,5 +238,5 @@
 	rc = udebug_thread_read(sess, thash_buf, buf_size, &copied, &needed);
 	if (rc < 0) {
-		printf("udebug_thread_read() -> %d\n", rc);
+		printf("udebug_thread_read() -> %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -272,5 +273,5 @@
 	rc = udebug_areas_read(sess, &dummy_buf, 0, &copied, &needed);
 	if (rc < 0) {
-		printf("udebug_areas_read() -> %d\n", rc);
+		printf("udebug_areas_read() -> %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -281,5 +282,5 @@
 	rc = udebug_areas_read(sess, ainfo_buf, buf_size, &copied, &needed);
 	if (rc < 0) {
-		printf("udebug_areas_read() -> %d\n", rc);
+		printf("udebug_areas_read() -> %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -357,5 +358,5 @@
 	rc = udebug_regs_read(sess, thash, &istate);
 	if (rc < 0) {
-		printf("Failed reading registers (%d).\n", rc);
+		printf("Failed reading registers: %s.\n", str_error_name(rc));
 		return EIO;
 	}
Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -68,6 +68,6 @@
 	mm/mapping1.c \
 	mm/pager1.c \
-	hw/misc/virtchar1.c \
-	hw/serial/serial1.c
+	hw/serial/serial1.c \
+	chardev/chardev1.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/tester/chardev/chardev1.c
===================================================================
--- uspace/app/tester/chardev/chardev1.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/app/tester/chardev/chardev1.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2017 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <str_error.h>
+#include <ipc/services.h>
+#include <io/chardev.h>
+#include <loc.h>
+#include "../tester.h"
+
+#define SMALL_BUFFER_SIZE 64
+#define LARGE_BUFFER_SIZE (DATA_XFER_LIMIT * 4)
+
+static char small_buffer[SMALL_BUFFER_SIZE];
+static char large_buffer[LARGE_BUFFER_SIZE];
+
+/** Test device that always performs small transfers. */
+static const char *test_chardev1_smallx(void)
+{
+	chardev_t *chardev;
+	service_id_t sid;
+	async_sess_t *sess;
+	size_t nbytes;
+	int rc;
+
+	TPRINTF("Test small transfer character device operations\n");
+
+	rc = loc_service_get_id(SERVICE_NAME_CHARDEV_TEST_SMALLX, &sid, 0);
+	if (rc != EOK) {
+		return "Failed resolving test device "
+		    SERVICE_NAME_CHARDEV_TEST_SMALLX;
+	}
+
+	sess = loc_service_connect(sid, INTERFACE_DDF, 0);
+	if (sess == NULL)
+		return "Failed connecting test device";
+
+	rc = chardev_open(sess, &chardev);
+	if (rc != EOK) {
+		async_hangup(sess);
+		return "Failed opening test device";
+	}
+
+	rc = chardev_write(chardev, small_buffer, SMALL_BUFFER_SIZE, &nbytes);
+	if (rc != EOK) {
+		chardev_close(chardev);
+		async_hangup(sess);
+		return "Failed sending data";
+	}
+
+	TPRINTF("Sent %zu bytes\n", nbytes);
+
+	rc = chardev_read(chardev, small_buffer, SMALL_BUFFER_SIZE, &nbytes);
+	if (rc != EOK) {
+		chardev_close(chardev);
+		async_hangup(sess);
+		return "Failed receiving data";
+	}
+
+	TPRINTF("Received %zu bytes\n", nbytes);
+
+	chardev_close(chardev);
+	async_hangup(sess);
+
+	TPRINTF("Done\n");
+	return NULL;
+}
+
+/** Test device that always performs large transfers. */
+static const char *test_chardev1_largex(void)
+{
+	chardev_t *chardev;
+	service_id_t sid;
+	async_sess_t *sess;
+	size_t nbytes;
+	int rc;
+
+	TPRINTF("Test large transfer character device operations\n");
+
+	rc = loc_service_get_id(SERVICE_NAME_CHARDEV_TEST_LARGEX, &sid, 0);
+	if (rc != EOK) {
+		return "Failed resolving test device "
+		    SERVICE_NAME_CHARDEV_TEST_LARGEX;
+	}
+
+	sess = loc_service_connect(sid, INTERFACE_DDF, 0);
+	if (sess == NULL)
+		return "Failed connecting test device";
+
+	rc = chardev_open(sess, &chardev);
+	if (rc != EOK) {
+		async_hangup(sess);
+		return "Failed opening test device";
+	}
+
+	rc = chardev_write(chardev, large_buffer, LARGE_BUFFER_SIZE, &nbytes);
+	if (rc != EOK) {
+		chardev_close(chardev);
+		async_hangup(sess);
+		return "Failed sending data";
+	}
+
+	TPRINTF("Sent %zu bytes\n", nbytes);
+
+	rc = chardev_read(chardev, large_buffer, LARGE_BUFFER_SIZE, &nbytes);
+	if (rc != EOK) {
+		chardev_close(chardev);
+		async_hangup(sess);
+		return "Failed receiving data";
+	}
+
+	TPRINTF("Received %zu bytes\n", nbytes);
+
+	chardev_close(chardev);
+	async_hangup(sess);
+
+	TPRINTF("Done\n");
+	return NULL;
+}
+
+/** Test device where all transfers return partial success. */
+static const char *test_chardev1_partialx(void)
+{
+	chardev_t *chardev;
+	service_id_t sid;
+	async_sess_t *sess;
+	size_t nbytes;
+	int rc;
+
+	TPRINTF("Test partially-successful character device operations\n");
+
+	rc = loc_service_get_id(SERVICE_NAME_CHARDEV_TEST_PARTIALX, &sid, 0);
+	if (rc != EOK) {
+		return "Failed resolving test device "
+		    SERVICE_NAME_CHARDEV_TEST_SMALLX;
+	}
+
+	sess = loc_service_connect(sid, INTERFACE_DDF, 0);
+	if (sess == NULL)
+		return "Failed connecting test device";
+
+	rc = chardev_open(sess, &chardev);
+	if (rc != EOK) {
+		async_hangup(sess);
+		return "Failed opening test device";
+	}
+
+	rc = chardev_write(chardev, small_buffer, SMALL_BUFFER_SIZE, &nbytes);
+	if (rc != EIO || nbytes != 1) {
+		chardev_close(chardev);
+		async_hangup(sess);
+		return "Failed sending data";
+	}
+
+	TPRINTF("Sent %zu bytes and got rc = %s (expected)\n", nbytes,
+	    str_error_name(rc));
+
+	rc = chardev_read(chardev, small_buffer, SMALL_BUFFER_SIZE, &nbytes);
+	if (rc != EIO || nbytes != 1) {
+		chardev_close(chardev);
+		async_hangup(sess);
+		return "Failed receiving data";
+	}
+
+	TPRINTF("Received %zu bytes and got rc = %s (expected)\n", nbytes,
+	    str_error_name(rc));
+
+	chardev_close(chardev);
+	async_hangup(sess);
+
+	TPRINTF("Done\n");
+	return NULL;
+}
+
+const char *test_chardev1(void)
+{
+	const char *s;
+
+	s = test_chardev1_smallx();
+	if (s != NULL)
+		return s;
+
+	s = test_chardev1_largex();
+	if (s != NULL)
+		return s;
+
+	return test_chardev1_partialx();;
+}
Index: uspace/app/tester/chardev/chardev1.def
===================================================================
--- uspace/app/tester/chardev/chardev1.def	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/app/tester/chardev/chardev1.def	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,6 @@
+{
+	"chardev1",
+	"Character device basic functionality",
+	&test_chardev1,
+	false
+},
Index: pace/app/tester/hw/misc/virtchar1.c
===================================================================
--- uspace/app/tester/hw/misc/virtchar1.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,106 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 tester
- * @brief Test the virtual char driver
- * @{
- */
-/**
- * @file
- */
-
-#include <inttypes.h>
-#include <errno.h>
-#include <str_error.h>
-#include <stddef.h>
-#include <async.h>
-#include <char_dev_iface.h>
-#include <str.h>
-#include <vfs/vfs.h>
-#include <vfs/vfs_sess.h>
-#include "../../tester.h"
-
-#define DEVICE_PATH_NORMAL  "/loc/devices/\\virt\\null\\a"
-
-#define BUFFER_SIZE  64
-
-static const char *test_virtchar1_internal(const char *path)
-{
-	TPRINTF("Opening `%s'...\n", path);
-	int fd = vfs_lookup(path, WALK_REGULAR);
-	if (fd < 0) {
-		TPRINTF("   ...error: %s\n", str_error(errno));
-		if (fd == ENOENT) {
-			TPRINTF("   (error was ENOENT: " \
-			    "have you compiled test drivers?)\n");
-		}
-		return "Failed opening NULL device for reading";
-	}
-	
-	TPRINTF("   ...file handle %d\n", fd);
-	
-	TPRINTF(" Asking for session...\n");
-	async_sess_t *sess = vfs_fd_session(fd, INTERFACE_DDF);
-	if (!sess) {
-		vfs_put(fd);
-		TPRINTF("   ...error: %s\n", str_error(errno));
-		return "Failed to get session to device";
-	}
-	TPRINTF("   ...session is %p\n", sess);
-	
-	TPRINTF(" Will try to read...\n");
-	size_t i;
-	char buffer[BUFFER_SIZE];
-	char_dev_read(sess, buffer, BUFFER_SIZE);
-	TPRINTF(" ...verifying that we read zeroes only...\n");
-	for (i = 0; i < BUFFER_SIZE; i++) {
-		if (buffer[i] != 0) {
-			return "Not all bytes are zeroes";
-		}
-	}
-	TPRINTF("   ...data read okay\n");
-	
-	/* Clean-up. */
-	TPRINTF(" Closing session and file descriptor\n");
-	async_hangup(sess);
-	vfs_put(fd);
-	
-	return NULL;
-}
-
-const char *test_virtchar1(void)
-{
-	const char *res = test_virtchar1_internal(DEVICE_PATH_NORMAL);
-	if (res != NULL)
-		return res;
-	
-	return NULL;
-}
-
-/** @}
- */
Index: pace/app/tester/hw/misc/virtchar1.def
===================================================================
--- uspace/app/tester/hw/misc/virtchar1.def	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"virtchar1",
-	"Virtual char device test",
-	&test_virtchar1,
-	false
-},
Index: uspace/app/tester/hw/serial/serial1.c
===================================================================
--- uspace/app/tester/hw/serial/serial1.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/hw/serial/serial1.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,16 +35,14 @@
  */
 
-#include <inttypes.h>
+#include <async.h>
 #include <errno.h>
+#include <io/chardev.h>
+#include <io/serial.h>
+#include <ipc/services.h>
+#include <loc.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stddef.h>
-#include <async.h>
-#include <thread.h>
-#include <ipc/services.h>
-#include <loc.h>
-#include <char_dev_iface.h>
 #include <str.h>
-#include <ipc/serial_ctl.h>
 #include "../../tester.h"
 
@@ -56,4 +54,9 @@
 {
 	size_t cnt;
+	serial_t *serial;
+	chardev_t *chardev;
+	int rc;
+	size_t nread;
+	size_t nwritten;
 	
 	if (test_argc < 1)
@@ -79,36 +82,48 @@
 	async_sess_t *sess = loc_service_connect(svc_id, INTERFACE_DDF,
 	    IPC_FLAG_BLOCKING);
-	if (!sess)
+	if (sess == NULL)
 		return "Failed connecting to serial device";
+	
+	res = chardev_open(sess, &chardev);
+	if (res != EOK) {
+		async_hangup(sess);
+		return "Failed opening serial port";
+	}
+	
+	res = serial_open(sess, &serial);
+	if (res != EOK) {
+		chardev_close(chardev);
+		async_hangup(sess);
+		return "Failed opening serial port";
+	}
 	
 	char *buf = (char *) malloc(cnt + 1);
 	if (buf == NULL) {
+		chardev_close(chardev);
+		serial_close(serial);
 		async_hangup(sess);
 		return "Failed allocating input buffer";
 	}
 	
-	sysarg_t old_baud;
-	sysarg_t old_par;
-	sysarg_t old_stop;
-	sysarg_t old_word_size;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	res = async_req_0_4(exch, SERIAL_GET_COM_PROPS, &old_baud,
-	    &old_par, &old_word_size, &old_stop);
-	async_exchange_end(exch);
-	
+	unsigned old_baud;
+	serial_parity_t old_par;
+	unsigned old_stop;
+	unsigned old_word_size;
+	
+	res = serial_get_comm_props(serial, &old_baud, &old_par,
+	    &old_word_size, &old_stop);
 	if (res != EOK) {
 		free(buf);
+		chardev_close(chardev);
+		serial_close(serial);
 		async_hangup(sess);
 		return "Failed to get old serial communication parameters";
 	}
 	
-	exch = async_exchange_begin(sess);
-	res = async_req_4_0(exch, SERIAL_SET_COM_PROPS, 1200,
-	    SERIAL_NO_PARITY, 8, 1);
-	async_exchange_end(exch);
-	
+	res = serial_set_comm_props(serial, 1200, SERIAL_NO_PARITY, 8, 1);
 	if (EOK != res) {
 		free(buf);
+		chardev_close(chardev);
+		serial_close(serial);
 		async_hangup(sess);
 		return "Failed setting serial communication parameters";
@@ -120,67 +135,62 @@
 	size_t total = 0;
 	while (total < cnt) {
-		ssize_t read = char_dev_read(sess, buf, cnt - total);
-		
-		if (read < 0) {
-			exch = async_exchange_begin(sess);
-			async_req_4_0(exch, SERIAL_SET_COM_PROPS, old_baud,
-			    old_par, old_word_size, old_stop);
-			async_exchange_end(exch);
-			
-			free(buf);
+		
+		rc = chardev_read(chardev, buf, cnt - total, &nread);
+		if (rc != EOK) {
+			(void) serial_set_comm_props(serial, old_baud,
+			    old_par, old_word_size, old_stop);
+			
+			free(buf);
+			chardev_close(chardev);
+			serial_close(serial);
 			async_hangup(sess);
 			return "Failed reading from serial device";
 		}
 		
-		if ((size_t) read > cnt - total) {
-			exch = async_exchange_begin(sess);
-			async_req_4_0(exch, SERIAL_SET_COM_PROPS, old_baud,
-			    old_par, old_word_size, old_stop);
-			async_exchange_end(exch);
-			
-			free(buf);
+		if (nread > cnt - total) {
+			(void) serial_set_comm_props(serial, old_baud,
+			    old_par, old_word_size, old_stop);
+			
+			free(buf);
+			chardev_close(chardev);
+			serial_close(serial);
 			async_hangup(sess);
 			return "Read more data than expected";
 		}
 		
-		TPRINTF("Read %zd bytes\n", read);
-		
-		if (read == 0)
-			thread_usleep(DEFAULT_SLEEP);
-		else {
-			buf[read] = 0;
-			
-			/*
-			 * Write data back to the device to test the opposite
-			 * direction of data transfer.
-			 */
-			ssize_t written = char_dev_write(sess, buf, read);
-			
-			if (written < 0) {
-				exch = async_exchange_begin(sess);
-				async_req_4_0(exch, SERIAL_SET_COM_PROPS, old_baud,
-				    old_par, old_word_size, old_stop);
-				async_exchange_end(exch);
-				
-				free(buf);
-				async_hangup(sess);
-				return "Failed writing to serial device";
-			}
-			
-			if (written != read) {
-				exch = async_exchange_begin(sess);
-				async_req_4_0(exch, SERIAL_SET_COM_PROPS, old_baud,
-				    old_par, old_word_size, old_stop);
-				async_exchange_end(exch);
-				
-				free(buf);
-				async_hangup(sess);
-				return "Written less data than read from serial device";
-			}
-			
-			TPRINTF("Written %zd bytes\n", written);
-		}
-		
-		total += read;
+		TPRINTF("Read %zd bytes\n", nread);
+		
+		buf[nread] = 0;
+		
+		/*
+		 * Write data back to the device to test the opposite
+		 * direction of data transfer.
+		 */
+		rc = chardev_write(chardev, buf, nread, &nwritten);
+		if (rc != EOK) {
+			(void) serial_set_comm_props(serial, old_baud,
+			    old_par, old_word_size, old_stop);
+			
+			free(buf);
+			chardev_close(chardev);
+			serial_close(serial);
+			async_hangup(sess);
+			return "Failed writing to serial device";
+		}
+		
+		if (nwritten != nread) {
+			(void) serial_set_comm_props(serial, old_baud,
+			    old_par, old_word_size, old_stop);
+			
+			free(buf);
+			chardev_close(chardev);
+			serial_close(serial);
+			async_hangup(sess);
+			return "Written less data than read from serial device";
+		}
+		
+		TPRINTF("Written %zd bytes\n", nwritten);
+		
+		total += nread;
 	}
 	
@@ -188,18 +198,18 @@
 	
 	size_t eot_size = str_size(EOT);
-	ssize_t written = char_dev_write(sess, (void *) EOT, eot_size);
-	
-	exch = async_exchange_begin(sess);
-	async_req_4_0(exch, SERIAL_SET_COM_PROPS, old_baud,
-	    old_par, old_word_size, old_stop);
-	async_exchange_end(exch);
+	rc = chardev_write(chardev, (void *) EOT, eot_size, &nwritten);
+	
+	(void) serial_set_comm_props(serial, old_baud, old_par, old_word_size,
+	    old_stop);
 	
 	free(buf);
+	chardev_close(chardev);
+	serial_close(serial);
 	async_hangup(sess);
 	
-	if (written < 0)
+	if (rc != EOK)
 		return "Failed to write EOT banner to serial device";
 	
-	if ((size_t) written != eot_size)
+	if (nwritten != eot_size)
 		return "Written less data than the size of the EOT banner "
 		    "to serial device";
Index: uspace/app/tester/mm/common.c
===================================================================
--- uspace/app/tester/mm/common.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/mm/common.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -29,5 +29,5 @@
  */
 
-#include <malloc.h>
+#include <stdlib.h>
 #include <as.h>
 #include <adt/list.h>
Index: uspace/app/tester/mm/malloc2.c
===================================================================
--- uspace/app/tester/mm/malloc2.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/mm/malloc2.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,5 +30,4 @@
 #include <stdlib.h>
 #include <stddef.h>
-#include <malloc.h>
 #include "../tester.h"
 
Index: uspace/app/tester/mm/mapping1.c
===================================================================
--- uspace/app/tester/mm/mapping1.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/mm/mapping1.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,5 +30,5 @@
 #include <stdlib.h>
 #include <stddef.h>
-#include <malloc.h>
+#include <str_error.h>
 #include <as.h>
 #include <errno.h>
@@ -75,6 +75,6 @@
 		int rc = as_get_physical_mapping(page_start, NULL);
 		if (rc != expected_rc) {
-			TPRINTF("as_get_physical_mapping() = %d != %d\n",
-			    rc, expected_rc);
+			TPRINTF("as_get_physical_mapping() = %s != %s\n",
+			    str_error_name(rc), str_error_name(expected_rc));
 			return false;
 		}
Index: uspace/app/tester/mm/pager1.c
===================================================================
--- uspace/app/tester/mm/pager1.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/mm/pager1.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,5 +30,4 @@
 #include <vfs/vfs.h>
 #include <stdlib.h>
-#include <malloc.h>
 #include <as.h>
 #include <ns.h>
@@ -45,13 +44,17 @@
 static void *create_paged_area(size_t size)
 {
+	size_t nwr;
+	int rc;
+
 	TPRINTF("Creating temporary file...\n");
 
-	fd = vfs_lookup_open(TEST_FILE, WALK_REGULAR | WALK_MAY_CREATE,
-	    MODE_READ | MODE_WRITE);
-	if (fd < 0)
+	rc = vfs_lookup_open(TEST_FILE, WALK_REGULAR | WALK_MAY_CREATE,
+	    MODE_READ | MODE_WRITE, &fd);
+	if (rc != EOK)
 		return NULL;
 	(void) vfs_unlink_path(TEST_FILE);
 
-	if (vfs_write(fd, (aoff64_t []) {0}, text, sizeof(text)) < 0) {
+	rc = vfs_write(fd, (aoff64_t []) {0}, text, sizeof(text), &nwr);
+	if (rc != EOK) {
 		vfs_put(fd);
 		return NULL;
Index: uspace/app/tester/stdio/stdio1.c
===================================================================
--- uspace/app/tester/stdio/stdio1.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/stdio/stdio1.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,4 +30,5 @@
 #include <stdlib.h>
 #include <stddef.h>
+#include <str_error.h>
 #include <errno.h>
 #include "../tester.h"
@@ -46,5 +47,5 @@
 	file = fopen(file_name, "rt");
 	if (file == NULL) {
-		TPRINTF("errno = %d\n", errno);
+		TPRINTF("errno = %s\n", str_error_name(errno));
 		return "Failed opening file";
 	} else
@@ -54,5 +55,5 @@
 	size_t cnt = fread(buf, 1, BUF_SIZE, file);
 	if (ferror(file)) {
-		TPRINTF("errno = %d\n", errno);
+		TPRINTF("errno = %s\n", str_error_name(errno));
 		fclose(file);
 		return "Failed reading file";
@@ -65,5 +66,5 @@
 	TPRINTF("Seek to beginning...");
 	if (fseek(file, 0, SEEK_SET) != 0) {
-		TPRINTF("errno = %d\n", errno);
+		TPRINTF("errno = %s\n", str_error_name(errno));
 		fclose(file);
 		return "Failed seeking in file";
@@ -83,5 +84,5 @@
 	TPRINTF("Close...");
 	if (fclose(file) != 0) {
-		TPRINTF("errno = %d\n", errno);
+		TPRINTF("errno = %s\n", str_error_name(errno));
 		return "Failed closing file";
 	} else
Index: uspace/app/tester/stdio/stdio2.c
===================================================================
--- uspace/app/tester/stdio/stdio2.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/stdio/stdio2.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,4 +30,5 @@
 #include <stdlib.h>
 #include <stddef.h>
+#include <str_error.h>
 #include <errno.h>
 #include "../tester.h"
@@ -42,5 +43,5 @@
 	file = fopen(file_name, "wt");
 	if (file == NULL) {
-		TPRINTF("errno = %d\n", errno);
+		TPRINTF("errno = %s\n", str_error_name(errno));
 		return "Failed opening file";
 	} else
@@ -53,5 +54,5 @@
 	TPRINTF("Close...");
 	if (fclose(file) != 0) {
-		TPRINTF("errno = %d\n", errno);
+		TPRINTF("errno = %s\n", str_error_name(errno));
 		return "Failed closing file";
 	} else
@@ -61,5 +62,5 @@
 	file = fopen(file_name, "rt");
 	if (file == NULL) {
-		TPRINTF("errno = %d\n", errno);
+		TPRINTF("errno = %s\n", str_error_name(errno));
 		return "Failed opening file";
 	} else
@@ -76,5 +77,5 @@
 	TPRINTF("\nClose...");
 	if (fclose(file) != 0) {
-		TPRINTF("errno = %d\n", errno);
+		TPRINTF("errno = %s\n", str_error_name(errno));
 		return "Failed closing file";
 	} else
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/tester.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -76,5 +76,5 @@
 #include "mm/pager1.def"
 #include "hw/serial/serial1.def"
-#include "hw/misc/virtchar1.def"
+#include "chardev/chardev1.def"
 	{NULL, NULL, NULL, false}
 };
Index: uspace/app/tester/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/tester.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -108,7 +108,7 @@
 extern const char *test_pager1(void);
 extern const char *test_serial1(void);
-extern const char *test_virtchar1(void);
 extern const char *test_devman1(void);
 extern const char *test_devman2(void);
+extern const char *test_chardev1(void);
 
 extern test_t tests[];
Index: uspace/app/tester/vfs/vfs1.c
===================================================================
--- uspace/app/tester/vfs/vfs1.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/tester/vfs/vfs1.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -31,4 +31,5 @@
 #include <stdlib.h>
 #include <stddef.h>
+#include <str_error.h>
 #include <str.h>
 #include <vfs/vfs.h>
@@ -72,18 +73,20 @@
 	rc = vfs_link_path(TEST_DIRECTORY, KIND_DIRECTORY, NULL);
 	if (rc != EOK) {
-		TPRINTF("rc=%d\n", rc);
+		TPRINTF("rc=%s\n", str_error_name(rc));
 		return "vfs_link_path() failed";
 	}
 	TPRINTF("Created directory %s\n", TEST_DIRECTORY);
 	
-	int fd0 = vfs_lookup_open(TEST_FILE, WALK_REGULAR | WALK_MAY_CREATE,
-	    MODE_READ | MODE_WRITE);
-	if (fd0 < 0)
+	int fd0;
+	rc = vfs_lookup_open(TEST_FILE, WALK_REGULAR | WALK_MAY_CREATE,
+	    MODE_READ | MODE_WRITE, &fd0);
+	if (rc != EOK)
 		return "vfs_lookup_open() failed";
 	TPRINTF("Created file %s (fd=%d)\n", TEST_FILE, fd0);
 	
 	size_t size = sizeof(text);
-	ssize_t cnt = vfs_write(fd0, &pos, text, size);
-	if (cnt < 0)
+	size_t cnt;
+	rc  = vfs_write(fd0, &pos, text, size, &cnt);
+	if (rc != EOK)
 		return "write() failed";
 	TPRINTF("Written %zd bytes\n", cnt);
@@ -93,15 +96,15 @@
 	char buf[BUF_SIZE];
 	TPRINTF("read..\n");
-	while ((cnt = vfs_read(fd0, &pos, buf, BUF_SIZE))) {
-		TPRINTF("read returns %zd\n", cnt);
-		if (cnt < 0)
+	while ((rc = vfs_read(fd0, &pos, buf, BUF_SIZE, &cnt))) {
+		TPRINTF("read returns rc = %s, cnt = %zu\n", str_error_name(rc), cnt);
+		if (rc != EOK)
 			return "read() failed";
 		
-		int _cnt = (int) cnt;
-		if (_cnt != cnt) {
+		int icnt = (int) cnt;
+		if ((size_t) icnt != cnt) {
 			/* Count overflow, just to be sure. */
 			TPRINTF("Read %zd bytes\n", cnt);
 		} else {
-			TPRINTF("Read %zd bytes: \"%.*s\"\n", cnt, _cnt, buf);
+			TPRINTF("Read %zd bytes: \"%.*s\"\n", cnt, icnt, buf);
 		}
 	}
Index: uspace/app/trace/Makefile
===================================================================
--- uspace/app/trace/Makefile	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/trace/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,6 +36,5 @@
 	ipcp.c \
 	ipc_desc.c \
-	proto.c \
-	errors.c
+	proto.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/trace/errors.c
===================================================================
--- uspace/app/trace/errors.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*
- * Copyright (c) 2008 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 trace
- * @{
- */
-/** @file
- */
-
-#include <errno.h>
-#include "errors.h"
-
-const err_desc_t err_desc[] = {
-	[-EOK]		= { "EOK",		"No error" },
-	[-ENOENT]	= { "ENOENT",		"No such entry" },
-	[-ENOMEM]	= { "ENOMEM",		"Not enough memory" },
-	[-ELIMIT]	= { "ELIMIT",		"Limit exceeded" },
-	[-EREFUSED]	= { "EREFUSED",		"Connection refused" },
-
-	[-EFORWARD]	= { "EFORWARD",		"Forward error" },
-	[-EPERM]	= { "EPERM",		"Permission denied" },
-	[-EHANGUP]	= { "EHANGUP",		"Answerbox closed connection" },
-	[-EEXIST]	= { "EEXIST",		"Entry already exists" },
-	[-EBADMEM]	= { "EBADMEM",		"Bad memory pointer" },
-
-	[-ENOTSUP]	= { "ENOTSUP",		"Not supported" },
-	[-EADDRNOTAVAIL] = { "EADDRNOTAVAIL", 	"Address not available." },
-	[-ETIMEOUT]	= { "ETIMEOUT",		"Timeout expired" },
-	[-EINVAL]	= { "EINVAL",		"Invalid value" },
-	[-EBUSY]	= { "EBUSY",		"Resource is busy" },
-
-	[-EOVERFLOW]	= { "EOVERFLOW",	"The result does not fit its size." }
-};
-
-/** @}
- */
Index: pace/app/trace/errors.h
===================================================================
--- uspace/app/trace/errors.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * Copyright (c) 2008 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 trace
- * @{
- */
-/** @file
- */
-
-#ifndef ERRORS_H_
-#define ERRORS_H_
-
-typedef struct {
-	const char *name;  /**< Error value name (Exx) */
-	const char *desc;  /**< Error description */
-} err_desc_t;
-
-extern const err_desc_t err_desc[];
-
-#endif
-
-/** @}
- */
Index: uspace/app/trace/ipcp.c
===================================================================
--- uspace/app/trace/ipcp.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/trace/ipcp.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,4 +35,5 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <str_error.h>
 #include <inttypes.h>
 #include <adt/hash_table.h>
@@ -44,6 +45,4 @@
 #include "ipcp.h"
 
-#define IPCP_CALLID_SYNC 0
-
 typedef struct {
 	sysarg_t phone_hash;
@@ -145,5 +144,5 @@
 		V_INTEGER,
 		V_INTEGER,
-		V_INTEGER		
+		V_INTEGER
 	};
 
@@ -189,6 +188,6 @@
 
 	if ((display_mask & DM_IPC) != 0) {
-		printf("Call ID: %p, phone: %d, proto: %s, method: ",
-		    (void *) hash, phone,
+		printf("Call ID: %d, phone: %d, proto: %s, method: ",
+		    hash, phone,
 		    (proto ? proto->name : "n/a"));
 		ipc_m_print(proto, IPC_GET_IMETHOD(*call));
@@ -266,7 +265,7 @@
 	
 	if ((display_mask & DM_IPC) != 0) {
-		printf("Response to %p: retval=%" PRIdn ", args = (%" PRIun ", "
+		printf("Response to %d: retval=%" PRIdn ", args = (%" PRIun ", "
 		    "%" PRIun ", %" PRIun ", %" PRIun ", %" PRIun ")\n",
-		    (void *) hash, retval, IPC_GET_ARG1(*answer),
+		    hash, retval, IPC_GET_ARG1(*answer),
 		    IPC_GET_ARG2(*answer), IPC_GET_ARG3(*answer),
 		    IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer));
@@ -323,13 +322,11 @@
 	pending_call_t *pcall;
 	
-	if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
+	if ((call->flags & IPC_CALL_ANSWERED) == 0) {
 		/* Not a response */
 		if ((display_mask & DM_IPC) != 0) {
-			printf("Not a response (hash %p)\n", (void *) hash);
+			printf("Not a response (hash %d)\n", hash);
 		}
 		return;
 	}
-	
-	hash = hash & ~IPC_CALLID_ANSWERED;
 	
 	item = hash_table_find(&pending_calls, &hash);
@@ -348,14 +345,8 @@
 }
 
-void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
-{
-	ipcp_call_out(phone, call, IPCP_CALLID_SYNC);
-	ipcp_call_in(answer, IPCP_CALLID_SYNC);
-}
-
 void ipcp_hangup(int phone, int rc)
 {
 	if ((display_mask & DM_SYSTEM) != 0) {
-		printf("Hang phone %d up -> %d\n", phone, rc);
+		printf("Hang phone %d up -> %s\n", phone, str_error_name(rc));
 		ipcp_connection_clear(phone);
 	}
Index: uspace/app/trace/syscalls.c
===================================================================
--- uspace/app/trace/syscalls.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/trace/syscalls.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -54,5 +54,5 @@
 
     [SYS_IPC_CALL_ASYNC_FAST] = { "ipc_call_async_fast", 6,	V_HASH },
-    [SYS_IPC_CALL_ASYNC_SLOW] = { "ipc_call_async_slow", 2,	V_HASH },
+    [SYS_IPC_CALL_ASYNC_SLOW] = { "ipc_call_async_slow", 3,	V_HASH },
 
     [SYS_IPC_ANSWER_FAST] = { "ipc_answer_fast",	6,	V_ERRNO },
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/trace/trace.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,4 +38,5 @@
 #include <stdint.h>
 #include <stddef.h>
+#include <str_error.h>
 #include <inttypes.h>
 #include <fibril.h>
@@ -62,5 +63,4 @@
 #include "syscalls.h"
 #include "ipcp.h"
-#include "errors.h"
 #include "trace.h"
 
@@ -157,5 +157,5 @@
 		
 		printf("Error connecting\n");
-		printf("ipc_connect_task(%" PRIu64 ") -> %d ", task_id, errno);
+		printf("ipc_connect_task(%" PRIu64 ") -> %s ", task_id, str_error_name(errno));
 		return errno;
 	}
@@ -163,5 +163,5 @@
 	int rc = udebug_begin(ksess);
 	if (rc < 0) {
-		printf("udebug_begin() -> %d\n", rc);
+		printf("udebug_begin() -> %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -169,5 +169,5 @@
 	rc = udebug_set_evmask(ksess, UDEBUG_EM_ALL);
 	if (rc < 0) {
-		printf("udebug_set_evmask(0x%x) -> %d\n ", UDEBUG_EM_ALL, rc);
+		printf("udebug_set_evmask(0x%x) -> %s\n ", UDEBUG_EM_ALL, str_error_name(rc));
 		return rc;
 	}
@@ -187,5 +187,5 @@
 		THBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed);
 	if (rc < 0) {
-		printf("udebug_thread_read() -> %d\n", rc);
+		printf("udebug_thread_read() -> %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -225,6 +225,6 @@
 		if (sval >= -15 && sval <= 0) {
 			printf("%ld %s (%s)", sval,
-			    err_desc[-sval].name,
-			    err_desc[-sval].desc);
+			    str_error_name((int) sval),
+			    str_error((int) sval));
 		} else {
 			printf("%ld", sval);
@@ -234,6 +234,6 @@
 		if (sval >= -15 && sval < 0) {
 			printf("%ld %s (%s)", sval,
-			    err_desc[-sval].name,
-			    err_desc[-sval].desc);
+			    str_error_name((int) sval),
+			    str_error((int) sval));
 		} else {
 			printf("%ld", sval);
@@ -284,5 +284,5 @@
 	sysarg_t phoneid;
 	
-	if (sc_rc == (sysarg_t) IPC_CALLRET_FATAL)
+	if (sc_rc != (sysarg_t) EOK)
 		return;
 
@@ -304,5 +304,5 @@
 	int rc;
 
-	if (sc_rc == (sysarg_t) IPC_CALLRET_FATAL)
+	if (sc_rc != (sysarg_t) EOK)
 		return;
 
@@ -604,5 +604,5 @@
 	rc = get_thread_list();
 	if (rc < 0) {
-		printf("Failed to get thread list (error %d)\n", rc);
+		printf("Failed to get thread list (%s)\n", str_error(rc));
 		return;
 	}
@@ -643,5 +643,5 @@
 			rc = udebug_stop(sess, thash);
 			if (rc != EOK)
-				printf("Error: stop -> %d\n", rc);
+				printf("Error: stop -> %s\n", str_error_name(rc));
 			break;
 		case KC_R:
Index: uspace/app/vcalc/vcalc.c
===================================================================
--- uspace/app/vcalc/vcalc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/vcalc/vcalc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,5 +38,5 @@
 #include <stdbool.h>
 #include <stdio.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <io/pixel.h>
 #include <task.h>
Index: uspace/app/vdemo/vdemo.c
===================================================================
--- uspace/app/vdemo/vdemo.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/vdemo/vdemo.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,5 +35,5 @@
 #include <stdbool.h>
 #include <stdio.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <io/pixel.h>
 #include <task.h>
Index: uspace/app/viewer/viewer.c
===================================================================
--- uspace/app/viewer/viewer.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/viewer/viewer.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,5 +37,5 @@
 #include <vfs/vfs.h>
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <stdbool.h>
 #include <window.h>
@@ -109,10 +109,11 @@
 static bool img_load(const char *fname, surface_t **p_local_surface)
 {
-	int fd = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ);
-	if (fd < 0)
+	int fd;
+	int rc = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ, &fd);
+	if (rc != EOK)
 		return false;
 	
 	struct stat stat;
-	int rc = vfs_stat(fd, &stat);
+	rc = vfs_stat(fd, &stat);
 	if (rc != EOK) {
 		vfs_put(fd);
@@ -126,6 +127,7 @@
 	}
 
-	ssize_t rd = vfs_read(fd, (aoff64_t []) {0}, tga, stat.size);
-	if ((rd < 0) || (rd != (ssize_t) stat.size)) {
+	size_t nread;
+	rc = vfs_read(fd, (aoff64_t []) {0}, tga, stat.size, &nread);
+	if (rc != EOK || nread != stat.size) {
 		free(tga);
 		vfs_put(fd);
Index: uspace/app/vlaunch/vlaunch.c
===================================================================
--- uspace/app/vlaunch/vlaunch.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/vlaunch/vlaunch.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,5 @@
 #include <errno.h>
 #include <stdio.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <task.h>
 #include <str_error.h>
Index: uspace/app/wavplay/dplay.c
===================================================================
--- uspace/app/wavplay/dplay.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/wavplay/dplay.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -345,5 +345,7 @@
 	}
 	printf("Playing on device: %s.\n", device);
-	if (audio_pcm_query_cap(session, AUDIO_CAP_PLAYBACK) <= 0) {
+	sysarg_t val;
+	ret = audio_pcm_query_cap(session, AUDIO_CAP_PLAYBACK, &val);
+	if (ret != EOK || !val) {
 		printf("Device %s does not support playback\n", device);
 		ret = ENOTSUP;
@@ -386,8 +388,10 @@
 		goto cleanup;
 	}
-	if (audio_pcm_query_cap(pb.device, AUDIO_CAP_BUFFER_POS) > 0) {
+	ret = audio_pcm_query_cap(pb.device, AUDIO_CAP_BUFFER_POS, &val);
+	if (ret == EOK && val) {
 		play(&pb);
 	} else {
-		if (audio_pcm_query_cap(pb.device, AUDIO_CAP_INTERRUPT) > 0)
+		ret = audio_pcm_query_cap(pb.device, AUDIO_CAP_INTERRUPT, &val);
+		if (ret == EOK && val)
 			play_fragment(&pb);
 		else
Index: uspace/app/wavplay/drec.c
===================================================================
--- uspace/app/wavplay/drec.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/wavplay/drec.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -176,4 +176,5 @@
 	int ret = EOK;
 	audio_pcm_sess_t *session = NULL;
+	sysarg_t val;
 	if (str_cmp(device, "default") == 0) {
 		session = audio_pcm_open_default();
@@ -186,5 +187,6 @@
 	}
 	printf("Recording on device: %s.\n", device);
-	if (audio_pcm_query_cap(session, AUDIO_CAP_CAPTURE) <= 0) {
+	ret = audio_pcm_query_cap(session, AUDIO_CAP_CAPTURE, &val);
+	if (ret != EOK || !val) {
 		printf("Device %s does not support recording\n", device);
 		ret = ENOTSUP;
@@ -225,5 +227,6 @@
 		goto cleanup;
 	}
-	if (audio_pcm_query_cap(rec.device, AUDIO_CAP_INTERRUPT) > 0)
+	ret = audio_pcm_query_cap(rec.device, AUDIO_CAP_INTERRUPT, &val);
+	if (ret == EOK && val)
 		record_fragment(&rec, format);
 	else
Index: uspace/app/wavplay/main.c
===================================================================
--- uspace/app/wavplay/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/wavplay/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,5 +37,5 @@
 #include <errno.h>
 #include <fibril_synch.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <str_error.h>
 #include <stdio.h>
Index: uspace/app/websrv/websrv.c
===================================================================
--- uspace/app/websrv/websrv.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/websrv/websrv.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -168,5 +168,5 @@
 		rc = tcp_conn_recv_wait(recv->conn, recv->rbuf, BUFFER_SIZE, &nrecv);
 		if (rc != EOK) {
-			fprintf(stderr, "tcp_conn_recv() failed (%d)\n", rc);
+			fprintf(stderr, "tcp_conn_recv() failed: %s\n", str_error(rc));
 			return rc;
 		}
@@ -247,4 +247,5 @@
 	char *fname = NULL;
 	int rc;
+	size_t nr;
 	int fd = -1;
 	
@@ -264,6 +265,6 @@
 	}
 	
-	fd = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ);
-	if (fd < 0) {
+	rc = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ, &fd);
+	if (rc != EOK) {
 		rc = send_response(conn, msg_not_found);
 		goto out;
@@ -279,12 +280,10 @@
 	aoff64_t pos = 0;
 	while (true) {
-		ssize_t nr = vfs_read(fd, &pos, fbuf, BUFFER_SIZE);
+		rc = vfs_read(fd, &pos, fbuf, BUFFER_SIZE, &nr);
+		if (rc != EOK)
+			goto out;
+		
 		if (nr == 0)
 			break;
-		
-		if (nr < 0) {
-			rc = EIO;
-			goto out;
-		}
 		
 		rc = tcp_conn_send(conn, fbuf, nr);
Index: uspace/app/wifi_supplicant/wifi_supplicant.c
===================================================================
--- uspace/app/wifi_supplicant/wifi_supplicant.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/app/wifi_supplicant/wifi_supplicant.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,4 +40,6 @@
 #include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <str_error.h>
 #include <loc.h>
 
@@ -138,5 +140,5 @@
 	int rc = get_wifi_list(&wifis, &count);
 	if (rc != EOK) {
-		printf("Error fetching wifi list.\n");
+		printf("Error fetching wifi list: %s\n", str_error(rc));
 		return EINVAL;
 	}
@@ -147,5 +149,5 @@
 		rc = loc_service_get_name(wifis[i], &svc_name);
 		if (rc != EOK) {
-			printf("Error getting service name.\n");
+			printf("Error getting service name: %s\n", str_error(rc));
 			free(wifis);
 			return rc;
@@ -176,6 +178,6 @@
 			printf("Device is not ready yet.\n");
 		else
-			printf("Error when disconnecting device. "
-			    "Error: %d\n", rc);
+			printf("Error when disconnecting device: %s\n",
+			    str_error(rc));
 		
 		return rc;
@@ -191,6 +193,6 @@
 			printf("Given SSID not in scan results.\n");
 		else
-			printf("Error when connecting to network. "
-			    "Error: %d\n", rc);
+			printf("Error when connecting to network: %s\n",
+			    str_error(rc));
 		
 		return rc;
@@ -220,6 +222,6 @@
 			printf("Not connected to any WiFi network.\n");
 		else
-			printf("Error when disconnecting from network. "
-			    "Error: %d\n", rc);
+			printf("Error when disconnecting from network: %s\n",
+			    str_error(rc));
 		
 		return rc;
@@ -246,5 +248,6 @@
 			printf("Device is not ready yet.\n");
 		else
-			printf("Failed to fetch scan results. Error: %d\n", rc);
+			printf("Failed to fetch scan results: %s\n",
+			    str_error(rc));
 		
 		return rc;
@@ -276,6 +279,6 @@
 	int rc = inetcfg_init();
 	if (rc != EOK) {
-		printf("%s: Failed connecting to inetcfg service (%d).\n",
-		    NAME, rc);
+		printf("%s: Failed connecting to inetcfg service: %s.\n",
+		    NAME, str_error(rc));
 		return 1;
 	}
@@ -283,6 +286,6 @@
 	rc = dhcp_init();
 	if (rc != EOK) {
-		printf("%s: Failed connecting to dhcp service (%d).\n",
-		    NAME, rc);
+		printf("%s: Failed connecting to dhcp service: %s.\n",
+		    NAME, str_error(rc));
 		return 1;
 	}
Index: uspace/doc/main_page.h
===================================================================
--- uspace/doc/main_page.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/doc/main_page.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,12 @@
+/**
+ @mainpage HelenOS Operating System Source Code Reference
+
+HelenOS is a portable microkernel-based multiserver operating system designed and implemented from scratch. It decomposes key operating system functionality such as file systems, networking, device drivers and graphical user interface into a collection of fine-grained user space components that interact with each other via message passing. A failure or crash of one component does not directly harm others. HelenOS is therefore flexible, modular, extensible, fault tolerant and easy to understand.
+
+HelenOS does not aim to be a clone of any existing operating system and trades compatibility with legacy APIs for cleaner design. Most of HelenOS components have been made to order specifically for HelenOS so that its essential parts can stay free of adaptation layers, glue code, franken-components and the maintenance burden incurred by them.
+
+HelenOS runs on seven different processor architectures and machines ranging from embedded ARM devices and single-board computers through multicore 32-bit and 64-bit desktop PCs to 64-bit Itanium and SPARC rack-mount servers.
+
+HelenOS is open source, free software. Its source code is available under the BSD license. Some third-party components are licensed under GPL. 
+
+*/
Index: pace/doc/main_usb.h
===================================================================
--- uspace/doc/main_usb.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,26 +1,0 @@
-/**
- @mainpage USB support for HelenOS
-
-This is reference manual for USB subsystem for HelenOS.
-
-HelenOS is a microkernel operating system where most of the functionality
-is provided by userspace tasks rather than system calls.
-This includes file system service, networking and also device drivers.
-
-USB is a standard for communication between host computers and computer
-peripherals.
-The advantage of USB over other kinds of connection between a computer
-and a peripheral is its flexibility.
-USB supports plugging and unplugging of devices without need to turn
-off any of the components.
-The data flow model is designed to accommodate together peripherals
-with different transfer characteristics.
-
-Adding support for USB devices to HelenOS shall improve the usability
-of the system in general even if the support concerns only USB 1.1 and
-the only peripheral drivers are for keyboards and mice.
-
-This reference documentation can be found also on-line at homepage
-of HelenOS USB project at http://helenos-usb.sourceforge.net/
-
-*/
Index: uspace/drv/audio/hdaudio/codec.c
===================================================================
--- uspace/drv/audio/hdaudio/codec.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/audio/hdaudio/codec.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,4 +37,5 @@
 #include <ddf/log.h>
 #include <errno.h>
+#include <str_error.h>
 #include <stdlib.h>
 
@@ -514,5 +515,5 @@
 		goto error;
 
-	ddf_msg(LVL_NOTE, "hda_get_subnc -> %d", rc);
+	ddf_msg(LVL_NOTE, "hda_get_subnc -> %s", str_error_name(rc));
 	ddf_msg(LVL_NOTE, "sfg=%d nfg=%d", sfg, nfg);
 
@@ -524,5 +525,5 @@
 			goto error;
 
-		ddf_msg(LVL_NOTE, "hda_get_fgrp_type -> %d", rc);
+		ddf_msg(LVL_NOTE, "hda_get_fgrp_type -> %s", str_error_name(rc));
 		ddf_msg(LVL_NOTE, "unsol: %d, grptype: %d", unsol, grptype);
 
@@ -546,5 +547,5 @@
 			goto error;
 
-		ddf_msg(LVL_NOTE, "hda_get_subnc -> %d", rc);
+		ddf_msg(LVL_NOTE, "hda_get_subnc -> %s", str_error_name(rc));
 		ddf_msg(LVL_NOTE, "saw=%d baw=%d", saw, naw);
 
Index: uspace/drv/audio/hdaudio/hdaudio.c
===================================================================
--- uspace/drv/audio/hdaudio/hdaudio.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/audio/hdaudio/hdaudio.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -58,5 +58,5 @@
 static int hda_fun_offline(ddf_fun_t *fun);
 
-static void hdaudio_interrupt(ipc_callid_t, ipc_call_t *, ddf_dev_t *);
+static void hdaudio_interrupt(ipc_call_t *, ddf_dev_t *);
 
 static driver_ops_t driver_ops = {
@@ -259,14 +259,14 @@
 	rc = hw_res_enable_interrupt(hda->parent_sess, res.irqs.irqs[0]);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed enabling interrupt. (%d)", rc);
-		goto error;
-	}
-
-	int irq_cap = register_interrupt_handler(dev, res.irqs.irqs[0],
-	    hdaudio_interrupt, &irq_code);
-	if (irq_cap < 0) {
-		rc = irq_cap;
-		ddf_msg(LVL_ERROR, "Failed registering interrupt handler. (%d)",
-		    rc);
+		ddf_msg(LVL_ERROR, "Failed enabling interrupt.: %s", str_error(rc));
+		goto error;
+	}
+
+	int irq_cap;
+	rc = register_interrupt_handler(dev, res.irqs.irqs[0],
+	    hdaudio_interrupt, &irq_code, &irq_cap);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed registering interrupt handler: %s",
+		    str_error_name(rc));
 		goto error;
 	}
@@ -314,5 +314,5 @@
 	hw_res_list_parsed_clean(&res);
 
-	ddf_msg(LVL_NOTE, "Failing hda_dev_add() -> %d", rc);
+	ddf_msg(LVL_NOTE, "Failing hda_dev_add() -> %s", str_error_name(rc));
 	return rc;
 }
@@ -368,6 +368,5 @@
 }
 
-static void hdaudio_interrupt(ipc_callid_t iid, ipc_call_t *icall,
-    ddf_dev_t *dev)
+static void hdaudio_interrupt(ipc_call_t *icall, ddf_dev_t *dev)
 {
 	hda_t *hda = (hda_t *)ddf_dev_data_get(dev);
Index: uspace/drv/audio/hdaudio/stream.c
===================================================================
--- uspace/drv/audio/hdaudio/stream.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/audio/hdaudio/stream.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,4 +39,5 @@
 #include <ddi.h>
 #include <errno.h>
+#include <str_error.h>
 #include <macros.h>
 #include <stdlib.h>
@@ -122,5 +123,5 @@
 	    0, &buffer_phys, &buffer);
 	if (rc != EOK) {
-		ddf_msg(LVL_NOTE, "dmamem_map_anon -> %d", rc);
+		ddf_msg(LVL_NOTE, "dmamem_map_anon -> %s", str_error_name(rc));
 		goto error;
 	}
Index: uspace/drv/audio/sb16/dsp.c
===================================================================
--- uspace/drv/audio/sb16/dsp.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/audio/sb16/dsp.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -303,10 +303,10 @@
 
 	// TODO: Assumes DMA 16
-	const int remain = hw_res_dma_channel_remain(sess, dsp->dma16_channel);
-	if (remain >= 0) {
+	size_t remain;
+	int rc = hw_res_dma_channel_remain(sess, dsp->dma16_channel, &remain);
+	if (rc == EOK) {
 		*pos = dsp->buffer.size - remain;
-		return EOK;
-	}
-	return remain;
+	}
+	return rc;
 }
 
Index: uspace/drv/audio/sb16/main.c
===================================================================
--- uspace/drv/audio/sb16/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/audio/sb16/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -76,5 +76,5 @@
 }
 
-static void irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev)
+static void irq_handler(ipc_call_t *call, ddf_dev_t *dev)
 {
 	sb16_t *sb16_dev = ddf_dev_data_get(dev);
@@ -123,8 +123,7 @@
 	};
 
-	irq_cap = register_interrupt_handler(device, irq, irq_handler,
-	    &irq_code);
-	if (irq_cap < 0) {
-		rc = irq_cap;
+	rc = register_interrupt_handler(device, irq, irq_handler,
+	    &irq_code, &irq_cap);
+	if (rc != EOK) {
 		ddf_log_error("Failed to register irq handler: %s.",
 		    str_error(rc));
Index: uspace/drv/block/ahci/ahci.c
===================================================================
--- uspace/drv/block/ahci/ahci.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/block/ahci/ahci.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -890,10 +890,9 @@
 /** AHCI interrupt handler.
  *
- * @param iid   The IPC call id.
  * @param icall The IPC call structure.
  * @param dev   DDF device structure.
  *
  */
-static void ahci_interrupt(ipc_callid_t iid, ipc_call_t *icall, ddf_dev_t *dev)
+static void ahci_interrupt(ipc_call_t *icall, ddf_dev_t *dev)
 {
 	ahci_dev_t *ahci = dev_ahci_dev(dev);
@@ -1185,12 +1184,13 @@
 	ct.ranges = ahci_ranges;
 	
-	int irq_cap = register_interrupt_handler(dev,
-	    hw_res_parsed.irqs.irqs[0], ahci_interrupt, &ct);
-	if (irq_cap < 0) {
+	int irq_cap;
+	int rc = register_interrupt_handler(dev,
+	    hw_res_parsed.irqs.irqs[0], ahci_interrupt, &ct, &irq_cap);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed registering interrupt handler.");
 		goto error_register_interrupt_handler;
 	}
 	
-	int rc = hw_res_enable_interrupt(ahci->parent_sess,
+	rc = hw_res_enable_interrupt(ahci->parent_sess,
 	    hw_res_parsed.irqs.irqs[0]);
 	if (rc != EOK) {
Index: uspace/drv/block/ddisk/ddisk.c
===================================================================
--- uspace/drv/block/ddisk/ddisk.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/block/ddisk/ddisk.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -64,5 +64,5 @@
 static void ddisk_bd_connection(ipc_callid_t, ipc_call_t *, void *);
 
-static void ddisk_irq_handler(ipc_callid_t, ipc_call_t *, ddf_dev_t *);
+static void ddisk_irq_handler(ipc_call_t *, ddf_dev_t *);
 
 static driver_ops_t driver_ops = {
@@ -176,5 +176,5 @@
 };
 
-void ddisk_irq_handler(ipc_callid_t iid, ipc_call_t *icall, ddf_dev_t *dev)
+void ddisk_irq_handler(ipc_call_t *icall, ddf_dev_t *dev)
 {
 	ddf_msg(LVL_DEBUG, "ddisk_irq_handler(), status=%" PRIx32,
@@ -503,8 +503,7 @@
 	ddisk_irq_commands[0].addr = (void *) &res_phys->status;
 	ddisk_irq_commands[3].addr = (void *) &res_phys->command;
-	ddisk->irq_cap = register_interrupt_handler(dev, ddisk->ddisk_res.irq,
-	    ddisk_irq_handler, &ddisk_irq_code);
-	if (ddisk->irq_cap < 0) {
-		rc = ddisk->irq_cap;
+	rc = register_interrupt_handler(dev, ddisk->ddisk_res.irq,
+	    ddisk_irq_handler, &ddisk_irq_code, &ddisk->irq_cap);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to register interrupt handler.");
 		goto error;
Index: uspace/drv/bus/adb/cuda_adb/cuda_adb.c
===================================================================
--- uspace/drv/bus/adb/cuda_adb/cuda_adb.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/adb/cuda_adb/cuda_adb.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -57,5 +57,5 @@
 static void cuda_dev_connection(ipc_callid_t, ipc_call_t *, void *);
 static int cuda_init(cuda_t *);
-static void cuda_irq_handler(ipc_callid_t, ipc_call_t *, void *);
+static void cuda_irq_handler(ipc_call_t *, void *);
 
 static void cuda_irq_listen(cuda_t *);
@@ -252,5 +252,5 @@
 	cuda_irq_code.cmds[0].addr = (void *) &((cuda_regs_t *)
 	    cuda->phys_base)->ifr;
-	async_irq_subscribe(10, cuda_irq_handler, cuda, &cuda_irq_code);
+	async_irq_subscribe(10, cuda_irq_handler, cuda, &cuda_irq_code, NULL);
 
 	/* Enable SR interrupt. */
@@ -264,5 +264,5 @@
 }
 
-static void cuda_irq_handler(ipc_callid_t iid, ipc_call_t *call, void *arg)
+static void cuda_irq_handler(ipc_call_t *call, void *arg)
 {
 	uint8_t rbuf[CUDA_RCV_BUF_SIZE];
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/isa/isa.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -49,5 +49,5 @@
 #include <ctype.h>
 #include <macros.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <dirent.h>
 #include <ipc/irc.h>
@@ -277,9 +277,10 @@
 	int fd;
 	size_t len;
-	ssize_t r;
+	int rc;
+	size_t nread;
 	struct stat st;
 
-	fd = vfs_lookup_open(conf_path, WALK_REGULAR, MODE_READ);
-	if (fd < 0) {
+	rc = vfs_lookup_open(conf_path, WALK_REGULAR, MODE_READ, &fd);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Unable to open %s", conf_path);
 		goto cleanup;
@@ -306,11 +307,11 @@
 	}
 
-	r = vfs_read(fd, (aoff64_t []) {0}, buf, len);
-	if (r < 0) {
+	rc = vfs_read(fd, (aoff64_t []) {0}, buf, len, &nread);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
 		goto cleanup;
 	}
 
-	buf[len] = 0;
+	buf[nread] = 0;
 
 	suc = true;
Index: uspace/drv/bus/isa/isa.dev
===================================================================
--- uspace/drv/bus/isa/isa.dev	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/isa/isa.dev	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -7,4 +7,5 @@
 	match 100 isa/apic
 	mem_range 0xfec00000 0x14
+
 com1:
 	match 100 isa/ns8250
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -514,5 +514,5 @@
 #define MEM_MASK (~0xf)
 	
-	io = (bool) (val & 1);
+	io = (val & 1) != 0;
 	if (io) {
 		addrw64 = false;
Index: uspace/drv/bus/usb/ehci/ehci_batch.c
===================================================================
--- uspace/drv/bus/usb/ehci/ehci_batch.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/usb/ehci/ehci_batch.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -234,8 +234,8 @@
 			    -= td_remain_size(ehci_batch->tds[i]);
 		} else {
-			usb_log_debug("Batch %p found error TD(%zu):%08x (%d).",
+			usb_log_debug("Batch %p found error TD(%zu):%08x: %s.",
 			    ehci_batch->usb_batch, i,
 			    ehci_batch->tds[i]->status,
-			    ehci_batch->usb_batch->error);
+			    str_error_name(ehci_batch->usb_batch->error));
 			/* Clear possible ED HALT */
 			qh_clear_halt(ehci_batch->qh);
Index: uspace/drv/bus/usb/ehci/hc.c
===================================================================
--- uspace/drv/bus/usb/ehci/hc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/usb/ehci/hc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -96,7 +96,9 @@
  * @param[in] hw_res Device's resources.
  *
+ * @param[out] irq
+ *
  * @return Error code.
  */
-int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
+int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq)
 {
 	assert(code);
@@ -146,5 +148,6 @@
 	    RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
 
-	return hw_res->irqs.irqs[0];
+	*irq = hw_res->irqs.irqs[0];
+	return EOK;
 }
 
Index: uspace/drv/bus/usb/ehci/hc.h
===================================================================
--- uspace/drv/bus/usb/ehci/hc.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/usb/ehci/hc.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -88,5 +88,5 @@
 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep);
 
-int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);
+int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq);
 
 void ehci_hc_interrupt(hcd_t *hcd, uint32_t status);
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -103,5 +103,5 @@
  * @return Error code.
  */
-int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
+int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq)
 {
 	assert(code);
@@ -141,5 +141,6 @@
 	    RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
 
-	return hw_res->irqs.irqs[0];
+	*irq = hw_res->irqs.irqs[0];
+	return EOK;
 }
 
Index: uspace/drv/bus/usb/ohci/hc.h
===================================================================
--- uspace/drv/bus/usb/ohci/hc.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/usb/ohci/hc.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -86,5 +86,5 @@
 extern void hc_dequeue_endpoint(hc_t *, const endpoint_t *);
 
-int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);
+int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq);
 
 extern void ohci_hc_interrupt(hcd_t *, uint32_t);
Index: uspace/drv/bus/usb/ohci/hw_struct/hcca.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/hcca.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/usb/ohci/hw_struct/hcca.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,5 +37,5 @@
 #define DRV_OHCI_HW_STRUCT_HCCA_H
 
-#include <malloc.h>
+#include <stdlib.h>
 #include <stdint.h>
 #include <macros.h>
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -103,8 +103,9 @@
  * @param[out] code IRQ code structure.
  * @param[in] hw_res Device's resources.
+ * @param[out] irq
  *
  * @return Error code.
  */
-int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
+int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq)
 {
 	assert(code);
@@ -142,5 +143,6 @@
 	    RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
 
-	return hw_res->irqs.irqs[0];
+	*irq = hw_res->irqs.irqs[0];
+	return EOK;
 }
 
Index: uspace/drv/bus/usb/uhci/hc.h
===================================================================
--- uspace/drv/bus/usb/uhci/hc.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/bus/usb/uhci/hc.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -127,5 +127,5 @@
 extern void hc_fini(hc_t *);
 
-extern int uhci_hc_gen_irq_code(irq_code_t *, const hw_res_list_parsed_t *);
+extern int uhci_hc_gen_irq_code(irq_code_t *, const hw_res_list_parsed_t *, int *);
 
 extern void uhci_hc_interrupt(hcd_t *, uint32_t);
Index: pace/drv/char/i8042/buffer.h
===================================================================
--- uspace/drv/char/i8042/buffer.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,153 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @addtogroup kbd
- * @{
- */
-
-/** @file
- * @brief Cyclic buffer structure.
- */
-
-#ifndef BUFFER_H_
-#define BUFFER_H_
-
-#include <assert.h>
-#include <fibril_synch.h>
-
-/** Cyclic buffer that blocks on full/empty.
- *
- * read_head == write_head means that the buffer is empty.
- * write_head + 1 == read_head means that the buffer is full.
- * Attempt to insert byte into the full buffer will block until it can succeed.
- * Attempt to read from empty buffer will block until it can succeed.
- *
- */
-typedef struct {
-	uint8_t *buffer;          /**< Storage space. */
-	uint8_t *buffer_end;      /**< End of storage place. */
-	fibril_mutex_t guard;     /**< Protects buffer structures. */
-	fibril_condvar_t change;  /**< Indicates change (empty/full). */
-	uint8_t *read_head;       /**< Place of the next readable element. */
-	uint8_t *write_head;      /**< Pointer to the next writable place. */
-} buffer_t;
-
-/** Initialize cyclic buffer using provided memory space.
- *
- * @param buffer Cyclic buffer structure to initialize.
- * @param data   Memory space to use.
- * @param size   Size of the memory place.
- *
- */
-static inline void buffer_init(buffer_t *buffer, uint8_t *data, size_t size)
-{
-	assert(buffer);
-	
-	fibril_mutex_initialize(&buffer->guard);
-	fibril_condvar_initialize(&buffer->change);
-	buffer->buffer = data;
-	buffer->buffer_end = data + size;
-	buffer->read_head = buffer->buffer;
-	buffer->write_head = buffer->buffer;
-	memset(buffer->buffer, 0, size);
-}
-
-/** Write byte to cyclic buffer.
- *
- * @param buffer Cyclic buffer to write to.
- * @param data   Data to write.
- *
- */
-static inline void buffer_write(buffer_t *buffer, uint8_t data)
-{
-	fibril_mutex_lock(&buffer->guard);
-	
-	/* Next position. */
-	uint8_t *new_head = buffer->write_head + 1;
-	if (new_head == buffer->buffer_end)
-		new_head = buffer->buffer;
-	
-	/* Buffer full. */
-	while (new_head == buffer->read_head)
-		fibril_condvar_wait(&buffer->change, &buffer->guard);
-	
-	/* Write data. */
-	*buffer->write_head = data;
-	
-	/* Buffer was empty. */
-	if (buffer->write_head == buffer->read_head)
-		fibril_condvar_broadcast(&buffer->change);
-	
-	/* Move head */
-	buffer->write_head = new_head;
-	fibril_mutex_unlock(&buffer->guard);
-}
-
-/** Read byte from cyclic buffer.
- *
- * @param buffer Cyclic buffer to read from.
- *
- * @return Byte read.
- *
- */
-static inline uint8_t buffer_read(buffer_t *buffer)
-{
-	fibril_mutex_lock(&buffer->guard);
-	
-	/* Buffer is empty. */
-	while (buffer->write_head == buffer->read_head)
-		fibril_condvar_wait(&buffer->change, &buffer->guard);
-	
-	/* Next position. */
-	uint8_t *new_head = buffer->read_head + 1;
-	if (new_head == buffer->buffer_end)
-		new_head = buffer->buffer;
-	
-	/* Read data. */
-	const uint8_t data = *buffer->read_head;
-	
-	/* Buffer was full. */
-	uint8_t *new_write_head = buffer->write_head + 1;
-	if (new_write_head == buffer->buffer_end)
-		new_write_head = buffer->buffer;
-	if (new_write_head == buffer->read_head)
-		fibril_condvar_broadcast(&buffer->change);
-	
-	/* Move head */
-	buffer->read_head = new_head;
-	
-	fibril_mutex_unlock(&buffer->guard);
-	return data;
-}
-
-#endif
-
-/**
- * @}
- */
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/i8042/i8042.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -2,5 +2,5 @@
  * Copyright (c) 2001-2004 Jakub Jermar
  * Copyright (c) 2006 Josef Cejka
- * Copyright (c) 2014 Jiri Svoboda
+ * Copyright (c) 2017 Jiri Svoboda
  * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
@@ -39,4 +39,5 @@
  */
 
+#include <adt/circ_buf.h>
 #include <ddf/log.h>
 #include <ddf/interrupt.h>
@@ -67,6 +68,6 @@
 
 static void i8042_char_conn(ipc_callid_t, ipc_call_t *, void *);
-static int i8042_read(chardev_srv_t *, void *, size_t);
-static int i8042_write(chardev_srv_t *, const void *, size_t);
+static int i8042_read(chardev_srv_t *, void *, size_t, size_t *);
+static int i8042_write(chardev_srv_t *, const void *, size_t, size_t *);
 
 static chardev_ops_t i8042_chardev_ops = {
@@ -121,21 +122,27 @@
  * Write new data to the corresponding buffer.
  *
- * @param iid  Call id.
  * @param call pointerr to call data.
  * @param dev  Device that caued the interrupt.
  *
  */
-static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call,
-    ddf_dev_t *dev)
+static void i8042_irq_handler(ipc_call_t *call, ddf_dev_t *dev)
 {
 	i8042_t *controller = ddf_dev_data_get(dev);
+	int rc;
 	
 	const uint8_t status = IPC_GET_ARG1(*call);
 	const uint8_t data = IPC_GET_ARG2(*call);
 	
-	buffer_t *buffer = (status & i8042_AUX_DATA) ?
-	    &controller->aux_buffer : &controller->kbd_buffer;
-	
-	buffer_write(buffer, data);
+	i8042_port_t *port = (status & i8042_AUX_DATA) ?
+	    controller->aux : controller->kbd;
+	
+	fibril_mutex_lock(&port->buf_lock);
+	
+	rc = circ_buf_push(&port->cbuf, &data);
+	if (rc != EOK)
+		ddf_msg(LVL_ERROR, "Buffer overrun");
+
+	fibril_mutex_unlock(&port->buf_lock);
+	fibril_condvar_broadcast(&port->buf_cv);
 }
 
@@ -159,12 +166,11 @@
 	const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
 	irq_cmd_t cmds[cmd_count];
+	ddf_fun_t *kbd_fun;
+	ddf_fun_t *aux_fun;
 	i8042_regs_t *ar;
-
+	
 	int rc;
 	bool kbd_bound = false;
 	bool aux_bound = false;
-
-	dev->kbd_fun = NULL;
-	dev->aux_fun = NULL;
 	
 	if (regs->size < sizeof(i8042_regs_t)) {
@@ -178,11 +184,11 @@
 	}
 	
-	dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
-	if (dev->kbd_fun == NULL) {
+	kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
+	if (kbd_fun == NULL) {
 		rc = ENOMEM;
 		goto error;
 	};
 	
-	dev->kbd = ddf_fun_data_alloc(dev->kbd_fun, sizeof(i8042_port_t));
+	dev->kbd = ddf_fun_data_alloc(kbd_fun, sizeof(i8042_port_t));
 	if (dev->kbd == NULL) {
 		rc = ENOMEM;
@@ -190,20 +196,23 @@
 	}
 	
+	dev->kbd->fun = kbd_fun;
 	dev->kbd->ctl = dev;
 	chardev_srvs_init(&dev->kbd->cds);
 	dev->kbd->cds.ops = &i8042_chardev_ops;
 	dev->kbd->cds.sarg = dev->kbd;
-	
-	rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
+	fibril_mutex_initialize(&dev->kbd->buf_lock);
+	fibril_condvar_initialize(&dev->kbd->buf_cv);
+	
+	rc = ddf_fun_add_match_id(dev->kbd->fun, "char/xtkbd", 90);
 	if (rc != EOK)
 		goto error;
 	
-	dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
-	if (dev->aux_fun == NULL) {
+	aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
+	if (aux_fun == NULL) {
 		rc = ENOMEM;
 		goto error;
 	}
 	
-	dev->aux = ddf_fun_data_alloc(dev->aux_fun, sizeof(i8042_port_t));
+	dev->aux = ddf_fun_data_alloc(aux_fun, sizeof(i8042_port_t));
 	if (dev->aux == NULL) {
 		rc = ENOMEM;
@@ -211,32 +220,35 @@
 	}
 	
+	dev->aux->fun = aux_fun;
 	dev->aux->ctl = dev;
 	chardev_srvs_init(&dev->aux->cds);
 	dev->aux->cds.ops = &i8042_chardev_ops;
 	dev->aux->cds.sarg = dev->aux;
-	
-	rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
+	fibril_mutex_initialize(&dev->aux->buf_lock);
+	fibril_condvar_initialize(&dev->aux->buf_cv);
+	
+	rc = ddf_fun_add_match_id(dev->aux->fun, "char/ps2mouse", 90);
 	if (rc != EOK)
 		goto error;
 	
-	ddf_fun_set_conn_handler(dev->kbd_fun, i8042_char_conn);
-	ddf_fun_set_conn_handler(dev->aux_fun, i8042_char_conn);
-	
-	buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
-	buffer_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE);
+	ddf_fun_set_conn_handler(dev->kbd->fun, i8042_char_conn);
+	ddf_fun_set_conn_handler(dev->aux->fun, i8042_char_conn);
+	
+	circ_buf_init(&dev->kbd->cbuf, dev->kbd->buf_data, BUFFER_SIZE, 1);
+	circ_buf_init(&dev->aux->cbuf, dev->aux->buf_data, BUFFER_SIZE, 1);
 	fibril_mutex_initialize(&dev->write_guard);
 	
-	rc = ddf_fun_bind(dev->kbd_fun);
+	rc = ddf_fun_bind(dev->kbd->fun);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to bind keyboard function: %s.",
-		    ddf_fun_get_name(dev->kbd_fun));
+		    ddf_fun_get_name(dev->kbd->fun));
 		goto error;
 	}
 	kbd_bound = true;
 	
-	rc = ddf_fun_bind(dev->aux_fun);
+	rc = ddf_fun_bind(dev->aux->fun);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to bind aux function: %s.",
-		    ddf_fun_get_name(dev->aux_fun));
+		    ddf_fun_get_name(dev->aux->fun));
 		goto error;
 	}
@@ -269,8 +281,8 @@
 	};
 	
-	const int irq_kbd_cap = register_interrupt_handler(ddf_dev, irq_kbd,
-	    i8042_irq_handler, &irq_code);
-	if (irq_kbd_cap < 0) {
-		rc = irq_kbd_cap;
+	int irq_kbd_cap;
+	rc = register_interrupt_handler(ddf_dev, irq_kbd,
+	    i8042_irq_handler, &irq_code, &irq_kbd_cap);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
 		    ddf_dev_get_name(ddf_dev));
@@ -278,8 +290,8 @@
 	}
 	
-	const int irq_mouse_cap = register_interrupt_handler(ddf_dev, irq_mouse,
-	    i8042_irq_handler, &irq_code);
-	if (irq_mouse_cap < 0) {
-		rc = irq_mouse_cap;
+	int irq_mouse_cap;
+	rc = register_interrupt_handler(ddf_dev, irq_mouse,
+	    i8042_irq_handler, &irq_code, &irq_mouse_cap);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
 		    ddf_dev_get_name(ddf_dev));
@@ -317,11 +329,11 @@
 error:
 	if (kbd_bound)
-		ddf_fun_unbind(dev->kbd_fun);
+		ddf_fun_unbind(dev->kbd->fun);
 	if (aux_bound)
-		ddf_fun_unbind(dev->aux_fun);
-	if (dev->kbd_fun != NULL)
-		ddf_fun_destroy(dev->kbd_fun);
-	if (dev->aux_fun != NULL)
-		ddf_fun_destroy(dev->aux_fun);
+		ddf_fun_unbind(dev->aux->fun);
+	if (dev->kbd->fun != NULL)
+		ddf_fun_destroy(dev->kbd->fun);
+	if (dev->aux->fun != NULL)
+		ddf_fun_destroy(dev->aux->fun);
 
 	return rc;
@@ -333,9 +345,11 @@
  * @param buffer Data source
  * @param size   Data size
- *
- * @return Bytes written.
- *
- */
-static int i8042_write(chardev_srv_t *srv, const void *data, size_t size)
+ * @param nwr    Place to store number of bytes successfully written
+ *
+ * @return EOK on success or non-zero error code
+ *
+ */
+static int i8042_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwr)
 {
 	i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg;
@@ -357,5 +371,6 @@
 	
 	fibril_mutex_unlock(&i8042->write_guard);
-	return size;
+	*nwr = size;
+	return EOK;
 }
 
@@ -365,21 +380,34 @@
  * @param buffer Data place
  * @param size   Data place size
- *
- * @return Bytes read.
- *
- */
-static int i8042_read(chardev_srv_t *srv, void *dest, size_t size)
+ * @param nread  Place to store number of bytes successfully read
+ *
+ * @return EOK on success or non-zero error code
+ *
+ */
+static int i8042_read(chardev_srv_t *srv, void *dest, size_t size,
+    size_t *nread)
 {
 	i8042_port_t *port = (i8042_port_t *)srv->srvs->sarg;
-	i8042_t *i8042 = port->ctl;
+	size_t p;
 	uint8_t *destp = (uint8_t *)dest;
-	
-	buffer_t *buffer = (port == i8042->aux) ?
-	    &i8042->aux_buffer : &i8042->kbd_buffer;
-	
-	for (size_t i = 0; i < size; ++i)
-		*destp++ = buffer_read(buffer);
-	
-	return size;
+	int rc;
+	
+	fibril_mutex_lock(&port->buf_lock);
+	
+	while (circ_buf_nused(&port->cbuf) == 0)
+		fibril_condvar_wait(&port->buf_cv, &port->buf_lock);
+
+	p = 0;
+	while (p < size) {
+		rc = circ_buf_pop(&port->cbuf, &destp[p]);
+		if (rc != EOK)
+			break;
+		++p;
+	}
+
+	fibril_mutex_unlock(&port->buf_lock);
+
+	*nread = p;
+	return EOK;
 }
 
Index: uspace/drv/char/i8042/i8042.h
===================================================================
--- uspace/drv/char/i8042/i8042.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/i8042/i8042.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -2,4 +2,5 @@
  * Copyright (c) 2006 Josef Cejka
  * Copyright (c) 2011 Jan Vesely
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -40,9 +41,9 @@
 #define i8042_H_
 
+#include <adt/circ_buf.h>
 #include <io/chardev_srv.h>
 #include <ddi.h>
 #include <fibril_synch.h>
 #include <ddf/driver.h>
-#include "buffer.h"
 
 #define NAME  "i8042"
@@ -59,22 +60,31 @@
 /** i8042 Port. */
 typedef struct {
-	struct i8042 *ctl;		/**< Controller */
-	chardev_srvs_t cds;		/**< Character device server data */
+	/** Controller */
+	struct i8042 *ctl;
+	/** Device function */
+	ddf_fun_t *fun;
+	/** Character device server data */
+	chardev_srvs_t cds;
+	/** Circular buffer */
+	circ_buf_t cbuf;
+	/** Buffer data space */
+	uint8_t buf_data[BUFFER_SIZE];
+	/** Protect buffer */
+	fibril_mutex_t buf_lock;
+	/** Signal new data in buffer */
+	fibril_condvar_t buf_cv;
 } i8042_port_t;
 
 /** i8042 Controller. */
 typedef struct i8042 {
-	i8042_regs_t *regs;             /**< I/O registers. */
-	ddf_fun_t *kbd_fun;             /**< Pirmary port device function. */
-	ddf_fun_t *aux_fun;             /**< Auxiliary port device function. */
-	buffer_t kbd_buffer;            /**< Primary port buffer. */
-	buffer_t aux_buffer;            /**< Aux. port buffer. */
-	uint8_t aux_data[BUFFER_SIZE];  /**< Primary port buffer space. */
-	uint8_t kbd_data[BUFFER_SIZE];  /**< Aux. port buffer space. */
+	/**< I/O registers. */
+	i8042_regs_t *regs;
+	/** Keyboard port */
 	i8042_port_t *kbd;
+	/** AUX port */
 	i8042_port_t *aux;
-	fibril_mutex_t write_guard;     /**< Prevents simultanous port writes.*/
+	/** Prevents simultanous port writes.*/
+	fibril_mutex_t write_guard;
 } i8042_t;
-
 
 extern int i8042_init(i8042_t *, addr_range_t *, int, int, ddf_dev_t *);
Index: uspace/drv/char/msim-con/msim-con.c
===================================================================
--- uspace/drv/char/msim-con/msim-con.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/msim-con/msim-con.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,5 +37,5 @@
 #include <ddi.h>
 #include <errno.h>
-#include <ipc/char.h>
+#include <io/chardev_srv.h>
 
 #include "msim-con.h"
@@ -43,12 +43,13 @@
 static void msim_con_connection(ipc_callid_t, ipc_call_t *, void *);
 
-static irq_pio_range_t msim_ranges[] = {
-	{
-		.base = 0,
-		.size = 1
-	}
+static int msim_con_read(chardev_srv_t *, void *, size_t, size_t *);
+static int msim_con_write(chardev_srv_t *, const void *, size_t, size_t *);
+
+static chardev_ops_t msim_con_chardev_ops = {
+	.read = msim_con_read,
+	.write = msim_con_write
 };
 
-static irq_cmd_t msim_cmds[] = {
+static irq_cmd_t msim_cmds_proto[] = {
 	{
 		.cmd = CMD_PIO_READ_8,
@@ -61,23 +62,19 @@
 };
 
-static irq_code_t msim_kbd = {
-	sizeof(msim_ranges) / sizeof(irq_pio_range_t),
-	msim_ranges,
-	sizeof(msim_cmds) / sizeof(irq_cmd_t),
-	msim_cmds
-};
-
-static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call, void *arg)
+static void msim_irq_handler(ipc_call_t *call, void *arg)
 {
 	msim_con_t *con = (msim_con_t *) arg;
 	uint8_t c;
+	int rc;
+
+	fibril_mutex_lock(&con->buf_lock);
 
 	c = IPC_GET_ARG2(*call);
-
-	if (con->client_sess != NULL) {
-		async_exch_t *exch = async_exchange_begin(con->client_sess);
-		async_msg_1(exch, CHAR_NOTIF_BYTE, c);
-		async_exchange_end(exch);
-	}
+	rc = circ_buf_push(&con->cbuf, &c);
+	if (rc != EOK)
+		ddf_msg(LVL_ERROR, "Buffer overrun");
+
+	fibril_mutex_unlock(&con->buf_lock);
+	fibril_condvar_broadcast(&con->buf_cv);
 }
 
@@ -87,5 +84,16 @@
 	ddf_fun_t *fun = NULL;
 	bool subscribed = false;
+	irq_cmd_t *msim_cmds = NULL;
 	int rc;
+
+	circ_buf_init(&con->cbuf, con->buf, msim_con_buf_size, 1);
+	fibril_mutex_initialize(&con->buf_lock);
+	fibril_condvar_initialize(&con->buf_cv);
+
+	msim_cmds = malloc(sizeof(msim_cmds_proto));
+	if (msim_cmds == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
 
 	con->res = *res;
@@ -98,10 +106,29 @@
 	}
 
+	rc = pio_enable((void *)res->base, 1, (void **) &con->out_reg);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error enabling I/O");
+		goto error;
+	}
+
 	ddf_fun_set_conn_handler(fun, msim_con_connection);
 
-	msim_ranges[0].base = res->base;
+	con->irq_range[0].base = res->base;
+	con->irq_range[0].size = 1;
+
+	memcpy(msim_cmds, msim_cmds_proto, sizeof(msim_cmds_proto));
 	msim_cmds[0].addr = (void *) res->base;
-	async_irq_subscribe(res->irq, msim_irq_handler, con, &msim_kbd);
+
+	con->irq_code.rangecount = 1;
+	con->irq_code.ranges = con->irq_range;
+	con->irq_code.cmdcount = sizeof(msim_cmds_proto) / sizeof(irq_cmd_t);
+	con->irq_code.cmds = msim_cmds;
+
+	async_irq_subscribe(res->irq, msim_irq_handler, con, &con->irq_code, NULL);
 	subscribed = true;
+
+	chardev_srvs_init(&con->cds);
+	con->cds.ops = &msim_con_chardev_ops;
+	con->cds.sarg = con;
 
 	rc = ddf_fun_bind(fun);
@@ -110,4 +137,6 @@
 		goto error;
 	}
+
+	ddf_fun_add_to_category(fun, "console");
 
 	return EOK;
@@ -117,4 +146,5 @@
 	if (fun != NULL)
 		ddf_fun_destroy(fun);
+	free(msim_cmds);
 
 	return rc;
@@ -135,4 +165,48 @@
 static void msim_con_putchar(msim_con_t *con, uint8_t ch)
 {
+	pio_write_8(con->out_reg, ch);
+}
+
+/** Read from msim console device */
+static int msim_con_read(chardev_srv_t *srv, void *buf, size_t size,
+    size_t *nread)
+{
+	msim_con_t *con = (msim_con_t *) srv->srvs->sarg;
+	size_t p;
+	uint8_t *bp = (uint8_t *) buf;
+	int rc;
+
+	fibril_mutex_lock(&con->buf_lock);
+
+	while (circ_buf_nused(&con->cbuf) == 0)
+		fibril_condvar_wait(&con->buf_cv, &con->buf_lock);
+
+	p = 0;
+	while (p < size) {
+		rc = circ_buf_pop(&con->cbuf, &bp[p]);
+		if (rc != EOK)
+			break;
+		++p;
+	}
+
+	fibril_mutex_unlock(&con->buf_lock);
+
+	*nread = p;
+	return EOK;
+}
+
+/** Write to msim console device */
+static int msim_con_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwr)
+{
+	msim_con_t *con = (msim_con_t *) srv->srvs->sarg;
+	size_t i;
+	uint8_t *dp = (uint8_t *) data;
+
+	for (i = 0; i < size; i++)
+		msim_con_putchar(con, dp[i]); 
+
+	*nwr = size;
+	return EOK;
 }
 
@@ -141,43 +215,8 @@
     void *arg)
 {
-	msim_con_t *con;
-
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-
-	con = (msim_con_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
-
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		sysarg_t method = IPC_GET_IMETHOD(call);
-
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-
-		async_sess_t *sess =
-		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
-		if (sess != NULL) {
-			if (con->client_sess == NULL) {
-				con->client_sess = sess;
-				async_answer_0(callid, EOK);
-			} else
-				async_answer_0(callid, ELIMIT);
-		} else {
-			switch (method) {
-			case CHAR_WRITE_BYTE:
-				ddf_msg(LVL_DEBUG, "Write %" PRIun " to device\n",
-				    IPC_GET_ARG1(call));
-				msim_con_putchar(con, (uint8_t) IPC_GET_ARG1(call));
-				async_answer_0(callid, EOK);
-				break;
-			default:
-				async_answer_0(callid, EINVAL);
-			}
-		}
-	}
+	msim_con_t *con = (msim_con_t *) ddf_dev_data_get(
+	    ddf_fun_get_dev((ddf_fun_t *) arg));
+
+	chardev_conn(iid, icall, &con->cds);
 }
 
Index: uspace/drv/char/msim-con/msim-con.h
===================================================================
--- uspace/drv/char/msim-con/msim-con.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/msim-con/msim-con.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,8 +36,16 @@
 #define MSIM_CON_H
 
+#include <adt/circ_buf.h>
 #include <async.h>
 #include <ddf/driver.h>
+#include <ddi.h>
+#include <fibril_synch.h>
+#include <io/chardev_srv.h>
 #include <loc.h>
 #include <stdint.h>
+
+enum {
+	msim_con_buf_size = 64
+};
 
 /** MSIM console resources */
@@ -51,5 +59,13 @@
 	async_sess_t *client_sess;
 	ddf_dev_t *dev;
+	chardev_srvs_t cds;
 	msim_con_res_t res;
+	irq_pio_range_t irq_range[1];
+	irq_code_t irq_code;
+	circ_buf_t cbuf;
+	uint8_t buf[msim_con_buf_size];
+	fibril_mutex_t buf_lock;
+	fibril_condvar_t buf_cv;
+	ioport8_t *out_reg;
 } msim_con_t;
 
Index: uspace/drv/char/ns8250/ns8250.c
===================================================================
--- uspace/drv/char/ns8250/ns8250.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/ns8250/ns8250.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -40,4 +40,5 @@
 #include <stdio.h>
 #include <errno.h>
+#include <str_error.h>
 #include <stdbool.h>
 #include <fibril_synch.h>
@@ -46,5 +47,5 @@
 #include <ctype.h>
 #include <macros.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <dirent.h>
 #include <ddi.h>
@@ -53,5 +54,5 @@
 #include <ddf/interrupt.h>
 #include <ddf/log.h>
-#include <ops/char_dev.h>
+#include <io/chardev_srv.h>
 
 #include <device/hw_res.h>
@@ -153,4 +154,6 @@
 	/** DDF function node */
 	ddf_fun_t *fun;
+	/** Character device service */
+	chardev_srvs_t cds;
 	/** Parent session */
 	async_sess_t *parent_sess;
@@ -189,4 +192,11 @@
 }
 
+/** Obtain soft-state structure from chardev srv */
+static ns8250_t *srv_ns8250(chardev_srv_t *srv)
+{
+	return (ns8250_t *)srv->srvs->sarg;
+}
+
+
 /** Find out if there is some incoming data available on the serial port.
  *
@@ -234,28 +244,33 @@
 /** Read data from the serial port device.
  *
- * @param fun		The serial port function
+ * @param srv		Server-side connection data
  * @param buf		The output buffer for read data.
  * @param count		The number of bytes to be read.
- *
- * @return		The number of bytes actually read on success, negative
- *			error number otherwise.
- */
-static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count)
-{
-	ns8250_t *ns = fun_ns8250(fun);
-	int ret = 0;
-	
-	if (count == 0) return 0;
+ * @param nread		Place to store number of bytes actually read
+ *
+ * @return		EOK on success or non-zero error code
+ */
+static int ns8250_read(chardev_srv_t *srv, void *buf, size_t count, size_t *nread)
+{
+	ns8250_t *ns = srv_ns8250(srv);
+	char *bp = (char *) buf;
+	size_t pos = 0;
+	
+	if (count == 0) {
+		*nread = 0;
+		return EOK;
+	}
 	
 	fibril_mutex_lock(&ns->mutex);
 	while (buf_is_empty(&ns->input_buffer))
 		fibril_condvar_wait(&ns->input_buffer_available, &ns->mutex);
-	while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
-		buf[ret] = (char)buf_pop_front(&ns->input_buffer);
-		ret++;
+	while (!buf_is_empty(&ns->input_buffer) && pos < count) {
+		bp[pos] = (char)buf_pop_front(&ns->input_buffer);
+		pos++;
 	}
 	fibril_mutex_unlock(&ns->mutex);
 	
-	return ret;
+	*nread = pos;
+	return EOK;
 }
 
@@ -274,27 +289,38 @@
 /** Write data to the serial port.
  *
- * @param fun		The serial port function
+ * @param srv		Server-side connection data
  * @param buf		The data to be written
  * @param count		The number of bytes to be written
- * @return		Zero on success
- */
-static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
-{
-	ns8250_t *ns = fun_ns8250(fun);
+ * @param nwritten	Place to store number of bytes successfully written
+ * @return		EOK on success or non-zero error code
+ */
+static int ns8250_write(chardev_srv_t *srv, const void *buf, size_t count,
+    size_t *nwritten)
+{
+	ns8250_t *ns = srv_ns8250(srv);
 	size_t idx;
+	uint8_t *bp = (uint8_t *) buf;
 	
 	for (idx = 0; idx < count; idx++)
-		ns8250_putchar(ns, (uint8_t) buf[idx]);
-	
-	return count;
-}
-
-static ddf_dev_ops_t ns8250_dev_ops;
+		ns8250_putchar(ns, bp[idx]);
+	
+	*nwritten = count;
+	return EOK;
+}
+
+static int ns8250_open(chardev_srvs_t *, chardev_srv_t *);
+static int ns8250_close(chardev_srv_t *);
+static void ns8250_default_handler(chardev_srv_t *, ipc_callid_t, ipc_call_t *);
 
 /** The character interface's callbacks. */
-static char_dev_ops_t ns8250_char_dev_ops = {
-	.read = &ns8250_read,
-	.write = &ns8250_write
+static chardev_ops_t ns8250_chardev_ops = {
+	.open = ns8250_open,
+	.close = ns8250_close,
+	.read = ns8250_read,
+	.write = ns8250_write,
+	.def_handler = ns8250_default_handler
 };
+
+static void ns8250_char_conn(ipc_callid_t, ipc_call_t *, void *);
 
 static int ns8250_dev_add(ddf_dev_t *dev);
@@ -758,6 +784,5 @@
  *
  */
-static inline void ns8250_interrupt_handler(ipc_callid_t iid, ipc_call_t *icall,
-    ddf_dev_t *dev)
+static inline void ns8250_interrupt_handler(ipc_call_t *icall, ddf_dev_t *dev)
 {
 	ns8250_t *ns = dev_ns8250(dev);
@@ -778,8 +803,9 @@
  * @param ns		Serial port device
  */
-static inline int ns8250_register_interrupt_handler(ns8250_t *ns)
+static inline int ns8250_register_interrupt_handler(ns8250_t *ns,
+    cap_handle_t *handle)
 {
 	return register_interrupt_handler(ns->dev, ns->irq,
-	    ns8250_interrupt_handler, NULL);
+	    ns8250_interrupt_handler, NULL, handle);
 }
 
@@ -850,6 +876,6 @@
 	
 	/* Register interrupt handler. */
-	ns->irq_cap = ns8250_register_interrupt_handler(ns);
-	if (ns->irq_cap < 0) {
+	rc = ns8250_register_interrupt_handler(ns, &ns->irq_cap);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to register interrupt handler.");
 		rc = EADDRNOTAVAIL;
@@ -862,5 +888,5 @@
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to enable the interrupt. Error code = "
-		    "%d.", rc);
+		    "%s.", str_error_name(rc));
 		goto fail;
 	}
@@ -872,6 +898,10 @@
 	}
 	
-	/* Set device operations. */
-	ddf_fun_set_ops(fun, &ns8250_dev_ops);
+	ddf_fun_set_conn_handler(fun, ns8250_char_conn);
+	
+	chardev_srvs_init(&ns->cds);
+	ns->cds.ops = &ns8250_chardev_ops;
+	ns->cds.sarg = ns;
+	
 	rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
@@ -930,9 +960,10 @@
  * device.
  *
- * @param dev		The device.
- */
-static int ns8250_open(ddf_fun_t *fun)
-{
-	ns8250_t *ns = fun_ns8250(fun);
+ * @param srvs		Service structure
+ * @param srv		Server-side connection structure
+ */
+static int ns8250_open(chardev_srvs_t *srvs, chardev_srv_t *srv)
+{
+	ns8250_t *ns = srv_ns8250(srv);
 	int res;
 	
@@ -954,9 +985,9 @@
  * the device.
  *
- * @param dev		The device.
- */
-static void ns8250_close(ddf_fun_t *fun)
-{
-	ns8250_t *data = fun_ns8250(fun);
+ * @param srv		Server-side connection structure
+ */
+static int ns8250_close(chardev_srv_t *srv)
+{
+	ns8250_t *data = srv_ns8250(srv);
 	
 	fibril_mutex_lock(&data->mutex);
@@ -968,4 +999,6 @@
 	
 	fibril_mutex_unlock(&data->mutex);
+	
+	return EOK;
 }
 
@@ -1034,7 +1067,8 @@
  * Configure the parameters of the serial communication.
  */
-static void ns8250_default_handler(ddf_fun_t *fun, ipc_callid_t callid,
+static void ns8250_default_handler(chardev_srv_t *srv, ipc_callid_t callid,
     ipc_call_t *call)
 {
+	ns8250_t *ns8250 = srv_ns8250(srv);
 	sysarg_t method = IPC_GET_IMETHOD(*call);
 	int ret;
@@ -1043,5 +1077,5 @@
 	switch (method) {
 	case SERIAL_GET_COM_PROPS:
-		ns8250_get_props(ddf_fun_get_dev(fun), &baud_rate, &parity, &word_length,
+		ns8250_get_props(ns8250->dev, &baud_rate, &parity, &word_length,
 		    &stop_bits);
 		async_answer_4(callid, EOK, baud_rate, parity, word_length,
@@ -1054,5 +1088,5 @@
 		word_length = IPC_GET_ARG3(*call);
 		stop_bits = IPC_GET_ARG4(*call);
-		ret = ns8250_set_props(ddf_fun_get_dev(fun), baud_rate, parity, word_length,
+		ret = ns8250_set_props(ns8250->dev, baud_rate, parity, word_length,
 		    stop_bits);
 		async_answer_0(callid, ret);
@@ -1064,4 +1098,11 @@
 }
 
+void ns8250_char_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ns8250_t *ns8250 = fun_ns8250((ddf_fun_t *)arg);
+
+	chardev_conn(iid, icall, &ns8250->cds);
+}
+
 /** Initialize the serial port driver.
  *
@@ -1072,10 +1113,4 @@
 {
 	ddf_log_init(NAME);
-	
-	ns8250_dev_ops.open = &ns8250_open;
-	ns8250_dev_ops.close = &ns8250_close;
-	
-	ns8250_dev_ops.interfaces[CHAR_DEV_IFACE] = &ns8250_char_dev_ops;
-	ns8250_dev_ops.default_handler = &ns8250_default_handler;
 }
 
Index: uspace/drv/char/pl050/pl050.c
===================================================================
--- uspace/drv/char/pl050/pl050.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/pl050/pl050.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,4 +35,5 @@
 #include <stdio.h>
 #include <errno.h>
+#include <str_error.h>
 #include <ddf/driver.h>
 #include <ddf/interrupt.h>
@@ -54,6 +55,6 @@
 static int pl050_fun_offline(ddf_fun_t *);
 static void pl050_char_conn(ipc_callid_t, ipc_call_t *, void *);
-static int pl050_read(chardev_srv_t *, void *, size_t);
-static int pl050_write(chardev_srv_t *, const void *, size_t);
+static int pl050_read(chardev_srv_t *, void *, size_t, size_t *);
+static int pl050_write(chardev_srv_t *, const void *, size_t, size_t *);
 
 static driver_ops_t driver_ops = {
@@ -137,5 +138,5 @@
 }
 
-static void pl050_interrupt(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev)
+static void pl050_interrupt(ipc_call_t *call, ddf_dev_t *dev)
 {
 	pl050_t *pl050 = (pl050_t *)ddf_dev_data_get(dev);
@@ -212,10 +213,10 @@
 	pl050->regs = regs;
 
-	const int irq_cap = register_interrupt_handler(pl050->dev,
-	    res.irqs.irqs[0], pl050_interrupt, &pl050_irq_code);
-	if (irq_cap < 0) {
-		rc = irq_cap;
-		ddf_msg(LVL_ERROR, "Failed registering interrupt handler. (%d)",
-		    rc);
+	int irq_cap;
+	rc = register_interrupt_handler(pl050->dev,
+	    res.irqs.irqs[0], pl050_interrupt, &pl050_irq_code, &irq_cap);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed registering interrupt handler. (%s)",
+		    str_error_name(rc));
 		goto error;
 	}
@@ -223,5 +224,5 @@
 	rc = hw_res_enable_interrupt(pl050->parent_sess, res.irqs.irqs[0]);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed enabling interrupt. (%d)", rc);
+		ddf_msg(LVL_ERROR, "Failed enabling interrupt: %s", str_error(rc));
 		goto error;
 	}
@@ -236,5 +237,6 @@
 }
 
-static int pl050_read(chardev_srv_t *srv, void *buffer, size_t size)
+static int pl050_read(chardev_srv_t *srv, void *buffer, size_t size,
+    size_t *nread)
 {
 	pl050_t *pl050 = (pl050_t *)srv->srvs->sarg;
@@ -246,6 +248,8 @@
 	left = size;
 	while (left > 0) {
-		while (pl050->buf_rp == pl050->buf_wp)
+		while (left == size && pl050->buf_rp == pl050->buf_wp)
 			fibril_condvar_wait(&pl050->buf_cv, &pl050->buf_lock);
+		if (pl050->buf_rp == pl050->buf_wp)
+			break;
 		*bp++ = pl050->buffer[pl050->buf_rp];
 		--left;
@@ -255,8 +259,10 @@
 	fibril_mutex_unlock(&pl050->buf_lock);
 
-	return size;
-}
-
-static int pl050_write(chardev_srv_t *srv, const void *data, size_t size)
+	*nread = size - left;
+	return EOK;
+}
+
+static int pl050_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwritten)
 {
 	pl050_t *pl050 = (pl050_t *)srv->srvs->sarg;
@@ -276,5 +282,6 @@
 	ddf_msg(LVL_NOTE, "%s/pl050_write() success", pl050->name);
 
-	return size;
+	*nwritten = size;
+	return EOK;
 }
 
@@ -343,5 +350,5 @@
 	rc = ddf_fun_bind(fun_a);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function 'a'. (%d)", rc);
+		ddf_msg(LVL_ERROR, "Failed binding function 'a': %s", str_error(rc));
 		ddf_fun_destroy(fun_a);
 		goto error;
Index: uspace/drv/char/ski-con/ski-con.c
===================================================================
--- uspace/drv/char/ski-con/ski-con.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/ski-con/ski-con.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2005 Jakub Jermar
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -31,11 +31,12 @@
  */
 
+#include <async.h>
 #include <ddf/driver.h>
 #include <ddf/log.h>
 #include <errno.h>
-#include <ipc/char.h>
+#include <fibril.h>
+#include <io/chardev.h>
 #include <stdint.h>
 #include <stdlib.h>
-#include <thread.h>
 #include <stdbool.h>
 
@@ -43,18 +44,33 @@
 
 #define SKI_GETCHAR		21
+#define SKI_PUTCHAR		31
 
 #define POLL_INTERVAL		10000
 
-static void ski_con_thread_impl(void *arg);
+static int ski_con_fibril(void *arg);
 static int32_t ski_con_getchar(void);
 static void ski_con_connection(ipc_callid_t, ipc_call_t *, void *);
 
+static int ski_con_read(chardev_srv_t *, void *, size_t, size_t *);
+static int ski_con_write(chardev_srv_t *, const void *, size_t, size_t *);
+
+static chardev_ops_t ski_con_chardev_ops = {
+	.read = ski_con_read,
+	.write = ski_con_write
+};
+
+static void ski_con_putchar(ski_con_t *con, char ch); /* XXX */
+
 /** Add ski console device. */
 int ski_con_add(ski_con_t *con)
 {
-	thread_id_t tid;
+	fid_t fid;
 	ddf_fun_t *fun = NULL;
 	bool bound = false;
 	int rc;
+
+	circ_buf_init(&con->cbuf, con->buf, ski_con_buf_size, 1);
+	fibril_mutex_initialize(&con->buf_lock);
+	fibril_condvar_initialize(&con->buf_cv);
 
 	fun = ddf_fun_create(con->dev, fun_exposed, "a");
@@ -67,4 +83,8 @@
 	ddf_fun_set_conn_handler(fun, ski_con_connection);
 
+	chardev_srvs_init(&con->cds);
+	con->cds.ops = &ski_con_chardev_ops;
+	con->cds.sarg = con;
+
 	rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
@@ -73,11 +93,16 @@
 	}
 
+	ddf_fun_add_to_category(fun, "console");
+
 	bound = true;
 
-	rc = thread_create(ski_con_thread_impl, con, "kbd_poll", &tid);
-	if (rc != 0) {
-		return rc;
-	}
-
+	fid = fibril_create(ski_con_fibril, con);
+	if (fid == 0) {
+		ddf_msg(LVL_ERROR, "Error creating fibril.");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	fibril_add_ready(fid);
 	return EOK;
 error:
@@ -102,9 +127,10 @@
 }
 
-/** Thread to poll Ski for keypresses. */
-static void ski_con_thread_impl(void *arg)
+/** Poll Ski for keypresses. */
+static int ski_con_fibril(void *arg)
 {
 	int32_t c;
 	ski_con_t *con = (ski_con_t *) arg;
+	int rc;
 
 	while (1) {
@@ -114,13 +140,18 @@
 				break;
 
-			if (con->client_sess != NULL) {
-				async_exch_t *exch = async_exchange_begin(con->client_sess);
-				async_msg_1(exch, CHAR_NOTIF_BYTE, c);
-				async_exchange_end(exch);
-			}
+			fibril_mutex_lock(&con->buf_lock);
+
+			rc = circ_buf_push(&con->cbuf, &c);
+			if (rc != EOK)
+				ddf_msg(LVL_ERROR, "Buffer overrun");
+
+			fibril_mutex_unlock(&con->buf_lock);
+			fibril_condvar_broadcast(&con->buf_cv);
 		}
 
-		thread_usleep(POLL_INTERVAL);
-	}
+		async_usleep(POLL_INTERVAL);
+	}
+
+	return 0;
 }
 
@@ -152,7 +183,73 @@
 }
 
+
+/** Display character on ski debug console
+ *
+ * Use SSC (Simulator System Call) to
+ * display character on debug console.
+ *
+ * @param c Character to be printed.
+ *
+ */
 static void ski_con_putchar(ski_con_t *con, char ch)
 {
-	
+	if (ch == '\n')
+		ski_con_putchar(con, '\r');
+
+#ifdef UARCH_ia64
+	asm volatile (
+		"mov r15 = %0\n"
+		"mov r32 = %1\n"   /* r32 is in0 */
+		"break 0x80000\n"  /* modifies r8 */
+		:
+		: "i" (SKI_PUTCHAR), "r" (ch)
+		: "r15", "in0", "r8"
+	);
+#else
+	(void) ch;
+#endif
+}
+
+/** Read from Ski console device */
+static int ski_con_read(chardev_srv_t *srv, void *buf, size_t size,
+    size_t *nread)
+{
+	ski_con_t *con = (ski_con_t *) srv->srvs->sarg;
+	size_t p;
+	uint8_t *bp = (uint8_t *) buf;
+	int rc;
+
+	fibril_mutex_lock(&con->buf_lock);
+
+	while (circ_buf_nused(&con->cbuf) == 0)
+		fibril_condvar_wait(&con->buf_cv, &con->buf_lock);
+
+	p = 0;
+	while (p < size) {
+		rc = circ_buf_pop(&con->cbuf, &bp[p]);
+		if (rc != EOK)
+			break;
+		++p;
+	}
+
+	fibril_mutex_unlock(&con->buf_lock);
+
+	*nread = p;
+	return EOK;
+}
+
+/** Write to Ski console device */
+static int ski_con_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwr)
+{
+	ski_con_t *con = (ski_con_t *) srv->srvs->sarg;
+	size_t i;
+	uint8_t *dp = (uint8_t *) data;
+
+	for (i = 0; i < size; i++)
+		ski_con_putchar(con, dp[i]); 
+
+	*nwr = size;
+	return EOK;
 }
 
@@ -161,43 +258,8 @@
     void *arg)
 {
-	ski_con_t *con;
-
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-
-	con = (ski_con_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
-
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		sysarg_t method = IPC_GET_IMETHOD(call);
-
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-
-		async_sess_t *sess =
-		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
-		if (sess != NULL) {
-			if (con->client_sess == NULL) {
-				con->client_sess = sess;
-				async_answer_0(callid, EOK);
-			} else
-				async_answer_0(callid, ELIMIT);
-		} else {
-			switch (method) {
-			case CHAR_WRITE_BYTE:
-				ddf_msg(LVL_DEBUG, "Write %" PRIun " to device\n",
-				    IPC_GET_ARG1(call));
-				ski_con_putchar(con, (uint8_t) IPC_GET_ARG1(call));
-				async_answer_0(callid, EOK);
-				break;
-			default:
-				async_answer_0(callid, EINVAL);
-			}
-		}
-	}
+	ski_con_t *con = (ski_con_t *) ddf_dev_data_get(
+	    ddf_fun_get_dev((ddf_fun_t *) arg));
+
+	chardev_conn(iid, icall, &con->cds);
 }
 
Index: uspace/drv/char/ski-con/ski-con.h
===================================================================
--- uspace/drv/char/ski-con/ski-con.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/ski-con/ski-con.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,8 +36,14 @@
 #define SKI_CON_H
 
+#include <adt/circ_buf.h>
 #include <async.h>
 #include <ddf/driver.h>
+#include <io/chardev_srv.h>
 #include <loc.h>
 #include <stdint.h>
+
+enum {
+	ski_con_buf_size = 64
+};
 
 /** Ski console */
@@ -45,4 +51,9 @@
 	async_sess_t *client_sess;
 	ddf_dev_t *dev;
+	chardev_srvs_t cds;
+	circ_buf_t cbuf;
+	uint8_t buf[ski_con_buf_size];
+	fibril_mutex_t buf_lock;
+	fibril_condvar_t buf_cv;
 } ski_con_t;
 
Index: uspace/drv/char/sun4v-con/main.c
===================================================================
--- uspace/drv/char/sun4v-con/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/sun4v-con/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -32,4 +32,5 @@
 #include <ddf/driver.h>
 #include <ddf/log.h>
+#include <device/hw_res_parsed.h>
 #include <errno.h>
 #include <stdio.h>
@@ -58,7 +59,38 @@
 };
 
+static int sun4v_con_get_res(ddf_dev_t *dev, sun4v_con_res_t *res)
+{
+	async_sess_t *parent_sess;
+	hw_res_list_parsed_t hw_res;
+	int rc;
+
+	parent_sess = ddf_dev_parent_sess_get(dev);
+	if (parent_sess == NULL)
+		return ENOMEM;
+
+	hw_res_list_parsed_init(&hw_res);
+	rc = hw_res_get_list_parsed(parent_sess, &hw_res, 0);
+	if (rc != EOK)
+		return rc;
+
+	if (hw_res.mem_ranges.count != 2) {
+		rc = EINVAL;
+		goto error;
+	}
+
+	res->in_base = RNGABS(hw_res.mem_ranges.ranges[0]);
+	res->out_base = RNGABS(hw_res.mem_ranges.ranges[1]);
+	return EOK;
+error:
+	hw_res_list_parsed_clean(&hw_res);
+	return rc;
+}
+
+
 static int sun4v_con_dev_add(ddf_dev_t *dev)
 {
 	sun4v_con_t *sun4v_con;
+	sun4v_con_res_t res;
+	int rc;
 
         ddf_msg(LVL_DEBUG, "sun4v_con_dev_add(%p)", dev);
@@ -71,5 +103,11 @@
 	sun4v_con->dev = dev;
 
-	return sun4v_con_add(sun4v_con);
+	rc = sun4v_con_get_res(dev, &res);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed getting hardware resource list.\n");
+		return EIO;
+	}
+
+	return sun4v_con_add(sun4v_con, &res);
 }
 
Index: uspace/drv/char/sun4v-con/niagara_buf.h
===================================================================
--- uspace/drv/char/sun4v-con/niagara_buf.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/drv/char/sun4v-con/niagara_buf.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,1 @@
+../../../../kernel/arch/sparc64/include/arch/drivers/niagara_buf.h
Index: uspace/drv/char/sun4v-con/sun4v-con.c
===================================================================
--- uspace/drv/char/sun4v-con/sun4v-con.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/sun4v-con/sun4v-con.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2008 Pavel Rimsky
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,8 +36,7 @@
 #include <ddi.h>
 #include <errno.h>
-#include <ipc/char.h>
+#include <str_error.h>
+#include <io/chardev_srv.h>
 #include <stdbool.h>
-#include <sysinfo.h>
-#include <thread.h>
 
 #include "sun4v-con.h"
@@ -47,35 +46,34 @@
 #define POLL_INTERVAL  10000
 
-/*
- * Kernel counterpart of the driver pushes characters (it has read) here.
- * Keep in sync with the definition from
- * kernel/arch/sparc64/src/drivers/niagara.c.
- */
-#define INPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
+static int sun4v_con_read(chardev_srv_t *, void *, size_t, size_t *);
+static int sun4v_con_write(chardev_srv_t *, const void *, size_t, size_t *);
 
-typedef volatile struct {
-	uint64_t write_ptr;
-	uint64_t read_ptr;
-	char data[INPUT_BUFFER_SIZE];
-} __attribute__((packed)) __attribute__((aligned(PAGE_SIZE))) *input_buffer_t;
-
-/* virtual address of the shared buffer */
-static input_buffer_t input_buffer;
-
-static void sun4v_thread_impl(void *arg);
+static chardev_ops_t sun4v_con_chardev_ops = {
+	.read = sun4v_con_read,
+	.write = sun4v_con_write
+};
 
 static void sun4v_con_putchar(sun4v_con_t *con, uint8_t data)
 {
-	(void) con;
-	(void) data;
+	if (data == '\n')
+		sun4v_con_putchar(con, '\r');
+
+	while (con->output_buffer->write_ptr ==
+	    (con->output_buffer->read_ptr + OUTPUT_BUFFER_SIZE - 1)
+	    % OUTPUT_BUFFER_SIZE);
+
+	con->output_buffer->data[con->output_buffer->write_ptr] = data;
+	con->output_buffer->write_ptr =
+	    ((con->output_buffer->write_ptr) + 1) % OUTPUT_BUFFER_SIZE;
 }
 
 /** Add sun4v console device. */
-int sun4v_con_add(sun4v_con_t *con)
+int sun4v_con_add(sun4v_con_t *con, sun4v_con_res_t *res)
 {
 	ddf_fun_t *fun = NULL;
 	int rc;
 
-	input_buffer = (input_buffer_t) AS_AREA_ANY;
+	con->res = *res;
+	con->input_buffer = (niagara_input_buffer_t *) AS_AREA_ANY;
 
 	fun = ddf_fun_create(con->dev, fun_exposed, "a");
@@ -86,24 +84,25 @@
 	}
 
+	chardev_srvs_init(&con->cds);
+	con->cds.ops = &sun4v_con_chardev_ops;
+	con->cds.sarg = con;
+
 	ddf_fun_set_conn_handler(fun, sun4v_con_connection);
 
-	sysarg_t paddr;
-	rc = sysinfo_get_value("niagara.inbuf.address", &paddr);
+	rc = physmem_map(res->in_base, 1, AS_AREA_READ | AS_AREA_WRITE,
+	    (void *) &con->input_buffer);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "niagara.inbuf.address not set (%d)", rc);
+		ddf_msg(LVL_ERROR, "Error mapping memory: %s", str_error_name(rc));
 		goto error;
 	}
 
-	rc = physmem_map(paddr, 1, AS_AREA_READ | AS_AREA_WRITE,
-	    (void *) &input_buffer);
+	con->output_buffer = (niagara_output_buffer_t *) AS_AREA_ANY;
+
+	rc = physmem_map(res->out_base, 1, AS_AREA_READ | AS_AREA_WRITE,
+	    (void *) &con->output_buffer);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Error mapping memory: %d", rc);
-		goto error;
+		ddf_msg(LVL_ERROR, "Error mapping memory: %s", str_error_name(rc));
+		return rc;
 	}
-
-	thread_id_t tid;
-	rc = thread_create(sun4v_thread_impl, con, "kbd_poll", &tid);
-	if (rc != EOK)
-		goto error;
 
 	rc = ddf_fun_bind(fun);
@@ -113,10 +112,13 @@
 	}
 
+	ddf_fun_add_to_category(fun, "console");
+
 	return EOK;
 error:
-	/* XXX Clean up thread */
+	if (con->input_buffer != (niagara_input_buffer_t *) AS_AREA_ANY)
+		physmem_unmap((void *) con->input_buffer);
 
-	if (input_buffer != (input_buffer_t) AS_AREA_ANY)
-		physmem_unmap((void *) input_buffer);
+	if (con->output_buffer != (niagara_output_buffer_t *) AS_AREA_ANY)
+		physmem_unmap((void *) con->output_buffer);
 
 	if (fun != NULL)
@@ -138,36 +140,41 @@
 }
 
-/**
- * Called regularly by the polling thread. Reads codes of all the
- * pressed keys from the buffer.
- */
-static void sun4v_key_pressed(sun4v_con_t *con)
+/** Read from Sun4v console device */
+static int sun4v_con_read(chardev_srv_t *srv, void *buf, size_t size,
+    size_t *nread)
 {
+	sun4v_con_t *con = (sun4v_con_t *) srv->srvs->sarg;
+	size_t p;
+	uint8_t *bp = (uint8_t *) buf;
 	char c;
 
-	while (input_buffer->read_ptr != input_buffer->write_ptr) {
-		c = input_buffer->data[input_buffer->read_ptr];
-		input_buffer->read_ptr =
-		    ((input_buffer->read_ptr) + 1) % INPUT_BUFFER_SIZE;
-		if (con->client_sess != NULL) {
-			async_exch_t *exch = async_exchange_begin(con->client_sess);
-			async_msg_1(exch, CHAR_NOTIF_BYTE, c);
-			async_exchange_end(exch);
-		}
-		(void) c;
+	while (con->input_buffer->read_ptr == con->input_buffer->write_ptr)
+		async_usleep(POLL_INTERVAL);
+
+	p = 0;
+	while (p < size && con->input_buffer->read_ptr != con->input_buffer->write_ptr) {
+		c = con->input_buffer->data[con->input_buffer->read_ptr];
+		con->input_buffer->read_ptr =
+		    ((con->input_buffer->read_ptr) + 1) % INPUT_BUFFER_SIZE;
+		bp[p++] = c;
 	}
+
+	*nread = p;
+	return EOK;
 }
 
-/**
- * Thread to poll Sun4v console for keypresses.
- */
-static void sun4v_thread_impl(void *arg)
+/** Write to Sun4v console device */
+static int sun4v_con_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwr)
 {
-	sun4v_con_t *con = (sun4v_con_t *) arg;
+	sun4v_con_t *con = (sun4v_con_t *) srv->srvs->sarg;
+	size_t i;
+	uint8_t *dp = (uint8_t *) data;
 
-	while (true) {
-		sun4v_key_pressed(con);
-		thread_usleep(POLL_INTERVAL);
-	}
+	for (i = 0; i < size; i++)
+		sun4v_con_putchar(con, dp[i]); 
+
+	*nwr = size;
+	return EOK;
 }
 
@@ -176,43 +183,8 @@
     void *arg)
 {
-	sun4v_con_t *con;
+	sun4v_con_t *con = (sun4v_con_t *) ddf_dev_data_get(
+	    ddf_fun_get_dev((ddf_fun_t *) arg));
 
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-
-	con = (sun4v_con_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
-
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		sysarg_t method = IPC_GET_IMETHOD(call);
-
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-
-		async_sess_t *sess =
-		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
-		if (sess != NULL) {
-			if (con->client_sess == NULL) {
-				con->client_sess = sess;
-				async_answer_0(callid, EOK);
-			} else
-				async_answer_0(callid, ELIMIT);
-		} else {
-			switch (method) {
-			case CHAR_WRITE_BYTE:
-				ddf_msg(LVL_DEBUG, "Write %" PRIun " to device\n",
-				    IPC_GET_ARG1(call));
-				sun4v_con_putchar(con, (uint8_t) IPC_GET_ARG1(call));
-				async_answer_0(callid, EOK);
-				break;
-			default:
-				async_answer_0(callid, EINVAL);
-			}
-		}
-	}
+	chardev_conn(iid, icall, &con->cds);
 }
 
Index: uspace/drv/char/sun4v-con/sun4v-con.h
===================================================================
--- uspace/drv/char/sun4v-con/sun4v-con.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/char/sun4v-con/sun4v-con.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,6 +38,15 @@
 #include <async.h>
 #include <ddf/driver.h>
+#include <io/chardev_srv.h>
 #include <loc.h>
 #include <stdint.h>
+
+#include "niagara_buf.h"
+
+/** Sun4v console resources */
+typedef struct {
+	uintptr_t in_base;
+	uintptr_t out_base;
+} sun4v_con_res_t;
 
 /** Sun4v console */
@@ -45,11 +54,13 @@
 	async_sess_t *client_sess;
 	ddf_dev_t *dev;
+	chardev_srvs_t cds;
+	sun4v_con_res_t res;
+	/** Virtual address of the shared input buffer */
+	niagara_input_buffer_t *input_buffer;
+	/** Virtual address of the shared input buffer */
+	niagara_output_buffer_t *output_buffer;
 } sun4v_con_t;
 
-extern int sun4v_con_init(sun4v_con_t *);
-extern void sun4v_con_write(uint8_t data);
-
-
-extern int sun4v_con_add(sun4v_con_t *);
+extern int sun4v_con_add(sun4v_con_t *, sun4v_con_res_t *);
 extern int sun4v_con_remove(sun4v_con_t *);
 extern int sun4v_con_gone(sun4v_con_t *);
Index: uspace/drv/fb/kfb/port.c
===================================================================
--- uspace/drv/fb/kfb/port.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/fb/kfb/port.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -42,5 +42,5 @@
 #include <errno.h>
 
-#include <malloc.h>
+#include <stdlib.h>
 #include <mem.h>
 #include <as.h>
Index: uspace/drv/hid/atkbd/atkbd.c
===================================================================
--- uspace/drv/hid/atkbd/atkbd.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/hid/atkbd/atkbd.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2017 Jiri Svoboda
  * Copyright (c) 2011 Jan Vesely
  * Copyright (c) 2009 Vineeth Pillai
@@ -201,18 +202,12 @@
 static int polling(void *arg)
 {
-	const at_kbd_t *kbd = arg;
-	
-	assert(kbd);
-	assert(kbd->parent_sess);
-	
-	async_exch_t *parent_exch = async_exchange_begin(kbd->parent_sess);
+	at_kbd_t *kbd = arg;
+	size_t nwr;
+	int rc;
 	
 	while (true) {
-		if (!parent_exch)
-			parent_exch = async_exchange_begin(kbd->parent_sess);
-
 		uint8_t code = 0;
-		ssize_t size = chardev_read(parent_exch, &code, 1);
-		if (size != 1)
+		rc = chardev_read(kbd->chardev, &code, 1, &nwr);
+		if (rc != EOK)
 			return EIO;
 		
@@ -224,46 +219,46 @@
 			map_size = sizeof(scanmap_e0) / sizeof(unsigned int);
 			
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nwr);
+			if (rc != EOK)
 				return EIO;
 		} else if (code == KBD_SCANCODE_SET_EXTENDED_SPECIAL) {
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nwr);
+			if (rc != EOK)
 				return EIO;
 			if (code != 0x14)
 				continue;
 
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nwr);
+			if (rc != EOK)
 				return EIO;
 			if (code != 0x77)
 				continue;
 
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nwr);
+			if (rc != EOK)
 				return EIO;
 			if (code != 0xe1)
 				continue;
 
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nwr);
+			if (rc != EOK)
 				return EIO;
 			if (code != 0xf0)
 				continue;
 
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nwr);
+			if (rc != EOK)
 				return EIO;
 			if (code != 0x14)
 				continue;
 
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nwr);
+			if (rc != EOK)
 				return EIO;
 			if (code != 0xf0)
 				continue;
 
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nwr);
+			if (rc != EOK)
 				return EIO;
 			if (code == 0x77)
@@ -279,6 +274,6 @@
 		if (code == KBD_SCANCODE_KEY_RELEASE) {
 			type = KEY_RELEASE;
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nwr);
+			if (rc != EOK)
 				return EIO;
 		} else {
@@ -362,12 +357,21 @@
 int at_kbd_init(at_kbd_t *kbd, ddf_dev_t *dev)
 {
+	async_sess_t *parent_sess;
+	int rc;
+	
 	assert(kbd);
 	assert(dev);
 	
 	kbd->client_sess = NULL;
-	kbd->parent_sess = ddf_dev_parent_sess_get(dev);
-	
-	if (!kbd->parent_sess) {
+	parent_sess = ddf_dev_parent_sess_get(dev);
+	if (parent_sess == NULL) {
 		ddf_msg(LVL_ERROR, "Failed creating parent session.");
+		rc = EIO;
+		goto error;
+	}
+	
+	rc = chardev_open(parent_sess, &kbd->chardev);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed opening character device.");
 		return EIO;
 	}
@@ -407,3 +411,7 @@
 	fibril_add_ready(kbd->polling_fibril);
 	return EOK;
+error:
+	chardev_close(kbd->chardev);
+	kbd->chardev = NULL;
+	return rc;
 }
Index: uspace/drv/hid/atkbd/atkbd.h
===================================================================
--- uspace/drv/hid/atkbd/atkbd.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/hid/atkbd/atkbd.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Jan Vesely
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -34,16 +35,21 @@
  */
 
-#ifndef _AT_KBD_H_
-#define _AT_KBD_H_
+#ifndef AT_KBD_H_
+#define AT_KBD_H_
 
 #include <ddf/driver.h>
 #include <fibril.h>
+#include <io/chardev.h>
 
 /** PC/AT keyboard driver structure. */
 typedef struct {
-	ddf_fun_t *kbd_fun;        /**< Keyboard function. */
-	async_sess_t *parent_sess; /**< Connection to device providing data. */
-	async_sess_t *client_sess; /**< Callback connection to client. */
-	fid_t polling_fibril;      /**< Fibril retrieving an parsing data. */
+	/** Keyboard function */
+	ddf_fun_t *kbd_fun;
+	/** Device providing keyboard connection */
+	chardev_t *chardev;
+	/** Callback connection to client */
+	async_sess_t *client_sess; 
+	/** Fibril retrieving and parsing data */
+	fid_t polling_fibril;
 } at_kbd_t;
 
Index: uspace/drv/hid/ps2mouse/main.c
===================================================================
--- uspace/drv/hid/ps2mouse/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/hid/ps2mouse/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,5 +30,5 @@
  */
 /** @file
- * @brief ps/2 mouse driver
+ * @brief PS/2 mouse driver
  */
 
Index: uspace/drv/hid/ps2mouse/ps2mouse.c
===================================================================
--- uspace/drv/hid/ps2mouse/ps2mouse.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/hid/ps2mouse/ps2mouse.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Jan Vesely
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -30,9 +31,10 @@
  */
 /** @file
- * @brief ps2 mouse driver.
+ * @brief PS/2 mouse driver.
  */
 
 #include <stdbool.h>
 #include <errno.h>
+#include <str_error.h>
 #include <ddf/log.h>
 #include <io/keycode.h>
@@ -70,12 +72,13 @@
 #define PS2_BUTTON_MASK(button) (1 << button)
 
-#define MOUSE_READ_BYTE_TEST(sess, value_) \
+#define MOUSE_READ_BYTE_TEST(mouse, value_) \
 do { \
 	uint8_t value = (value_); \
 	uint8_t data = 0; \
-	const ssize_t size = chardev_read(sess, &data, 1); \
-	if (size != 1) { \
-		ddf_msg(LVL_ERROR, "Failed reading byte: %zd)", size);\
-		return size < 0 ? size : EIO; \
+	size_t nread; \
+	const int rc = chardev_read((mouse)->chardev, &data, 1, &nread); \
+	if (rc != EOK) { \
+		ddf_msg(LVL_ERROR, "Failed reading byte: %s", str_error_name(rc));\
+		return rc; \
 	} \
 	if (data != value) { \
@@ -86,12 +89,13 @@
 } while (0)
 
-#define MOUSE_WRITE_BYTE(sess, value_) \
+#define MOUSE_WRITE_BYTE(mouse, value_) \
 do { \
 	uint8_t value = (value_); \
 	uint8_t data = (value); \
-	const ssize_t size = chardev_write(sess, &data, 1); \
-	if (size < 0 ) { \
-		ddf_msg(LVL_ERROR, "Failed writing byte: %hhx", value); \
-		return size; \
+	size_t nwr; \
+	const int rc = chardev_write((mouse)->chardev, &data, 1, &nwr); \
+	if (rc != EOK) { \
+		ddf_msg(LVL_ERROR, "Failed writing byte: %s", str_error_name(rc)); \
+		return rc; \
 	} \
 } while (0)
@@ -99,5 +103,5 @@
 static int polling_ps2(void *);
 static int polling_intellimouse(void *);
-static int probe_intellimouse(async_exch_t *, bool);
+static int probe_intellimouse(ps2_mouse_t *, bool);
 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
 
@@ -108,71 +112,133 @@
 
 /** Initialize mouse driver structure.
+ *
+ * Connects to parent, creates keyboard function, starts polling fibril.
+ *
  * @param kbd Mouse driver structure to initialize.
  * @param dev DDF device structure.
  *
- * Connects to parent, creates keyboard function, starts polling fibril.
+ * @return EOK on success or non-zero error code
  */
 int ps2_mouse_init(ps2_mouse_t *mouse, ddf_dev_t *dev)
 {
+	async_sess_t *parent_sess;
+	bool bound = false;
+	int rc;
+
 	mouse->client_sess = NULL;
-	mouse->parent_sess = ddf_dev_parent_sess_get(dev);
-	if (!mouse->parent_sess)
-		return ENOMEM;
+
+	parent_sess = ddf_dev_parent_sess_get(dev);
+	if (parent_sess == NULL) {
+		ddf_msg(LVL_ERROR, "Failed getting parent session.");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = chardev_open(parent_sess, &mouse->chardev);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed opening character device.");
+		goto error;
+	}
 
 	mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
-	if (!mouse->mouse_fun) {
-		return ENOMEM;
-	}
+	if (mouse->mouse_fun == NULL) {
+		ddf_msg(LVL_ERROR, "Error creating mouse function.");
+		rc = ENOMEM;
+		goto error;
+	}
+
 	ddf_fun_set_ops(mouse->mouse_fun, &mouse_ops);
 
-	int ret = ddf_fun_bind(mouse->mouse_fun);
-	if (ret != EOK) {
-		ddf_fun_destroy(mouse->mouse_fun);
-		return ENOMEM;
-	}
-
-	ret = ddf_fun_add_to_category(mouse->mouse_fun, "mouse");
-	if (ret != EOK) {
-		ddf_fun_unbind(mouse->mouse_fun);
-		ddf_fun_destroy(mouse->mouse_fun);
-		return ENOMEM;
-	}
+	rc = ddf_fun_bind(mouse->mouse_fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding mouse function.");
+		goto error;
+	}
+
+	bound = true;
+
+	rc = ddf_fun_add_to_category(mouse->mouse_fun, "mouse");
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding mouse function to category.");
+		goto error;
+	}
+
 	/* Probe IntelliMouse extensions. */
 	int (*polling_f)(void*) = polling_ps2;
-	async_exch_t *exch = async_exchange_begin(mouse->parent_sess);
-	if (probe_intellimouse(exch, false) == EOK) {
+	if (probe_intellimouse(mouse, false) == EOK) {
 		ddf_msg(LVL_NOTE, "Enabled IntelliMouse extensions");
 		polling_f = polling_intellimouse;
-		if (probe_intellimouse(exch, true) == EOK)
+		if (probe_intellimouse(mouse, true) == EOK)
 			ddf_msg(LVL_NOTE, "Enabled 4th and 5th button.");
 	}
+
 	/* Enable mouse data reporting. */
 	uint8_t report = PS2_MOUSE_ENABLE_DATA_REPORT;
-	ssize_t size = chardev_write(exch, &report, 1);
-	if (size != 1) {
+	size_t nwr;
+	rc = chardev_write(mouse->chardev, &report, 1, &nwr);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to enable data reporting.");
-		async_exchange_end(exch);
-		ddf_fun_unbind(mouse->mouse_fun);
-		ddf_fun_destroy(mouse->mouse_fun);
-		return EIO;
-	}
-
-	size = chardev_read(exch, &report, 1);
-	async_exchange_end(exch);
-	if (size != 1 || report != PS2_MOUSE_ACK) {
+		rc = EIO;
+		goto error;
+	}
+
+	size_t nread;
+	rc = chardev_read(mouse->chardev, &report, 1, &nread);
+	if (rc != EOK || report != PS2_MOUSE_ACK) {
 		ddf_msg(LVL_ERROR, "Failed to confirm data reporting: %hhx.",
 		    report);
+		rc = EIO;
+		goto error;
+	}
+
+	mouse->polling_fibril = fibril_create(polling_f, mouse);
+	if (mouse->polling_fibril == 0) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	fibril_add_ready(mouse->polling_fibril);
+	return EOK;
+error:
+	if (bound)
 		ddf_fun_unbind(mouse->mouse_fun);
+	if (mouse->mouse_fun != NULL) {
 		ddf_fun_destroy(mouse->mouse_fun);
-		return EIO;
-	}
-
-	mouse->polling_fibril = fibril_create(polling_f, mouse);
-	if (!mouse->polling_fibril) {
-		ddf_fun_unbind(mouse->mouse_fun);
-		ddf_fun_destroy(mouse->mouse_fun);
-		return ENOMEM;
-	}
-	fibril_add_ready(mouse->polling_fibril);
+		mouse->mouse_fun = NULL;
+	}
+
+	chardev_close(mouse->chardev);
+	mouse->chardev = NULL;
+	return rc;
+}
+
+/** Read fixed-size mouse packet.
+ *
+ * Continue reading until entire packet is received.
+ *
+ * @param mouse Mouse device
+ * @param pbuf Buffer for storing packet
+ * @param psize Packet size
+ *
+ * @return EOK on success or non-zero error code
+ */
+static int ps2_mouse_read_packet(ps2_mouse_t *mouse, void *pbuf, size_t psize)
+{
+	int rc;
+	size_t pos;
+	size_t nread;
+
+	pos = 0;
+	while (pos < psize) {
+		rc = chardev_read(mouse->chardev, pbuf + pos, psize - pos,
+		    &nread);
+		if (rc != EOK) {
+			ddf_msg(LVL_WARN, "Error reading packet.");
+			return rc;
+		}
+
+		pos += nread;
+	}
+
 	return EOK;
 }
@@ -184,20 +250,14 @@
 int polling_ps2(void *arg)
 {
-	assert(arg);
-	const ps2_mouse_t *mouse = arg;
-
-	assert(mouse->parent_sess);
+	ps2_mouse_t *mouse = (ps2_mouse_t *) arg;
+	int rc;
+
 	bool buttons[PS2_BUTTON_COUNT] = {};
-	async_exch_t *parent_exch = async_exchange_begin(mouse->parent_sess);
 	while (1) {
-
 		uint8_t packet[PS2_BUFSIZE] = {};
-		const ssize_t size =
-		    chardev_read(parent_exch, packet, PS2_BUFSIZE);
-
-		if (size != PS2_BUFSIZE) {
-			ddf_msg(LVL_WARN, "Incorrect packet size: %zd.", size);
+		rc = ps2_mouse_read_packet(mouse, packet, PS2_BUFSIZE);
+		if (rc != EOK)
 			continue;
-		}
+
 		ddf_msg(LVL_DEBUG2, "Got packet: %hhx:%hhx:%hhx.",
 		    packet[0], packet[1], packet[2]);
@@ -232,5 +292,6 @@
 		async_exchange_end(exch);
 	}
-	async_exchange_end(parent_exch);
+
+	return 0;
 }
 
@@ -241,22 +302,14 @@
 static int polling_intellimouse(void *arg)
 {
-	assert(arg);
-	const ps2_mouse_t *mouse = arg;
-
-	assert(mouse->parent_sess);
+	ps2_mouse_t *mouse = (ps2_mouse_t *) arg;
+	int rc;
+
 	bool buttons[INTELLIMOUSE_BUTTON_COUNT] = {};
-	async_exch_t *parent_exch = NULL;
 	while (1) {
-		if (!parent_exch)
-			parent_exch = async_exchange_begin(mouse->parent_sess);
-
 		uint8_t packet[INTELLIMOUSE_BUFSIZE] = {};
-		const ssize_t size = chardev_read(
-		    parent_exch, packet, INTELLIMOUSE_BUFSIZE);
-
-		if (size != INTELLIMOUSE_BUFSIZE) {
-			ddf_msg(LVL_WARN, "Incorrect packet size: %zd.", size);
+		rc = ps2_mouse_read_packet(mouse, packet, INTELLIMOUSE_BUFSIZE);
+		if (rc != EOK)
 			continue;
-		}
+
 		ddf_msg(LVL_DEBUG2, "Got packet: %hhx:%hhx:%hhx:%hhx.",
 		    packet[0], packet[1], packet[2], packet[3]);
@@ -310,5 +363,6 @@
 		async_exchange_end(exch);
 	}
-	async_exchange_end(parent_exch);
+
+	return 0;
 }
 
@@ -319,26 +373,24 @@
  * See http://www.computer-engineering.org/ps2mouse/ for details.
  */
-static int probe_intellimouse(async_exch_t *exch, bool buttons)
-{
-	assert(exch);
-
-	MOUSE_WRITE_BYTE(exch, PS2_MOUSE_SET_SAMPLE_RATE);
-	MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
-	MOUSE_WRITE_BYTE(exch, 200);
-	MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
-
-	MOUSE_WRITE_BYTE(exch, PS2_MOUSE_SET_SAMPLE_RATE);
-	MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
-	MOUSE_WRITE_BYTE(exch, buttons ? 200 : 100);
-	MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
-
-	MOUSE_WRITE_BYTE(exch, PS2_MOUSE_SET_SAMPLE_RATE);
-	MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
-	MOUSE_WRITE_BYTE(exch, 80);
-	MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
-
-	MOUSE_WRITE_BYTE(exch, PS2_MOUSE_GET_DEVICE_ID);
-	MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
-	MOUSE_READ_BYTE_TEST(exch, buttons ? 4 : 3);
+static int probe_intellimouse(ps2_mouse_t *mouse, bool buttons)
+{
+	MOUSE_WRITE_BYTE(mouse, PS2_MOUSE_SET_SAMPLE_RATE);
+	MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
+	MOUSE_WRITE_BYTE(mouse, 200);
+	MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
+
+	MOUSE_WRITE_BYTE(mouse, PS2_MOUSE_SET_SAMPLE_RATE);
+	MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
+	MOUSE_WRITE_BYTE(mouse, buttons ? 200 : 100);
+	MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
+
+	MOUSE_WRITE_BYTE(mouse, PS2_MOUSE_SET_SAMPLE_RATE);
+	MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
+	MOUSE_WRITE_BYTE(mouse, 80);
+	MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
+
+	MOUSE_WRITE_BYTE(mouse, PS2_MOUSE_GET_DEVICE_ID);
+	MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
+	MOUSE_READ_BYTE_TEST(mouse, buttons ? 4 : 3);
 
 	return EOK;
Index: uspace/drv/hid/ps2mouse/ps2mouse.h
===================================================================
--- uspace/drv/hid/ps2mouse/ps2mouse.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/hid/ps2mouse/ps2mouse.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Jan Vesely
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -30,24 +31,30 @@
  */
 /** @file
- * @brief ps/2 mouse driver.
+ * @brief PS/2 mouse driver.
  */
 
-#ifndef _PS2MOUSE_H_
-#define _PS2MOUSE_H_
+#ifndef PS2MOUSE_H_
+#define PS2MOUSE_H_
 
 #include <ddf/driver.h>
 #include <fibril.h>
+#include <io/chardev.h>
 
 /** PS/2 mouse driver structure. */
 typedef struct {
-	ddf_fun_t *mouse_fun;      /**< Mouse function. */
-	async_sess_t *parent_sess; /**< Connection to device providing data. */
-	async_sess_t *client_sess;  /**< Callback connection to client. */
-	fid_t polling_fibril;      /**< Fibril retrieving an parsing data. */
+	/** Mouse function. */
+	ddf_fun_t *mouse_fun;
+	/** Device providing mouse connection */
+	chardev_t *chardev;
+	/** Callback connection to client. */
+	async_sess_t *client_sess;
+	/** Fibril retrieving an parsing data. */
+	fid_t polling_fibril;
 } ps2_mouse_t;
 
-int ps2_mouse_init(ps2_mouse_t *, ddf_dev_t *);
+extern int ps2_mouse_init(ps2_mouse_t *, ddf_dev_t *);
 
 #endif
+
 /**
  * @}
Index: uspace/drv/hid/xtkbd/xtkbd.c
===================================================================
--- uspace/drv/hid/xtkbd/xtkbd.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/hid/xtkbd/xtkbd.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Jan Vesely
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -206,21 +207,15 @@
 static int polling(void *arg)
 {
-	const xt_kbd_t *kbd = arg;
-	
-	assert(kbd);
-	assert(kbd->parent_sess);
-	
-	async_exch_t *parent_exch = async_exchange_begin(kbd->parent_sess);
+	xt_kbd_t *kbd = arg;
+	size_t nread;
+	int rc;
 	
 	while (true) {
-		if (!parent_exch)
-			parent_exch = async_exchange_begin(kbd->parent_sess);
-		
 		const unsigned int *map = scanmap_simple;
 		size_t map_size = sizeof(scanmap_simple) / sizeof(unsigned int);
 		
 		uint8_t code = 0;
-		ssize_t size = chardev_read(parent_exch, &code, 1);
-		if (size != 1)
+		rc = chardev_read(kbd->chardev, &code, 1, &nread);
+		if (rc != EOK)
 			return EIO;
 		
@@ -234,6 +229,6 @@
 			map_size = sizeof(scanmap_e0) / sizeof(unsigned int);
 			
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nread);
+			if (rc != EOK)
 				return EIO;
 			
@@ -241,6 +236,6 @@
 			
 			if (code == 0x2a) {  /* Print Screen */
-				size = chardev_read(parent_exch, &code, 1);
-				if (size != 1)
+				rc = chardev_read(kbd->chardev, &code, 1, &nread);
+				if (rc != EOK)
 					return EIO;
 				
@@ -248,6 +243,6 @@
 					continue;
 				
-				size = chardev_read(parent_exch, &code, 1);
-				if (size != 1)
+				rc = chardev_read(kbd->chardev, &code, 1, &nread);
+				if (rc != EOK)
 					return EIO;
 				
@@ -259,6 +254,6 @@
 			
 			if (code == 0x46) {  /* Break */
-				size = chardev_read(parent_exch, &code, 1);
-				if (size != 1)
+				rc = chardev_read(kbd->chardev, &code, 1, &nread);
+				if (rc != EOK)
 					return EIO;
 				
@@ -266,6 +261,6 @@
 					continue;
 				
-				size = chardev_read(parent_exch, &code, 1);
-				if (size != 1)
+				rc = chardev_read(kbd->chardev, &code, 1, &nread);
+				if (rc != EOK)
 					return EIO;
 				
@@ -279,6 +274,6 @@
 		/* Extended special set */
 		if (code == KBD_SCANCODE_SET_EXTENDED_SPECIAL) {
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nread);
+			if (rc != EOK)
 				return EIO;
 			
@@ -286,6 +281,6 @@
 				continue;
 			
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nread);
+			if (rc != EOK)
 				return EIO;
 			
@@ -293,6 +288,6 @@
 				continue;
 			
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nread);
+			if (rc != EOK)
 				return EIO;
 			
@@ -300,6 +295,6 @@
 				continue;
 			
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nread);
+			if (rc != EOK)
 				return EIO;
 			
@@ -307,6 +302,6 @@
 				continue;
 			
-			size = chardev_read(parent_exch, &code, 1);
-			if (size != 1)
+			rc = chardev_read(kbd->chardev, &code, 1, &nread);
+			if (rc != EOK)
 				return EIO;
 			
@@ -357,9 +352,13 @@
 		uint8_t cmds[] = { KBD_CMD_SET_LEDS, status };
 		
-		async_exch_t *exch = async_exchange_begin(kbd->parent_sess);
-		const ssize_t size = chardev_write(exch, cmds, sizeof(cmds));
-		async_exchange_end(exch);
-		
-		async_answer_0(icallid, size < 0 ? size : EOK);
+		size_t nwr;
+		int rc = chardev_write(kbd->chardev, &cmds[0], 1, &nwr);
+		if (rc != EOK) {
+			async_answer_0(icallid, rc);
+			break;
+		}
+
+		rc = chardev_write(kbd->chardev, &cmds[1], 1, &nwr);
+		async_answer_0(icallid, rc);
 		break;
 	}
@@ -413,48 +412,60 @@
 int xt_kbd_init(xt_kbd_t *kbd, ddf_dev_t *dev)
 {
-	assert(kbd);
-	assert(dev);
+	async_sess_t *parent_sess;
+	bool bound = false;
+	int rc;
 	
 	kbd->client_sess = NULL;
-	kbd->parent_sess = ddf_dev_parent_sess_get(dev);
-	
-	if (!kbd->parent_sess) {
+	
+	parent_sess = ddf_dev_parent_sess_get(dev);
+	if (parent_sess == NULL) {
 		ddf_msg(LVL_ERROR, "Failed creating parent session.");
-		return EIO;
+		rc = EIO;
+		goto error;
+	}
+	
+	rc = chardev_open(parent_sess, &kbd->chardev);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed opening character device.");
+		goto error;
 	}
 	
 	kbd->kbd_fun = ddf_fun_create(dev, fun_exposed, "kbd");
-	if (!kbd->kbd_fun) {
+	if (kbd->kbd_fun == NULL) {
 		ddf_msg(LVL_ERROR, "Failed creating function 'kbd'.");
-		return ENOMEM;
+		rc = ENOMEM;
+		goto error;
 	}
 	
 	ddf_fun_set_ops(kbd->kbd_fun, &kbd_ops);
 	
-	int ret = ddf_fun_bind(kbd->kbd_fun);
-	if (ret != EOK) {
+	rc = ddf_fun_bind(kbd->kbd_fun);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed binding function 'kbd'.");
-		ddf_fun_destroy(kbd->kbd_fun);
-		return EEXIST;
-	}
-	
-	ret = ddf_fun_add_to_category(kbd->kbd_fun, "keyboard");
-	if (ret != EOK) {
+		goto error;
+	}
+	
+	rc = ddf_fun_add_to_category(kbd->kbd_fun, "keyboard");
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed adding function 'kbd' to category "
 		    "'keyboard'.");
-		ddf_fun_unbind(kbd->kbd_fun);
-		ddf_fun_destroy(kbd->kbd_fun);
-		return ENOMEM;
+		goto error;
 	}
 	
 	kbd->polling_fibril = fibril_create(polling, kbd);
-	if (!kbd->polling_fibril) {
+	if (kbd->polling_fibril == 0) {
 		ddf_msg(LVL_ERROR, "Failed creating polling fibril.");
-		ddf_fun_unbind(kbd->kbd_fun);
-		ddf_fun_destroy(kbd->kbd_fun);
-		return ENOMEM;
+		rc = ENOMEM;
+		goto error;
 	}
 	
 	fibril_add_ready(kbd->polling_fibril);
 	return EOK;
+error:
+	if (bound)
+		ddf_fun_unbind(kbd->kbd_fun);
+	if (kbd->kbd_fun != NULL)
+		ddf_fun_destroy(kbd->kbd_fun);
+	chardev_close(kbd->chardev);
+	return rc;
 }
Index: uspace/drv/hid/xtkbd/xtkbd.h
===================================================================
--- uspace/drv/hid/xtkbd/xtkbd.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/hid/xtkbd/xtkbd.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Jan Vesely
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -34,16 +35,22 @@
  */
 
-#ifndef _XT_KBD_H_
-#define _XT_KBD_H_
+#ifndef XT_KBD_H_
+#define XT_KBD_H_
 
+#include <async.h>
 #include <ddf/driver.h>
 #include <fibril.h>
+#include <io/chardev.h>
 
-/** PC/XT keyboard driver structure. */
+/** PC/XT keyboard driver structure */
 typedef struct {
-	ddf_fun_t *kbd_fun;        /**< Keyboard function. */
-	async_sess_t *parent_sess; /**< Connection to device providing data. */
-	async_sess_t *client_sess; /**< Callback connection to client. */
-	fid_t polling_fibril;      /**< Fibril retrieving an parsing data. */
+	/** Keyboard function */
+	ddf_fun_t *kbd_fun;
+	/** Device providing keyboard connection */
+	chardev_t *chardev;
+	/** Callback connection to client */
+	async_sess_t *client_sess;
+	/** Fibril retrieving an parsing data */
+	fid_t polling_fibril;
 } xt_kbd_t;
 
Index: uspace/drv/intctl/apic/apic.c
===================================================================
--- uspace/drv/intctl/apic/apic.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/intctl/apic/apic.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -45,4 +45,5 @@
 #include <stdbool.h>
 #include <errno.h>
+#include <str_error.h>
 #include <async.h>
 #include <stdio.h>
@@ -220,5 +221,5 @@
 	rc = pio_enable((void *) res->base, IO_APIC_SIZE, &regs);
 	if (rc != EOK) {
-		printf("%s: Failed to enable PIO for APIC: %d\n", NAME, rc);
+		printf("%s: Failed to enable PIO for APIC: %s\n", NAME, str_error(rc));
 		return EIO;
 	}
@@ -237,5 +238,5 @@
 	rc = ddf_fun_bind(fun_a);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function 'a'. (%d)", rc);
+		ddf_msg(LVL_ERROR, "Failed binding function 'a': %s", str_error(rc));
 		goto error;
 	}
Index: uspace/drv/intctl/i8259/i8259.c
===================================================================
--- uspace/drv/intctl/i8259/i8259.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/intctl/i8259/i8259.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -45,4 +45,5 @@
 #include <stdbool.h>
 #include <errno.h>
+#include <str_error.h>
 #include <async.h>
 #include <stdio.h>
@@ -170,5 +171,5 @@
 	rc = ddf_fun_bind(fun_a);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function 'a'. (%d)", rc);
+		ddf_msg(LVL_ERROR, "Failed binding function 'a': %s", str_error(rc));
 		goto error;
 	}
Index: uspace/drv/intctl/icp-ic/icp-ic.c
===================================================================
--- uspace/drv/intctl/icp-ic/icp-ic.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/intctl/icp-ic/icp-ic.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,4 +41,5 @@
 #include <ddf/log.h>
 #include <errno.h>
+#include <str_error.h>
 #include <ipc/irc.h>
 #include <stdint.h>
@@ -136,5 +137,5 @@
 	rc = ddf_fun_bind(fun_a);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function 'a'. (%d)", rc);
+		ddf_msg(LVL_ERROR, "Failed binding function 'a': %s", str_error(rc));
 		goto error;
 	}
Index: uspace/drv/intctl/obio/obio.c
===================================================================
--- uspace/drv/intctl/obio/obio.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/intctl/obio/obio.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -47,4 +47,5 @@
 #include <ddi.h>
 #include <errno.h>
+#include <str_error.h>
 #include <inttypes.h>
 #include <ipc/irc.h>
@@ -125,5 +126,5 @@
 	}
 
-	ddf_msg(LVL_NOTE, "OBIO registers with base at 0x%" PRIun, res->base);
+	ddf_msg(LVL_NOTE, "OBIO registers with base at 0x%" PRIxn, res->base);
 
 	fun_a = ddf_fun_create(obio->dev, fun_exposed, "a");
@@ -138,5 +139,5 @@
 	rc = ddf_fun_bind(fun_a);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function 'a'. (%d)", rc);
+		ddf_msg(LVL_ERROR, "Failed binding function 'a': %s", str_error(rc));
 		goto error;
 	}
Index: uspace/drv/nic/ar9271/ar9271.c
===================================================================
--- uspace/drv/nic/ar9271/ar9271.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/nic/ar9271/ar9271.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -33,4 +33,5 @@
  */
 
+#include <async.h>
 #include <ieee80211.h>
 #include <usb/classes/classes.h>
@@ -41,7 +42,7 @@
 #include <ddf/interrupt.h>
 #include <errno.h>
+#include <str_error.h>
 #include <nic.h>
 #include <macros.h>
-#include <thread.h>
 #include "ath_usb.h"
 #include "wmi.h"
@@ -784,5 +785,5 @@
 			free(buffer);
 			usb_log_error("Error while uploading firmware. "
-			    "Error: %d\n", rc);
+			    "Error: %s\n", str_error_name(rc));
 			return rc;
 		}
@@ -818,5 +819,5 @@
 	
 	/* Wait until firmware is ready - wait for 1 second to be sure. */
-	thread_sleep(1);
+	async_sleep(1);
 	
 	return rc;
@@ -836,5 +837,5 @@
 	if (rc != EOK) {
 		usb_log_error("Failed to create USB device: %s, "
-		    "ERR_NUM = %d\n", err_msg, rc);
+		    "ERR_NUM = %s\n", err_msg, str_error_name(rc));
 		return NULL;
 	}
@@ -853,6 +854,6 @@
 	if (rc != EOK) {
 		free(ar9271);
-		usb_log_error("Failed to initialize AR9271 structure: %d\n",
-		    rc);
+		usb_log_error("Failed to initialize AR9271 structure: %s\n",
+		    str_error_name(rc));
 		return NULL;
 	}
Index: uspace/drv/nic/ar9271/ath_usb.c
===================================================================
--- uspace/drv/nic/ar9271/ath_usb.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/nic/ar9271/ath_usb.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,5 +35,5 @@
 #include <usb/dev/pipes.h>
 #include <usb/debug.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <errno.h>
 #include "ath_usb.h"
Index: uspace/drv/nic/ar9271/htc.c
===================================================================
--- uspace/drv/nic/ar9271/htc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/nic/ar9271/htc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,4 +36,5 @@
 #include <byteorder.h>
 #include <errno.h>
+#include <str_error.h>
 #include "wmi.h"
 #include "htc.h"
@@ -264,5 +265,5 @@
 	if (rc != EOK) {
 		free(buffer);
-		usb_log_error("Failed to send HTC message. Error: %d\n", rc);
+		usb_log_error("Failed to send HTC message. Error: %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -278,5 +279,5 @@
 		free(buffer);
 		usb_log_error("Failed to receive HTC service connect response. "
-		    "Error: %d\n", rc);
+		    "Error: %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -331,5 +332,5 @@
 		free(buffer);
 		usb_log_error("Failed to send HTC config message. "
-		    "Error: %d\n", rc);
+		    "Error: %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -344,5 +345,5 @@
 	if (rc != EOK) {
 		usb_log_error("Failed to receive HTC config response message. "
-		    "Error: %d\n", rc);
+		    "Error: %s\n", str_error_name(rc));
 	}
 	
@@ -376,5 +377,5 @@
 	if (rc != EOK)
 		usb_log_error("Failed to send HTC setup complete message. "
-		    "Error: %d\n", rc);
+		    "Error: %s\n", str_error_name(rc));
 	
 	free(buffer);
@@ -404,5 +405,5 @@
 		free(buffer);
 		usb_log_error("Failed to receive HTC check ready message. "
-		    "Error: %d\n", rc);
+		    "Error: %s\n", str_error_name(rc));
 		return rc;
 	}
Index: uspace/drv/nic/ar9271/wmi.c
===================================================================
--- uspace/drv/nic/ar9271/wmi.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/nic/ar9271/wmi.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,5 +35,6 @@
 #include <usb/debug.h>
 #include <errno.h>
-#include <malloc.h>
+#include <str_error.h>
+#include <stdlib.h>
 #include <mem.h>
 #include <byteorder.h>
@@ -245,5 +246,5 @@
 	if (rc != EOK) {
 		free(buffer);
-		usb_log_error("Failed to send WMI message. Error: %d\n", rc);
+		usb_log_error("Failed to send WMI message. Error: %s\n", str_error_name(rc));
 		return rc;
 	}
@@ -268,5 +269,5 @@
 			free(buffer);
 			usb_log_error("Failed to receive WMI message response. "
-			    "Error: %d\n", rc);
+			    "Error: %s\n", str_error_name(rc));
 			return rc;
 		}
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/nic/e1k/e1k.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -33,4 +33,5 @@
  */
 
+#include <async.h>
 #include <assert.h>
 #include <stdio.h>
@@ -38,5 +39,4 @@
 #include <adt/list.h>
 #include <align.h>
-#include <thread.h>
 #include <byteorder.h>
 #include <as.h>
@@ -372,5 +372,5 @@
 		fibril_mutex_unlock(&e1000->ctrl_lock);
 		
-		thread_usleep(10);
+		async_usleep(10);
 		
 		fibril_mutex_lock(&e1000->ctrl_lock);
@@ -1237,10 +1237,9 @@
 /** Handle device interrupt
  *
- * @param iid   IPC call id
  * @param icall IPC call structure
  * @param dev   E1000 device
  *
  */
-static void e1000_interrupt_handler(ipc_callid_t iid, ipc_call_t *icall,
+static void e1000_interrupt_handler(ipc_call_t *icall,
     ddf_dev_t *dev)
 {
@@ -1260,9 +1259,10 @@
  * @param nic Driver data
  *
- * @return IRQ capability handle if the handler was registered
+ * @param[out] handle  IRQ capability handle if the handler was registered
+ *
  * @return Negative error code otherwise
  *
  */
-inline static int e1000_register_int_handler(nic_t *nic)
+inline static int e1000_register_int_handler(nic_t *nic, cap_handle_t *handle)
 {
 	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
@@ -1275,9 +1275,9 @@
 	e1000_irq_code.cmds[2].addr = e1000->reg_base_phys + E1000_IMC;
 	
-	int cap = register_interrupt_handler(nic_get_ddf_dev(nic), e1000->irq,
-	    e1000_interrupt_handler, &e1000_irq_code);
+	int rc = register_interrupt_handler(nic_get_ddf_dev(nic), e1000->irq,
+	    e1000_interrupt_handler, &e1000_irq_code, handle);
 	
 	fibril_mutex_unlock(&irq_reg_mutex);
-	return cap;
+	return rc;
 }
 
@@ -1725,5 +1725,5 @@
 	
 	/* Wait for the reset */
-	thread_usleep(20);
+	async_usleep(20);
 	
 	/* check if RST_BIT cleared */
@@ -1813,5 +1813,5 @@
 	 * transfers to descriptors.
 	 */
-	thread_usleep(100);
+	async_usleep(100);
 	
 	return EOK;
@@ -2165,7 +2165,7 @@
 	ddf_fun_set_ops(fun, &e1000_dev_ops);
 	
-	int irq_cap = e1000_register_int_handler(nic);
-	if (irq_cap < 0) {
-		rc = irq_cap;
+	int irq_cap;
+	rc = e1000_register_int_handler(nic, &irq_cap);
+	if (rc != EOK) {
 		goto err_fun_create;
 	}
@@ -2239,5 +2239,5 @@
 	uint32_t eerd = E1000_REG_READ(e1000, E1000_EERD);
 	while ((eerd & e1000->info.eerd_done) == 0) {
-		thread_usleep(1);
+		async_usleep(1);
 		eerd = E1000_REG_READ(e1000, E1000_EERD);
 	}
Index: uspace/drv/nic/ne2k/dp8390.c
===================================================================
--- uspace/drv/nic/ne2k/dp8390.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/nic/ne2k/dp8390.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -55,9 +55,9 @@
 
 #include <assert.h>
+#include <async.h>
 #include <byteorder.h>
 #include <errno.h>
 #include <stdio.h>
 #include <ddi.h>
-#include <thread.h>
 #include "dp8390.h"
 
@@ -172,7 +172,7 @@
 	/* Reset the ethernet card */
 	uint8_t val = pio_read_8(ne2k->port + NE2K_RESET);
-	thread_usleep(2000);
+	async_usleep(2000);
 	pio_write_8(ne2k->port + NE2K_RESET, val);
-	thread_usleep(2000);
+	async_usleep(2000);
 	
 	/* Reset the DP8390 */
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -122,7 +122,7 @@
 };
 
-static void ne2k_interrupt_handler(ipc_callid_t, ipc_call_t *, ddf_dev_t *);
-
-static int ne2k_register_interrupt(nic_t *nic_data)
+static void ne2k_interrupt_handler(ipc_call_t *, ddf_dev_t *);
+
+static int ne2k_register_interrupt(nic_t *nic_data, cap_handle_t *handle)
 {
 	ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data);
@@ -160,7 +160,6 @@
 	}
 
-	int irq_cap = register_interrupt_handler(nic_get_ddf_dev(nic_data),
-		ne2k->irq, ne2k_interrupt_handler, &ne2k->code);
-	return irq_cap;
+	return register_interrupt_handler(nic_get_ddf_dev(nic_data),
+		ne2k->irq, ne2k_interrupt_handler, &ne2k->code, handle);
 }
 
@@ -228,6 +227,5 @@
 	ne2k->probed = true;
 	
-	int irq_cap = ne2k_register_interrupt(nic_data);
-	if (irq_cap < 0)
+	if (ne2k_register_interrupt(nic_data, NULL) != EOK)
 		return EINVAL;
 	
@@ -239,10 +237,8 @@
 }
 
-void ne2k_interrupt_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev)
+void ne2k_interrupt_handler(ipc_call_t *call, ddf_dev_t *dev)
 {
 	nic_t *nic_data = DRIVER_DATA(dev);
 	ne2k_interrupt(nic_data, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call));
-	
-	async_answer_0(iid, EOK);
 }
 
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -28,7 +28,7 @@
 
 #include <assert.h>
+#include <async.h>
 #include <errno.h>
 #include <align.h>
-#include <thread.h>
 #include <byteorder.h>
 #include <libarch/barrier.h>
@@ -435,5 +435,5 @@
 	memory_barrier();
 	while(pio_read_8(io_base + CR) & CR_RST) {
-		thread_usleep(1);
+		async_usleep(1);
 		read_barrier();
 	}
@@ -816,11 +816,9 @@
 /** Handle device interrupt
  *
- * @param iid    The IPC call id
  * @param icall  The IPC call structure
  * @param dev    The rtl8139 device
  *
  */
-static void rtl8139_interrupt_handler(ipc_callid_t iid, ipc_call_t *icall,
-    ddf_dev_t *dev)
+static void rtl8139_interrupt_handler(ipc_call_t *icall, ddf_dev_t *dev)
 {
 	assert(dev);
@@ -844,8 +842,9 @@
  *  @param nic_data  The driver data
  *
- *  @return IRQ capability handle if the handler was registered.
+ *  @param[out] handle  IRQ capability handle if the handler was registered.
+ *
  *  @return Negative error code otherwise.
  */
-inline static int rtl8139_register_int_handler(nic_t *nic_data)
+inline static int rtl8139_register_int_handler(nic_t *nic_data, cap_handle_t *handle)
 {
 	rtl8139_t *rtl8139 = nic_get_specific(nic_data);
@@ -858,10 +857,10 @@
 	rtl8139_irq_code.cmds[2].addr = rtl8139->io_addr + ISR;
 	rtl8139_irq_code.cmds[3].addr = rtl8139->io_addr + IMR;
-	int cap = register_interrupt_handler(nic_get_ddf_dev(nic_data),
-	    rtl8139->irq, rtl8139_interrupt_handler, &rtl8139_irq_code);
+	int rc = register_interrupt_handler(nic_get_ddf_dev(nic_data),
+	    rtl8139->irq, rtl8139_interrupt_handler, &rtl8139_irq_code, handle);
 
 	RTL8139_IRQ_STRUCT_UNLOCK();
 
-	return cap;
+	return rc;
 }
 
@@ -1289,7 +1288,7 @@
 
 	/* Register interrupt handler */
-	int irq_cap = rtl8139_register_int_handler(nic_data);
-	if (irq_cap < 0) {
-		rc = irq_cap;
+	int irq_cap;
+	rc = rtl8139_register_int_handler(nic_data, &irq_cap);
+	if (rc != EOK) {
 		goto err_pio;
 	}
Index: uspace/drv/nic/rtl8169/driver.c
===================================================================
--- uspace/drv/nic/rtl8169/driver.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/nic/rtl8169/driver.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -28,5 +28,7 @@
 
 #include <assert.h>
+#include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <align.h>
 #include <byteorder.h>
@@ -34,5 +36,4 @@
 
 #include <as.h>
-#include <thread.h>
 #include <ddf/log.h>
 #include <ddf/interrupt.h>
@@ -72,7 +73,6 @@
 static int rtl8169_on_stopped(nic_t *nic_data);
 static void rtl8169_send_frame(nic_t *nic_data, void *data, size_t size);
-static void rtl8169_irq_handler(ipc_callid_t iid, ipc_call_t *icall,
-    ddf_dev_t *dev);
-static inline int rtl8169_register_int_handler(nic_t *nic_data);
+static void rtl8169_irq_handler(ipc_call_t *icall, ddf_dev_t *dev);
+static inline int rtl8169_register_int_handler(nic_t *nic_data, cap_handle_t *handle);
 static inline void rtl8169_get_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr);
 static inline void rtl8169_set_hwaddr(rtl8169_t *rtl8169, const nic_address_t *addr);
@@ -360,5 +360,5 @@
 }
 
-inline static int rtl8169_register_int_handler(nic_t *nic_data)
+inline static int rtl8169_register_int_handler(nic_t *nic_data, cap_handle_t *handle)
 {
 	rtl8169_t *rtl8169 = nic_get_specific(nic_data);
@@ -368,8 +368,8 @@
 	rtl8169_irq_code.cmds[2].addr = rtl8169->regs + ISR;
 	rtl8169_irq_code.cmds[3].addr = rtl8169->regs + IMR;
-	int irq_cap = register_interrupt_handler(nic_get_ddf_dev(nic_data),
-	    rtl8169->irq, rtl8169_irq_handler, &rtl8169_irq_code);
-
-	return irq_cap;
+	int rc = register_interrupt_handler(nic_get_ddf_dev(nic_data),
+	    rtl8169->irq, rtl8169_irq_handler, &rtl8169_irq_code, handle);
+
+	return rc;
 }
 
@@ -428,8 +428,8 @@
 		goto err_pio;
 
-	int irq_cap = rtl8169_register_int_handler(nic_data);
-	if (irq_cap < 0) {
-		rc = irq_cap;
-		ddf_msg(LVL_ERROR, "Failed to register IRQ handler (%d)", rc);
+	int irq_cap;
+	rc = rtl8169_register_int_handler(nic_data, &irq_cap);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to register IRQ handler (%s)", str_error_name(rc));
 		goto err_irq;
 	}
@@ -707,5 +707,5 @@
 	rc = rtl8169_allocate_buffers(rtl8169);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Error allocating buffers: %d", rc);
+		ddf_msg(LVL_ERROR, "Error allocating buffers: %s", str_error_name(rc));
 		return 0;
 	}
@@ -764,5 +764,5 @@
 	memory_barrier();
 	while (pio_read_8(rtl8169->regs + CR) & CR_RST) {
-		thread_usleep(1);
+		async_usleep(1);
 		read_barrier();
 	}
@@ -1032,6 +1032,5 @@
 }
 
-static void rtl8169_irq_handler(ipc_callid_t iid, ipc_call_t *icall,
-    ddf_dev_t *dev)
+static void rtl8169_irq_handler(ipc_call_t *icall, ddf_dev_t *dev)
 {
 	assert(dev);
@@ -1178,5 +1177,5 @@
 	do {
 		phyar = pio_read_32(rtl8169->regs + PHYAR);
-		thread_usleep(20);
+		async_usleep(20);
 	} while ((phyar & PHYAR_RW_WRITE) == 0);
 
@@ -1196,8 +1195,8 @@
 	do {
 		phyar = pio_read_32(rtl8169->regs + PHYAR);
-		thread_usleep(20);
+		async_usleep(20);
 	} while ((phyar & PHYAR_RW_WRITE) != 0);
 
-	thread_usleep(20);
+	async_usleep(20);
 }
 
Index: uspace/drv/platform/msim/msim.c
===================================================================
--- uspace/drv/platform/msim/msim.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/platform/msim/msim.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -65,10 +65,10 @@
 static void msim_init(void);
 
-/** The root device driver's standard operations. */
+/** Standard driver operations. */
 static driver_ops_t msim_ops = {
 	.dev_add = &msim_dev_add
 };
 
-/** The root device driver structure. */
+/** Driver structure. */
 static driver_t msim_driver = {
 	.name = NAME,
@@ -194,4 +194,7 @@
 	
 	msim_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(msim_fun_t));
+	if (fun == NULL)
+		goto failure;
+	
 	*fun = *fun_proto;
 	
@@ -230,9 +233,8 @@
 }
 
-/** Get the root device.
- *
- * @param dev		The device which is root of the whole device tree (both
- *			of HW and pseudo devices).
- * @return		Zero on success, negative error number otherwise.
+/** Add MSIM platform device.
+ *
+ * @param dev DDF device
+ * @return Zero on success or non-zero error code.
  */
 static int msim_dev_add(ddf_dev_t *dev)
Index: uspace/drv/platform/sun4v/sun4v.c
===================================================================
--- uspace/drv/platform/sun4v/sun4v.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/platform/sun4v/sun4v.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,13 +36,22 @@
  */
 
+#include <as.h>
 #include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-
 #include <ddf/driver.h>
 #include <ddf/log.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ops/hw_res.h>
+#include <ops/pio_window.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysinfo.h>
 
 #define NAME "sun4v"
+
+typedef struct sun4v_fun {
+	hw_resource_list_t hw_resources;
+	pio_window_t pio_window;
+} sun4v_fun_t;
 
 static int sun4v_dev_add(ddf_dev_t *dev);
@@ -57,5 +66,78 @@
 };
 
-static int sun4v_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id)
+static hw_resource_t console_res[] = {
+	{
+		.type = MEM_RANGE,
+		.res.mem_range = {
+			.address = 0,
+			.size = PAGE_SIZE,
+			.relative = true,
+			.endianness = LITTLE_ENDIAN
+		}
+	},
+	{
+		.type = MEM_RANGE,
+		.res.mem_range = {
+			.address = 0,
+			.size = PAGE_SIZE,
+			.relative = true,
+			.endianness = LITTLE_ENDIAN
+		}
+	},
+};
+
+static sun4v_fun_t console_data = {
+	.hw_resources = {
+		sizeof(console_res) / sizeof(console_res[0]),
+		console_res
+	},
+	.pio_window = {
+		.mem = {
+			.base = 0,
+			.size = PAGE_SIZE
+		}
+	}
+};
+
+/** Obtain function soft-state from DDF function node */
+static sun4v_fun_t *sun4v_fun(ddf_fun_t *fnode)
+{
+	return ddf_fun_data_get(fnode);
+}
+
+static hw_resource_list_t *sun4v_get_resources(ddf_fun_t *fnode)
+{
+	sun4v_fun_t *fun = sun4v_fun(fnode);
+
+	assert(fun != NULL);
+	return &fun->hw_resources;
+}
+
+static int sun4v_enable_interrupt(ddf_fun_t *fun, int irq)
+{
+	return true;
+}
+
+static pio_window_t *sun4v_get_pio_window(ddf_fun_t *fnode)
+{
+	sun4v_fun_t *fun = sun4v_fun(fnode);
+
+	assert(fun != NULL);
+	return &fun->pio_window;
+}
+
+static hw_res_ops_t fun_hw_res_ops = {
+	.get_resource_list = &sun4v_get_resources,
+	.enable_interrupt = &sun4v_enable_interrupt,
+};
+
+static pio_window_ops_t fun_pio_window_ops = {
+	.get_pio_window = &sun4v_get_pio_window
+};
+
+static ddf_dev_ops_t sun4v_fun_ops;
+
+static int sun4v_add_fun(ddf_dev_t *dev, const char *name,
+    const char *str_match_id, sun4v_fun_t *fun_proto)
 {
 	ddf_msg(LVL_NOTE, "Adding function '%s'.", name);
@@ -72,4 +154,12 @@
 	}
 
+	sun4v_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(sun4v_fun_t));
+	if (fun == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	*fun = *fun_proto;
+
 	/* Add match ID */
 	rc = ddf_fun_add_match_id(fnode, str_match_id, 100);
@@ -79,6 +169,10 @@
 	}
 
+	/* Set provided operations to the device. */
+	ddf_fun_set_ops(fnode, &sun4v_fun_ops);
+
 	/* Register function. */
-	if (ddf_fun_bind(fnode) != EOK) {
+	rc = ddf_fun_bind(fnode);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
 		goto error;
@@ -98,5 +192,5 @@
 	int rc;
 
-	rc = sun4v_add_fun(dev, "console", "sun4v/console");
+	rc = sun4v_add_fun(dev, "console", "sun4v/console", &console_data);
 	if (rc != EOK)
 		return rc;
@@ -108,5 +202,5 @@
 static int sun4v_dev_add(ddf_dev_t *dev)
 {
-	ddf_msg(LVL_NOTE, "sun4v_dev_add, device handle = %d",
+	ddf_msg(LVL_DEBUG, "sun4v_dev_add, device handle = %d",
 	    (int)ddf_dev_get_handle(dev));
 
@@ -119,4 +213,36 @@
 }
 
+static int sun4v_init(void)
+{
+	int rc;
+	sysarg_t paddr;
+
+	sun4v_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
+	sun4v_fun_ops.interfaces[PIO_WINDOW_DEV_IFACE] = &fun_pio_window_ops;
+
+	rc = ddf_log_init(NAME);
+	if (rc != EOK) {
+		printf(NAME ": Failed initializing logging service\n");
+		return rc;
+	}
+
+	rc = sysinfo_get_value("niagara.inbuf.address", &paddr);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "niagara.inbuf.address not set: %s", str_error(rc));
+		return rc;
+	}
+
+	console_res[0].res.mem_range.address = paddr;
+
+	rc = sysinfo_get_value("niagara.outbuf.address", &paddr);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "niagara.outbuf.address not set: %s", str_error(rc));
+		return rc;
+	}
+
+	console_res[1].res.mem_range.address = paddr;
+	return EOK;
+}
+
 int main(int argc, char *argv[])
 {
@@ -125,9 +251,7 @@
 	printf(NAME ": Sun4v platform driver\n");
 
-	rc = ddf_log_init(NAME);
-	if (rc != EOK) {
-		printf(NAME ": Failed initializing logging service");
+	rc = sun4v_init();
+	if (rc != EOK)
 		return 1;
-	}
 
 	return ddf_driver_main(&sun4v_driver);
Index: uspace/drv/root/virt/devices.def
===================================================================
--- uspace/drv/root/virt/devices.def	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/root/virt/devices.def	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -26,8 +26,4 @@
 },
 {
-	.name = "null",
-	.match_id = "virtual&test1"
-},
-{
 	.name = "test3",
 	.match_id = "virtual&test3"
Index: uspace/drv/test/test1/Makefile
===================================================================
--- uspace/drv/test/test1/Makefile	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/test/test1/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -32,5 +32,4 @@
 
 SOURCES = \
-	char.c \
 	test1.c
 
Index: pace/drv/test/test1/char.c
===================================================================
--- uspace/drv/test/test1/char.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,56 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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.
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <mem.h>
-#include <ops/char_dev.h>
-
-#include "test1.h"
-
-static int impl_char_read(ddf_fun_t *fun, char *buf, size_t count) {
-	memset(buf, 0, count);
-	return count;
-}
-
-static int imp_char_write(ddf_fun_t *fun, char *buf, size_t count) {
-	return count;
-}
-
-static char_dev_ops_t char_dev_ops = {
-	.read = &impl_char_read,
-	.write = &imp_char_write
-};
-
-ddf_dev_ops_t char_device_ops = {
-	.interfaces[CHAR_DEV_IFACE] = &char_dev_ops
-};
-
Index: uspace/drv/test/test1/test1.c
===================================================================
--- uspace/drv/test/test1/test1.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/test/test1/test1.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -177,8 +177,5 @@
 	ddf_fun_add_to_category(fun_a, "virtual");
 
-	if (str_cmp(dev_name, "null") == 0) {
-		ddf_fun_set_ops(fun_a,  &char_device_ops);
-		ddf_fun_add_to_category(fun_a, "virt-null");
-	} else if (str_cmp(dev_name, "test1") == 0) {
+	if (str_cmp(dev_name, "test1") == 0) {
 		(void) register_fun_verbose(dev,
 		    "cloning myself ;-)", "clone",
Index: uspace/drv/test/test1/test1.h
===================================================================
--- uspace/drv/test/test1/test1.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/drv/test/test1/test1.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,3 @@
 #define NAME "test1"
 
-extern ddf_dev_ops_t char_device_ops;
-
 #endif
Index: uspace/lib/bithenge/src/file.c
===================================================================
--- uspace/lib/bithenge/src/file.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/bithenge/src/file.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -77,6 +77,7 @@
 		return ELIMIT;
 
-	ssize_t amount_read = vfs_read(blob->fd, &offset, buffer, *size);
-	if (amount_read < 0)
+	size_t amount_read;
+	int rc = vfs_read(blob->fd, &offset, buffer, *size, &amount_read);
+	if (rc != EOK)
 		return errno;
 	*size += amount_read;
@@ -144,7 +145,8 @@
 	assert(filename);
 
-	int fd = vfs_lookup_open(filename, WALK_REGULAR, MODE_READ);
-	if (fd < 0)
-		return errno;
+	int fd;
+	int rc = vfs_lookup_open(filename, WALK_REGULAR, MODE_READ, &fd);
+	if (rc != EOK)
+		return rc;
 
 	return new_file_blob(out, fd, true);
Index: uspace/lib/block/block.c
===================================================================
--- uspace/lib/block/block.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/block/block.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -49,7 +49,8 @@
 #include <macros.h>
 #include <mem.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <stdio.h>
 #include <stacktrace.h>
+#include <str_error.h>
 #include <offset.h>
 #include <inttypes.h>
@@ -925,6 +926,6 @@
 	int rc = bd_read_blocks(devcon->bd, ba, cnt, buf, size);
 	if (rc != EOK) {
-		printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
-		    " from device handle %" PRIun "\n", rc, cnt, ba,
+		printf("Error %s reading %zu blocks starting at block %" PRIuOFF64
+		    " from device handle %" PRIun "\n", str_error_name(rc), cnt, ba,
 		    devcon->service_id);
 #ifndef NDEBUG
@@ -952,6 +953,6 @@
 	int rc = bd_write_blocks(devcon->bd, ba, cnt, data, size);
 	if (rc != EOK) {
-		printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
-		    " to device handle %" PRIun "\n", rc, cnt, ba, devcon->service_id);
+		printf("Error %s writing %zu blocks starting at block %" PRIuOFF64
+		    " to device handle %" PRIun "\n", str_error_name(rc), cnt, ba, devcon->service_id);
 #ifndef NDEBUG
 		stacktrace_print();
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -118,4 +118,5 @@
 	generic/io/kio.c \
 	generic/io/klog.c \
+	generic/io/serial.c \
 	generic/io/snprintf.c \
 	generic/io/vprintf.c \
@@ -142,4 +143,5 @@
 	generic/getopt.c \
 	generic/adt/checksum.c \
+	generic/adt/circ_buf.c \
 	generic/adt/list.c \
 	generic/adt/hash_table.c \
@@ -180,4 +182,5 @@
 
 TEST_SOURCES = \
+	test/adt/circ_buf.c \
 	test/fibril/timer.c \
 	test/main.c \
Index: uspace/lib/c/arch/arm32/include/libarch/atomic.h
===================================================================
--- uspace/lib/c/arch/arm32/include/libarch/atomic.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/arch/arm32/include/libarch/atomic.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -82,5 +82,5 @@
 	ras_page[1] = 0xffffffff;
 	
-	return (bool) ret;
+	return ret != 0;
 }
 
Index: uspace/lib/c/arch/ia64/src/tls.c
===================================================================
--- uspace/lib/c/arch/ia64/src/tls.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/arch/ia64/src/tls.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,4 @@
 
 #include <tls.h>
-#include <malloc.h>
 
 tcb_t *tls_alloc_arch(void **data, size_t size)
Index: uspace/lib/c/generic/adt/circ_buf.c
===================================================================
--- uspace/lib/c/generic/adt/circ_buf.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/lib/c/generic/adt/circ_buf.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+ 
+/** @file Circular buffer
+ */
+
+#include <adt/circ_buf.h>
+#include <errno.h>
+#include <mem.h>
+#include <stddef.h>
+
+/** Initialize circular buffer.
+ *
+ * @param cbuf Circular buffer
+ * @param buf Buffer for storing data
+ * @param nmemb Number of entries in @a buf
+ * @param size Size of individual buffer entry
+ */
+void circ_buf_init(circ_buf_t *cbuf, void *buf, size_t nmemb, size_t size)
+{
+	cbuf->buf = buf;
+	cbuf->nmemb = nmemb;
+	cbuf->size = size;
+	cbuf->rp = 0;
+	cbuf->wp = 0;
+	cbuf->nused = 0;
+}
+
+/** Return number of free buffer entries.
+ *
+ * @param cbuf Circular buffer
+ * @return Number of free buffer entries
+ */
+size_t circ_buf_nfree(circ_buf_t *cbuf)
+{
+	return cbuf->nmemb - cbuf->nused;
+}
+
+/** Return number of used buffer entries.
+ *
+ * @param cbuf Circular buffer
+ * @return Number of used buffer entries
+ */
+size_t circ_buf_nused(circ_buf_t *cbuf)
+{
+	return cbuf->nused;
+}
+
+/** Push new entry into circular buffer.
+ *
+ * @param cbuf Circular buffer
+ * @param data Pointer to entry data
+ * @return EOK on success, EAGAIN if circular buffer is full
+ */
+int circ_buf_push(circ_buf_t *cbuf, const void *data)
+{
+	if (circ_buf_nfree(cbuf) == 0)
+		return EAGAIN;
+
+	memcpy(cbuf->buf + cbuf->size * cbuf->wp, data, cbuf->size);
+	cbuf->wp = (cbuf->wp + 1) % cbuf->nmemb;
+	cbuf->nused++;
+	return EOK;
+}
+
+/** Pop entry from circular buffer.
+ *
+ * @param cbuf Circular buffer
+ * @param datab Pointer to data buffer for storing entry
+ * @return EOK on success, EAGAIN if circular buffer is full
+ */
+int circ_buf_pop(circ_buf_t *cbuf, void *datab)
+{
+	if (cbuf->nused == 0)
+		return EAGAIN;
+
+	memcpy(datab, cbuf->buf + cbuf->size * cbuf->rp, cbuf->size);
+	cbuf->rp = (cbuf->rp + 1) % cbuf->nmemb;
+	cbuf->nused--;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/adt/hash_table.c
===================================================================
--- uspace/lib/c/generic/adt/hash_table.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/adt/hash_table.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -51,6 +51,6 @@
 #include <adt/hash_table.h>
 #include <adt/list.h>
-#include <malloc.h>
 #include <assert.h>
+#include <stdlib.h>
 #include <str.h>
 
Index: uspace/lib/c/generic/as.c
===================================================================
--- uspace/lib/c/generic/as.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/as.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,5 +40,4 @@
 #include <stdint.h>
 #include <bitops.h>
-#include <malloc.h>
 #include "private/libc.h"
 
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/async.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -77,17 +77,17 @@
  *   }
  *
- *   port_handler(icallid, *icall)
+ *   port_handler(ichandle, *icall)
  *   {
  *     if (want_refuse) {
- *       async_answer_0(icallid, ELIMIT);
+ *       async_answer_0(ichandle, ELIMIT);
  *       return;
  *     }
- *     async_answer_0(icallid, EOK);
- *
- *     callid = async_get_call(&call);
- *     somehow_handle_the_call(callid, call);
- *     async_answer_2(callid, 1, 2, 3);
- *
- *     callid = async_get_call(&call);
+ *     async_answer_0(ichandle, EOK);
+ *
+ *     chandle = async_get_call(&call);
+ *     somehow_handle_the_call(chandle, call);
+ *     async_answer_2(chandle, 1, 2, 3);
+ *
+ *     chandle = async_get_call(&call);
  *     ...
  *   }
@@ -113,5 +113,5 @@
 #include <libarch/barrier.h>
 #include <stdbool.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <mem.h>
 #include <stdlib.h>
@@ -185,5 +185,5 @@
 	link_t link;
 	
-	ipc_callid_t callid;
+	cap_handle_t chandle;
 	ipc_call_t call;
 } msg_t;
@@ -237,5 +237,5 @@
 	
 	/** Identification of the opening call. */
-	ipc_callid_t callid;
+	cap_handle_t chandle;
 	
 	/** Call data of the opening call. */
@@ -243,5 +243,5 @@
 	
 	/** Identification of the closing call. */
-	ipc_callid_t close_callid;
+	cap_handle_t close_chandle;
 	
 	/** Fibril function that will be used to handle the connection. */
@@ -374,16 +374,16 @@
 /** Default fallback fibril function.
  *
- * This fallback fibril function gets called on incomming
- * connections that do not have a specific handler defined.
- *
- * @param callid Hash of the incoming call.
- * @param call   Data of the incoming call.
- * @param arg    Local argument
- *
- */
-static void default_fallback_port_handler(ipc_callid_t callid, ipc_call_t *call,
-    void *arg)
-{
-	ipc_answer_0(callid, ENOENT);
+ * This fallback fibril function gets called on incomming connections that do
+ * not have a specific handler defined.
+ *
+ * @param chandle  Handle of the incoming call.
+ * @param call     Data of the incoming call.
+ * @param arg      Local argument
+ *
+ */
+static void default_fallback_port_handler(cap_handle_t chandle,
+    ipc_call_t *call, void *arg)
+{
+	ipc_answer_0(chandle, ENOENT);
 }
 
@@ -715,5 +715,5 @@
 	client_t *client = async_client_get(fibril_connection->in_task_id, true);
 	if (!client) {
-		ipc_answer_0(fibril_connection->callid, ENOMEM);
+		ipc_answer_0(fibril_connection->chandle, ENOMEM);
 		return 0;
 	}
@@ -724,5 +724,5 @@
 	 * Call the connection handler function.
 	 */
-	fibril_connection->handler(fibril_connection->callid,
+	fibril_connection->handler(fibril_connection->chandle,
 	    &fibril_connection->call, fibril_connection->data);
 	
@@ -751,5 +751,5 @@
 		
 		list_remove(&msg->link);
-		ipc_answer_0(msg->callid, EHANGUP);
+		ipc_answer_0(msg->chandle, EHANGUP);
 		free(msg);
 	}
@@ -759,6 +759,6 @@
 	 * i.e. IPC_M_PHONE_HUNGUP.
 	 */
-	if (fibril_connection->close_callid)
-		ipc_answer_0(fibril_connection->close_callid, EOK);
+	if (fibril_connection->close_chandle)
+		ipc_answer_0(fibril_connection->close_chandle, EOK);
 	
 	free(fibril_connection);
@@ -768,29 +768,29 @@
 /** Create a new fibril for a new connection.
  *
- * Create new fibril for connection, fill in connection structures
- * and insert it into the hash table, so that later we can easily
- * do routing of messages to particular fibrils.
- *
- * @param in_task_id    Identification of the incoming connection.
- * @param in_phone_hash Identification of the incoming connection.
- * @param callid        Hash of the opening IPC_M_CONNECT_ME_TO call.
- *                      If callid is zero, the connection was opened by
- *                      accepting the IPC_M_CONNECT_TO_ME call and this
- *                      function is called directly by the server.
- * @param call          Call data of the opening call.
- * @param handler       Connection handler.
- * @param data          Client argument to pass to the connection handler.
- *
- * @return New fibril id or NULL on failure.
+ * Create new fibril for connection, fill in connection structures and insert it
+ * into the hash table, so that later we can easily do routing of messages to
+ * particular fibrils.
+ *
+ * @param in_task_id     Identification of the incoming connection.
+ * @param in_phone_hash  Identification of the incoming connection.
+ * @param chandle        Handle of the opening IPC_M_CONNECT_ME_TO call.
+ *                       If chandle is CAP_NIL, the connection was opened by
+ *                       accepting the IPC_M_CONNECT_TO_ME call and this
+ *                       function is called directly by the server.
+ * @param call           Call data of the opening call.
+ * @param handler        Connection handler.
+ * @param data           Client argument to pass to the connection handler.
+ *
+ * @return  New fibril id or NULL on failure.
  *
  */
 static fid_t async_new_connection(task_id_t in_task_id, sysarg_t in_phone_hash,
-    ipc_callid_t callid, ipc_call_t *call, async_port_handler_t handler,
+    cap_handle_t chandle, ipc_call_t *call, async_port_handler_t handler,
     void *data)
 {
 	connection_t *conn = malloc(sizeof(*conn));
 	if (!conn) {
-		if (callid)
-			ipc_answer_0(callid, ENOMEM);
+		if (chandle != CAP_NIL)
+			ipc_answer_0(chandle, ENOMEM);
 		
 		return (uintptr_t) NULL;
@@ -800,6 +800,6 @@
 	conn->in_phone_hash = in_phone_hash;
 	list_initialize(&conn->msg_queue);
-	conn->callid = callid;
-	conn->close_callid = 0;
+	conn->chandle = chandle;
+	conn->close_chandle = CAP_NIL;
 	conn->handler = handler;
 	conn->data = data;
@@ -815,6 +815,6 @@
 		free(conn);
 		
-		if (callid)
-			ipc_answer_0(callid, ENOMEM);
+		if (chandle != CAP_NIL)
+			ipc_answer_0(chandle, ENOMEM);
 		
 		return (uintptr_t) NULL;
@@ -892,5 +892,5 @@
 	
 	fid_t fid = async_new_connection(answer.in_task_id, phone_hash,
-	    0, NULL, handler, data);
+	    CAP_NIL, NULL, handler, data);
 	if (fid == (uintptr_t) NULL)
 		return ENOMEM;
@@ -961,6 +961,6 @@
  * timeouts are unregistered.
  *
- * @param callid Hash of the incoming call.
- * @param call   Data of the incoming call.
+ * @param chandle  Handle of the incoming call.
+ * @param call     Data of the incoming call.
  *
  * @return False if the call doesn't match any connection.
@@ -968,5 +968,5 @@
  *
  */
-static bool route_call(ipc_callid_t callid, ipc_call_t *call)
+static bool route_call(cap_handle_t chandle, ipc_call_t *call)
 {
 	assert(call);
@@ -991,10 +991,10 @@
 	}
 	
-	msg->callid = callid;
+	msg->chandle = chandle;
 	msg->call = *call;
 	list_append(&msg->link, &conn->msg_queue);
 	
 	if (IPC_GET_IMETHOD(*call) == IPC_M_PHONE_HUNGUP)
-		conn->close_callid = callid;
+		conn->close_chandle = chandle;
 	
 	/* If the connection fibril is waiting for an event, activate it */
@@ -1017,9 +1017,8 @@
 /** Process notification.
  *
- * @param callid Hash of the incoming call.
  * @param call   Data of the incoming call.
  *
  */
-static void process_notification(ipc_callid_t callid, ipc_call_t *call)
+static void process_notification(ipc_call_t *call)
 {
 	async_notification_handler_t handler = NULL;
@@ -1042,5 +1041,5 @@
 	
 	if (handler)
-		handler(callid, call, data);
+		handler(call, data);
 }
 
@@ -1052,10 +1051,11 @@
  * @param ucode   Top-half pseudocode handler.
  *
- * @return IRQ capability handle on success.
+ * @param[out] handle  IRQ capability handle on success.
+ *
  * @return Negative error code.
  *
  */
 int async_irq_subscribe(int inr, async_notification_handler_t handler,
-    void *data, const irq_code_t *ucode)
+    void *data, const irq_code_t *ucode, cap_handle_t *handle)
 {
 	notification_t *notification =
@@ -1077,5 +1077,10 @@
 	futex_up(&async_futex);
 	
-	return ipc_irq_subscribe(inr, imethod, ucode);
+	cap_handle_t cap;
+	int rc = ipc_irq_subscribe(inr, imethod, ucode, &cap);
+	if (rc == EOK && handle != NULL) {
+		*handle = cap;
+	}
+	return rc;
 }
 
@@ -1187,15 +1192,13 @@
 /** Return new incoming message for the current (fibril-local) connection.
  *
- * @param call  Storage where the incoming call data will be stored.
- * @param usecs Timeout in microseconds. Zero denotes no timeout.
- *
- * @return If no timeout was specified, then a hash of the
- *         incoming call is returned. If a timeout is specified,
- *         then a hash of the incoming call is returned unless
- *         the timeout expires prior to receiving a message. In
- *         that case zero is returned.
- *
- */
-ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
+ * @param call   Storage where the incoming call data will be stored.
+ * @param usecs  Timeout in microseconds. Zero denotes no timeout.
+ *
+ * @return  If no timeout was specified, then a handle of the incoming call is
+ *          returned. If a timeout is specified, then a handle of the incoming
+ *          call is returned unless the timeout expires prior to receiving a
+ *          message. In that case zero CAP_NIL is returned.
+ */
+cap_handle_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
 {
 	assert(call);
@@ -1220,5 +1223,5 @@
 	/* If nothing in queue, wait until something arrives */
 	while (list_empty(&conn->msg_queue)) {
-		if (conn->close_callid) {
+		if (conn->close_chandle) {
 			/*
 			 * Handle the case when the connection was already
@@ -1231,5 +1234,5 @@
 			IPC_SET_IMETHOD(*call, IPC_M_PHONE_HUNGUP);
 			futex_up(&async_futex);
-			return conn->close_callid;
+			return conn->close_chandle;
 		}
 		
@@ -1256,5 +1259,5 @@
 			/* If we timed out -> exit */
 			futex_up(&async_futex);
-			return 0;
+			return CAP_NIL;
 		}
 	}
@@ -1264,10 +1267,10 @@
 	list_remove(&msg->link);
 	
-	ipc_callid_t callid = msg->callid;
+	cap_handle_t chandle = msg->chandle;
 	*call = msg->call;
 	free(msg);
 	
 	futex_up(&async_futex);
-	return callid;
+	return chandle;
 }
 
@@ -1332,18 +1335,18 @@
  * Otherwise the call is routed to its connection fibril.
  *
- * @param callid Hash of the incoming call.
- * @param call   Data of the incoming call.
- *
- */
-static void handle_call(ipc_callid_t callid, ipc_call_t *call)
+ * @param chandle  Handle of the incoming call.
+ * @param call     Data of the incoming call.
+ *
+ */
+static void handle_call(cap_handle_t chandle, ipc_call_t *call)
 {
 	assert(call);
 	
 	/* Kernel notification */
-	if ((callid & IPC_CALLID_NOTIFICATION)) {
+	if ((chandle == CAP_NIL) && (call->flags & IPC_CALL_NOTIF)) {
 		fibril_t *fibril = (fibril_t *) __tcb_get()->fibril_data;
 		unsigned oldsw = fibril->switches;
 		
-		process_notification(callid, call);
+		process_notification(call);
 		
 		if (oldsw != fibril->switches) {
@@ -1371,5 +1374,5 @@
 		sysarg_t in_phone_hash = IPC_GET_ARG5(*call);
 		
-		async_notification_handler_t handler = fallback_port_handler;
+		async_port_handler_t handler = fallback_port_handler;
 		void *data = fallback_port_data;
 		
@@ -1381,5 +1384,5 @@
 		}
 		
-		async_new_connection(call->in_task_id, in_phone_hash, callid,
+		async_new_connection(call->in_task_id, in_phone_hash, chandle,
 		    call, handler, data);
 		return;
@@ -1387,9 +1390,9 @@
 	
 	/* Try to route the call through the connection hash table */
-	if (route_call(callid, call))
+	if (route_call(chandle, call))
 		return;
 	
 	/* Unknown call from unknown phone - hang it up */
-	ipc_answer_0(callid, EHANGUP);
+	ipc_answer_0(chandle, EHANGUP);
 }
 
@@ -1486,19 +1489,24 @@
 		
 		ipc_call_t call;
-		ipc_callid_t callid = ipc_wait_cycle(&call, timeout, flags);
+		int rc = ipc_wait_cycle(&call, timeout, flags);
 		
 		atomic_dec(&threads_in_ipc_wait);
 		
-		if (!callid) {
-			handle_expired_timeouts();
+		assert(rc == EOK);
+
+		if (call.cap_handle == CAP_NIL) {
+			if (call.flags == 0) {
+				/* This neither a notification nor an answer. */
+				handle_expired_timeouts();
+				continue;
+			}
+		}
+
+		if (call.flags & IPC_CALL_ANSWERED)
 			continue;
-		}
-		
-		if (callid & IPC_CALLID_ANSWERED)
-			continue;
-		
-		handle_call(callid, &call);
-	}
-	
+
+		handle_call(call.cap_handle, &call);
+	}
+
 	return 0;
 }
@@ -1631,6 +1639,5 @@
  * @param arg3    Service-defined payload argument.
  * @param arg4    Service-defined payload argument.
- * @param dataptr If non-NULL, storage where the reply data will be
- *                stored.
+ * @param dataptr If non-NULL, storage where the reply data will be stored.
  *
  * @return Hash of the sent message or 0 on error.
@@ -1869,4 +1876,23 @@
 }
 
+/** Delay execution for the specified number of seconds
+ *
+ * @param sec Number of seconds to sleep
+ */
+void async_sleep(unsigned int sec)
+{
+	/*
+	 * Sleep in 1000 second steps to support
+	 * full argument range
+	 */
+
+	while (sec > 0) {
+		unsigned int period = (sec > 1000) ? 1000 : sec;
+
+		async_usleep(period * 1000000);
+		sec -= period;
+	}
+}
+
 /** Pseudo-synchronous message sending - fast version.
  *
@@ -2018,39 +2044,39 @@
 }
 
-sysarg_t async_answer_0(ipc_callid_t callid, sysarg_t retval)
-{
-	return ipc_answer_0(callid, retval);
-}
-
-sysarg_t async_answer_1(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1)
-{
-	return ipc_answer_1(callid, retval, arg1);
-}
-
-sysarg_t async_answer_2(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
+sysarg_t async_answer_0(cap_handle_t chandle, sysarg_t retval)
+{
+	return ipc_answer_0(chandle, retval);
+}
+
+sysarg_t async_answer_1(cap_handle_t chandle, sysarg_t retval, sysarg_t arg1)
+{
+	return ipc_answer_1(chandle, retval, arg1);
+}
+
+sysarg_t async_answer_2(cap_handle_t chandle, sysarg_t retval, sysarg_t arg1,
     sysarg_t arg2)
 {
-	return ipc_answer_2(callid, retval, arg1, arg2);
-}
-
-sysarg_t async_answer_3(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
+	return ipc_answer_2(chandle, retval, arg1, arg2);
+}
+
+sysarg_t async_answer_3(cap_handle_t chandle, sysarg_t retval, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3)
 {
-	return ipc_answer_3(callid, retval, arg1, arg2, arg3);
-}
-
-sysarg_t async_answer_4(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
+	return ipc_answer_3(chandle, retval, arg1, arg2, arg3);
+}
+
+sysarg_t async_answer_4(cap_handle_t chandle, sysarg_t retval, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
 {
-	return ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4);
-}
-
-sysarg_t async_answer_5(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
+	return ipc_answer_4(chandle, retval, arg1, arg2, arg3, arg4);
+}
+
+sysarg_t async_answer_5(cap_handle_t chandle, sysarg_t retval, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
 {
-	return ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5);
-}
-
-int async_forward_fast(ipc_callid_t callid, async_exch_t *exch,
+	return ipc_answer_5(chandle, retval, arg1, arg2, arg3, arg4, arg5);
+}
+
+int async_forward_fast(cap_handle_t chandle, async_exch_t *exch,
     sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
 {
@@ -2058,8 +2084,8 @@
 		return ENOENT;
 	
-	return ipc_forward_fast(callid, exch->phone, imethod, arg1, arg2, mode);
-}
-
-int async_forward_slow(ipc_callid_t callid, async_exch_t *exch,
+	return ipc_forward_fast(chandle, exch->phone, imethod, arg1, arg2, mode);
+}
+
+int async_forward_slow(cap_handle_t chandle, async_exch_t *exch,
     sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
     sysarg_t arg4, sysarg_t arg5, unsigned int mode)
@@ -2068,5 +2094,5 @@
 		return ENOENT;
 	
-	return ipc_forward_slow(callid, exch->phone, imethod, arg1, arg2, arg3,
+	return ipc_forward_slow(chandle, exch->phone, imethod, arg1, arg2, arg3,
 	    arg4, arg5, mode);
 }
@@ -2103,7 +2129,11 @@
 
 static int async_connect_me_to_internal(int phone, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3, sysarg_t arg4)
+    sysarg_t arg3, sysarg_t arg4, int *out_phone)
 {
 	ipc_call_t result;
+	
+	// XXX: Workaround for GCC's inability to infer association between
+	// rc == EOK and *out_phone being assigned.
+	*out_phone = -1;
 	
 	amsg_t *msg = amsg_create();
@@ -2123,5 +2153,6 @@
 		return rc;
 	
-	return (int) IPC_GET_ARG5(result);
+	*out_phone = (int) IPC_GET_ARG5(result);
+	return EOK;
 }
 
@@ -2153,8 +2184,9 @@
 	}
 	
-	int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
-	    0);
-	if (phone < 0) {
-		errno = phone;
+	int phone;
+	int rc = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
+	    0, &phone);
+	if (rc != EOK) {
+		errno = rc;
 		free(sess);
 		return NULL;
@@ -2205,8 +2237,9 @@
 	}
 	
-	int phone = async_connect_me_to_internal(exch->phone, iface, arg2,
-	    arg3, 0);
-	if (phone < 0) {
-		errno = phone;
+	int phone;
+	int rc = async_connect_me_to_internal(exch->phone, iface, arg2,
+	    arg3, 0, &phone);
+	if (rc != EOK) {
+		errno = rc;
 		free(sess);
 		return NULL;
@@ -2275,9 +2308,10 @@
 	}
 	
-	int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
-	    IPC_FLAG_BLOCKING);
-	
-	if (phone < 0) {
-		errno = phone;
+	int phone;
+	int rc = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
+	    IPC_FLAG_BLOCKING, &phone);
+	
+	if (rc != EOK) {
+		errno = rc;
 		free(sess);
 		return NULL;
@@ -2328,8 +2362,9 @@
 	}
 	
-	int phone = async_connect_me_to_internal(exch->phone, iface, arg2,
-	    arg3, IPC_FLAG_BLOCKING);
-	if (phone < 0) {
-		errno = phone;
+	int phone;
+	int rc = async_connect_me_to_internal(exch->phone, iface, arg2,
+	    arg3, IPC_FLAG_BLOCKING, &phone);
+	if (rc != EOK) {
+		errno = rc;
 		free(sess);
 		return NULL;
@@ -2363,7 +2398,8 @@
 	}
 	
-	int phone = ipc_connect_kbox(id);
-	if (phone < 0) {
-		errno = phone;
+	cap_handle_t phone;
+	int rc = ipc_connect_kbox(id, &phone);
+	if (rc != EOK) {
+		errno = rc;
 		free(sess);
 		return NULL;
@@ -2482,4 +2518,5 @@
 		} else if (mgmt == EXCHANGE_PARALLEL) {
 			int phone;
+			int rc;
 			
 		retry:
@@ -2487,7 +2524,7 @@
 			 * Make a one-time attempt to connect a new data phone.
 			 */
-			phone = async_connect_me_to_internal(sess->phone, sess->arg1,
-			    sess->arg2, sess->arg3, 0);
-			if (phone >= 0) {
+			rc = async_connect_me_to_internal(sess->phone, sess->arg1,
+			    sess->arg2, sess->arg3, 0, &phone);
+			if (rc == EOK) {
 				exch = (async_exch_t *) malloc(sizeof(async_exch_t));
 				if (exch != NULL) {
@@ -2604,17 +2641,17 @@
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid Storage for the hash of the IPC_M_SHARE_IN call.
- * @param size   Destination address space area size.
+ * @param chandle  Storage for the handle of the IPC_M_SHARE_IN call.
+ * @param size     Destination address space area size.
  *
  * @return True on success, false on failure.
  *
  */
-bool async_share_in_receive(ipc_callid_t *callid, size_t *size)
-{
-	assert(callid);
+bool async_share_in_receive(cap_handle_t *chandle, size_t *size)
+{
+	assert(chandle);
 	assert(size);
 	
 	ipc_call_t data;
-	*callid = async_get_call(&data);
+	*chandle = async_get_call(&data);
 	
 	if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_IN)
@@ -2631,14 +2668,14 @@
  * argument.
  *
- * @param callid Hash of the IPC_M_DATA_READ call to answer.
- * @param src    Source address space base.
- * @param flags  Flags to be used for sharing. Bits can be only cleared.
+ * @param chandle  Handle of the IPC_M_DATA_READ call to answer.
+ * @param src      Source address space base.
+ * @param flags    Flags to be used for sharing. Bits can be only cleared.
  *
  * @return Zero on success or a value from @ref errno.h on failure.
  *
  */
-int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
-{
-	return ipc_answer_3(callid, EOK, (sysarg_t) src, (sysarg_t) flags,
+int async_share_in_finalize(cap_handle_t chandle, void *src, unsigned int flags)
+{
+	return ipc_answer_3(chandle, EOK, (sysarg_t) src, (sysarg_t) flags,
 	    (sysarg_t) __entry);
 }
@@ -2670,19 +2707,20 @@
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid Storage for the hash of the IPC_M_SHARE_OUT call.
- * @param size   Storage for the source address space area size.
- * @param flags  Storage for the sharing flags.
+ * @param chandle  Storage for the hash of the IPC_M_SHARE_OUT call.
+ * @param size     Storage for the source address space area size.
+ * @param flags    Storage for the sharing flags.
  *
  * @return True on success, false on failure.
  *
  */
-bool async_share_out_receive(ipc_callid_t *callid, size_t *size, unsigned int *flags)
-{
-	assert(callid);
+bool async_share_out_receive(cap_handle_t *chandle, size_t *size,
+    unsigned int *flags)
+{
+	assert(chandle);
 	assert(size);
 	assert(flags);
 	
 	ipc_call_t data;
-	*callid = async_get_call(&data);
+	*chandle = async_get_call(&data);
 	
 	if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_OUT)
@@ -2700,14 +2738,14 @@
  * argument.
  *
- * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
- * @param dst    Address of the storage for the destination address space area
- *               base address.
- *
- * @return Zero on success or a value from @ref errno.h on failure.
- *
- */
-int async_share_out_finalize(ipc_callid_t callid, void **dst)
-{
-	return ipc_answer_2(callid, EOK, (sysarg_t) __entry, (sysarg_t) dst);
+ * @param chandle  Handle of the IPC_M_DATA_WRITE call to answer.
+ * @param dst      Address of the storage for the destination address space area
+ *                 base address.
+ *
+ * @return  Zero on success or a value from @ref errno.h on failure.
+ *
+ */
+int async_share_out_finalize(cap_handle_t chandle, void **dst)
+{
+	return ipc_answer_2(chandle, EOK, (sysarg_t) __entry, (sysarg_t) dst);
 }
 
@@ -2755,14 +2793,14 @@
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid Storage for the hash of the IPC_M_DATA_READ.
- * @param size   Storage for the maximum size. Can be NULL.
+ * @param chandle  Storage for the handle of the IPC_M_DATA_READ.
+ * @param size     Storage for the maximum size. Can be NULL.
  *
  * @return True on success, false on failure.
  *
  */
-bool async_data_read_receive(ipc_callid_t *callid, size_t *size)
+bool async_data_read_receive(cap_handle_t *chandle, size_t *size)
 {
 	ipc_call_t data;
-	return async_data_read_receive_call(callid, &data, size);
+	return async_data_read_receive_call(chandle, &data, size);
 }
 
@@ -2775,17 +2813,17 @@
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid Storage for the hash of the IPC_M_DATA_READ.
- * @param size   Storage for the maximum size. Can be NULL.
+ * @param chandle  Storage for the handle of the IPC_M_DATA_READ.
+ * @param size     Storage for the maximum size. Can be NULL.
  *
  * @return True on success, false on failure.
  *
  */
-bool async_data_read_receive_call(ipc_callid_t *callid, ipc_call_t *data,
+bool async_data_read_receive_call(cap_handle_t *chandle, ipc_call_t *data,
     size_t *size)
 {
-	assert(callid);
+	assert(chandle);
 	assert(data);
 	
-	*callid = async_get_call(data);
+	*chandle = async_get_call(data);
 	
 	if (IPC_GET_IMETHOD(*data) != IPC_M_DATA_READ)
@@ -2804,15 +2842,15 @@
  * argument.
  *
- * @param callid Hash of the IPC_M_DATA_READ call to answer.
- * @param src    Source address for the IPC_M_DATA_READ call.
- * @param size   Size for the IPC_M_DATA_READ call. Can be smaller than
- *               the maximum size announced by the sender.
- *
- * @return Zero on success or a value from @ref errno.h on failure.
- *
- */
-int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
-{
-	return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) size);
+ * @param chandle  Handle of the IPC_M_DATA_READ call to answer.
+ * @param src      Source address for the IPC_M_DATA_READ call.
+ * @param size     Size for the IPC_M_DATA_READ call. Can be smaller than
+ *                 the maximum size announced by the sender.
+ *
+ * @return  Zero on success or a value from @ref errno.h on failure.
+ *
+ */
+int async_data_read_finalize(cap_handle_t chandle, const void *src, size_t size)
+{
+	return ipc_answer_2(chandle, EOK, (sysarg_t) src, (sysarg_t) size);
 }
 
@@ -2827,7 +2865,7 @@
 		return ENOENT;
 	
-	ipc_callid_t callid;
-	if (!async_data_read_receive(&callid, NULL)) {
-		ipc_answer_0(callid, EINVAL);
+	cap_handle_t chandle;
+	if (!async_data_read_receive(&chandle, NULL)) {
+		ipc_answer_0(chandle, EINVAL);
 		return EINVAL;
 	}
@@ -2836,13 +2874,13 @@
 	    dataptr);
 	if (msg == 0) {
-		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(chandle, EINVAL);
 		return EINVAL;
 	}
 	
-	int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
+	int retval = ipc_forward_fast(chandle, exch->phone, 0, 0, 0,
 	    IPC_FF_ROUTE_FROM_ME);
 	if (retval != EOK) {
 		async_forget(msg);
-		ipc_answer_0(callid, retval);
+		ipc_answer_0(chandle, retval);
 		return retval;
 	}
@@ -2880,14 +2918,14 @@
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid Storage for the hash of the IPC_M_DATA_WRITE.
- * @param size   Storage for the suggested size. May be NULL.
- *
- * @return True on success, false on failure.
- *
- */
-bool async_data_write_receive(ipc_callid_t *callid, size_t *size)
+ * @param chandle  Storage for the handle of the IPC_M_DATA_WRITE.
+ * @param size     Storage for the suggested size. May be NULL.
+ *
+ * @return  True on success, false on failure.
+ *
+ */
+bool async_data_write_receive(cap_handle_t *chandle, size_t *size)
 {
 	ipc_call_t data;
-	return async_data_write_receive_call(callid, &data, size);
+	return async_data_write_receive_call(chandle, &data, size);
 }
 
@@ -2900,18 +2938,18 @@
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid Storage for the hash of the IPC_M_DATA_WRITE.
- * @param data   Storage for the ipc call data.
- * @param size   Storage for the suggested size. May be NULL.
+ * @param chandle  Storage for the handle of the IPC_M_DATA_WRITE.
+ * @param data     Storage for the ipc call data.
+ * @param size     Storage for the suggested size. May be NULL.
  *
  * @return True on success, false on failure.
  *
  */
-bool async_data_write_receive_call(ipc_callid_t *callid, ipc_call_t *data,
+bool async_data_write_receive_call(cap_handle_t *chandle, ipc_call_t *data,
     size_t *size)
 {
-	assert(callid);
+	assert(chandle);
 	assert(data);
 	
-	*callid = async_get_call(data);
+	*chandle = async_get_call(data);
 	
 	if (IPC_GET_IMETHOD(*data) != IPC_M_DATA_WRITE)
@@ -2930,14 +2968,14 @@
  * argument.
  *
- * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
- * @param dst    Final destination address for the IPC_M_DATA_WRITE call.
- * @param size   Final size for the IPC_M_DATA_WRITE call.
- *
- * @return Zero on success or a value from @ref errno.h on failure.
- *
- */
-int async_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
-{
-	return ipc_answer_2(callid, EOK, (sysarg_t) dst, (sysarg_t) size);
+ * @param chandle  Handle of the IPC_M_DATA_WRITE call to answer.
+ * @param dst      Final destination address for the IPC_M_DATA_WRITE call.
+ * @param size     Final size for the IPC_M_DATA_WRITE call.
+ *
+ * @return  Zero on success or a value from @ref errno.h on failure.
+ *
+ */
+int async_data_write_finalize(cap_handle_t chandle, void *dst, size_t size)
+{
+	return ipc_answer_2(chandle, EOK, (sysarg_t) dst, (sysarg_t) size);
 }
 
@@ -2969,23 +3007,23 @@
 	assert(data);
 	
-	ipc_callid_t callid;
+	cap_handle_t chandle;
 	size_t size;
-	if (!async_data_write_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);
+	if (!async_data_write_receive(&chandle, &size)) {
+		ipc_answer_0(chandle, EINVAL);
 		return EINVAL;
 	}
 	
 	if (size < min_size) {
-		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(chandle, EINVAL);
 		return EINVAL;
 	}
 	
 	if ((max_size > 0) && (size > max_size)) {
-		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(chandle, EINVAL);
 		return EINVAL;
 	}
 	
 	if ((granularity > 0) && ((size % granularity) != 0)) {
-		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(chandle, EINVAL);
 		return EINVAL;
 	}
@@ -2999,9 +3037,9 @@
 	
 	if (arg_data == NULL) {
-		ipc_answer_0(callid, ENOMEM);
+		ipc_answer_0(chandle, ENOMEM);
 		return ENOMEM;
 	}
 	
-	int rc = async_data_write_finalize(callid, arg_data, size);
+	int rc = async_data_write_finalize(chandle, arg_data, size);
 	if (rc != EOK) {
 		free(arg_data);
@@ -3028,7 +3066,7 @@
 void async_data_write_void(sysarg_t retval)
 {
-	ipc_callid_t callid;
-	async_data_write_receive(&callid, NULL);
-	ipc_answer_0(callid, retval);
+	cap_handle_t chandle;
+	async_data_write_receive(&chandle, NULL);
+	ipc_answer_0(chandle, retval);
 }
 
@@ -3043,7 +3081,7 @@
 		return ENOENT;
 	
-	ipc_callid_t callid;
-	if (!async_data_write_receive(&callid, NULL)) {
-		ipc_answer_0(callid, EINVAL);
+	cap_handle_t chandle;
+	if (!async_data_write_receive(&chandle, NULL)) {
+		ipc_answer_0(chandle, EINVAL);
 		return EINVAL;
 	}
@@ -3052,13 +3090,13 @@
 	    dataptr);
 	if (msg == 0) {
-		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(chandle, EINVAL);
 		return EINVAL;
 	}
 	
-	int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
+	int retval = ipc_forward_fast(chandle, exch->phone, 0, 0, 0,
 	    IPC_FF_ROUTE_FROM_ME);
 	if (retval != EOK) {
 		async_forget(msg);
-		ipc_answer_0(callid, retval);
+		ipc_answer_0(chandle, retval);
 		return retval;
 	}
@@ -3085,10 +3123,9 @@
 	/* Accept the phone */
 	ipc_call_t call;
-	ipc_callid_t callid = async_get_call(&call);
-	int phone = (int) IPC_GET_ARG5(call);
-	
-	if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) ||
-	    (phone < 0)) {
-		async_answer_0(callid, EINVAL);
+	cap_handle_t chandle = async_get_call(&call);
+	cap_handle_t phandle = (cap_handle_t) IPC_GET_ARG5(call);
+	
+	if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) || (phandle < 0)) {
+		async_answer_0(chandle, EINVAL);
 		return NULL;
 	}
@@ -3096,5 +3133,5 @@
 	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
 	if (sess == NULL) {
-		async_answer_0(callid, ENOMEM);
+		async_answer_0(chandle, ENOMEM);
 		return NULL;
 	}
@@ -3102,5 +3139,5 @@
 	sess->iface = 0;
 	sess->mgmt = mgmt;
-	sess->phone = phone;
+	sess->phone = phandle;
 	sess->arg1 = 0;
 	sess->arg2 = 0;
@@ -3115,5 +3152,5 @@
 	
 	/* Acknowledge the connected phone */
-	async_answer_0(callid, EOK);
+	async_answer_0(chandle, EOK);
 	
 	return sess;
@@ -3136,8 +3173,7 @@
 async_sess_t *async_callback_receive_start(exch_mgmt_t mgmt, ipc_call_t *call)
 {
-	int phone = (int) IPC_GET_ARG5(*call);
-	
-	if ((IPC_GET_IMETHOD(*call) != IPC_M_CONNECT_TO_ME) ||
-	    (phone < 0))
+	cap_handle_t phandle = (cap_handle_t) IPC_GET_ARG5(*call);
+	
+	if ((IPC_GET_IMETHOD(*call) != IPC_M_CONNECT_TO_ME) || (phandle < 0))
 		return NULL;
 	
@@ -3148,5 +3184,5 @@
 	sess->iface = 0;
 	sess->mgmt = mgmt;
-	sess->phone = phone;
+	sess->phone = phandle;
 	sess->arg1 = 0;
 	sess->arg2 = 0;
@@ -3170,11 +3206,11 @@
 }
 
-bool async_state_change_receive(ipc_callid_t *callid, sysarg_t *arg1,
+bool async_state_change_receive(cap_handle_t *chandle, sysarg_t *arg1,
     sysarg_t *arg2, sysarg_t *arg3)
 {
-	assert(callid);
+	assert(chandle);
 	
 	ipc_call_t call;
-	*callid = async_get_call(&call);
+	*chandle = async_get_call(&call);
 	
 	if (IPC_GET_IMETHOD(call) != IPC_M_STATE_CHANGE_AUTHORIZE)
@@ -3191,7 +3227,7 @@
 }
 
-int async_state_change_finalize(ipc_callid_t callid, async_exch_t *other_exch)
-{
-	return ipc_answer_1(callid, EOK, other_exch->phone);
+int async_state_change_finalize(cap_handle_t chandle, async_exch_t *other_exch)
+{
+	return ipc_answer_1(chandle, EOK, other_exch->phone);
 }
 
Index: uspace/lib/c/generic/bd.c
===================================================================
--- uspace/lib/c/generic/bd.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/bd.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -32,5 +32,5 @@
 /**
  * @file
- * @brief IP link client stub
+ * @brief Block device client interface
  */
 
Index: uspace/lib/c/generic/clipboard.c
===================================================================
--- uspace/lib/c/generic/clipboard.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/clipboard.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -45,5 +45,5 @@
 #include <ipc/services.h>
 #include <loc.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <str.h>
 
Index: uspace/lib/c/generic/device/hw_res.c
===================================================================
--- uspace/lib/c/generic/device/hw_res.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/device/hw_res.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,5 @@
 #include <errno.h>
 #include <async.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 int hw_res_get_resource_list(async_sess_t *sess,
@@ -140,9 +140,10 @@
  * @param channel DMA channel.
  *
- * @return Number of bytes remaining in the buffer if positive.
- * @return Error code if negative.
+ * @param[out] rem Number of bytes remaining in the buffer if positive.
+ *
+ * @return Error code.
  *
  */
-int hw_res_dma_channel_remain(async_sess_t *sess, unsigned channel)
+int hw_res_dma_channel_remain(async_sess_t *sess, unsigned channel, size_t *rem)
 {
 	async_exch_t *exch = async_exchange_begin(sess);
@@ -155,5 +156,5 @@
 	
 	if (ret == EOK)
-		return remain;
+		*rem = remain;
 	
 	return ret;
Index: uspace/lib/c/generic/device/hw_res_parsed.c
===================================================================
--- uspace/lib/c/generic/device/hw_res_parsed.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/device/hw_res_parsed.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -34,7 +34,7 @@
 
 #include <device/hw_res_parsed.h>
-#include <malloc.h>
 #include <assert.h>
 #include <errno.h>
+#include <stdlib.h>
 
 static void hw_res_parse_add_dma_channel(hw_res_list_parsed_t *out,
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/devman.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,5 +44,5 @@
 #include <async.h>
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 static FIBRIL_MUTEX_INITIALIZE(devman_driver_block_mutex);
Index: uspace/lib/c/generic/dirent.c
===================================================================
--- uspace/lib/c/generic/dirent.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/dirent.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -54,13 +54,14 @@
 	}
 	
-	int fd = vfs_lookup(dirname, WALK_DIRECTORY);
-	if (fd < 0) {
+	int fd;
+	int rc = vfs_lookup(dirname, WALK_DIRECTORY, &fd);
+	if (rc != EOK) {
 		free(dirp);
-		errno = fd;
+		errno = rc;
 		return NULL;
 	}
 	
-	int rc = vfs_open(fd, MODE_READ);
-	if (rc < 0) {
+	rc = vfs_open(fd, MODE_READ);
+	if (rc != EOK) {
 		free(dirp);
 		vfs_put(fd);
Index: uspace/lib/c/generic/elf/elf_load.c
===================================================================
--- uspace/lib/c/generic/elf/elf_load.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/elf/elf_load.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -53,5 +53,5 @@
  * @param file File handle 
  * @param info Place to store ELF program information
- * @return EOK on success or non-zero error code
+ * @return EE_OK on success or an EE_x error code
  */
 int elf_load(int file, elf_info_t *info)
Index: uspace/lib/c/generic/elf/elf_mod.c
===================================================================
--- uspace/lib/c/generic/elf/elf_mod.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/elf/elf_mod.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -69,5 +69,6 @@
 	"incompatible image",
 	"unsupported image type",
-	"irrecoverable error"
+	"irrecoverable error",
+	"file io error"
 };
 
@@ -90,5 +91,5 @@
  *                  extracted from the binary.
  *
- * @return EOK on success or negative error code.
+ * @return EE_OK on success or EE_xx error code.
  *
  */
@@ -97,8 +98,11 @@
 	elf_ld_t elf;
 
-	int ofile = vfs_clone(file, -1, true);
-	int rc = vfs_open(ofile, MODE_READ);
+	int ofile;
+	int rc = vfs_clone(file, -1, true, &ofile);
+	if (rc == EOK) {
+		rc = vfs_open(ofile, MODE_READ);
+	}
 	if (rc != EOK) {
-		return rc;
+		return EE_IO;
 	}
 
@@ -107,8 +111,8 @@
 	elf.flags = flags;
 
-	rc = elf_load_module(&elf, so_bias);
+	int ret = elf_load_module(&elf, so_bias);
 
 	vfs_put(ofile);
-	return rc;
+	return ret;
 }
 
@@ -116,8 +120,13 @@
     elf_finfo_t *info)
 {
-	int file = vfs_lookup(path, 0);
-	int rc = elf_load_file(file, so_bias, flags, info);
-	vfs_put(file);
-	return rc;
+	int file;
+	int rc = vfs_lookup(path, 0, &file);
+	if (rc == EOK) {
+		int ret = elf_load_file(file, so_bias, flags, info);
+		vfs_put(file);
+		return ret;
+	} else {
+		return EE_IO;
+	}
 }
 
@@ -137,10 +146,12 @@
 	elf_header_t *header = &header_buf;
 	aoff64_t pos = 0;
-	int i, rc;
-
-	rc = vfs_read(elf->fd, &pos, header, sizeof(elf_header_t));
-	if (rc != sizeof(elf_header_t)) {
+	size_t nr;
+	int i, ret;
+	int rc;
+
+	rc = vfs_read(elf->fd, &pos, header, sizeof(elf_header_t), &nr);
+	if (rc != EOK || nr != sizeof(elf_header_t)) {
 		DPRINTF("Read error.\n"); 
-		return EE_INVALID;
+		return EE_IO;
 	}
 
@@ -199,13 +210,13 @@
 		pos = header->e_phoff + i * sizeof(elf_segment_header_t);
 		rc = vfs_read(elf->fd, &pos, &segment_hdr,
-		    sizeof(elf_segment_header_t));
-		if (rc != sizeof(elf_segment_header_t)) {
+		    sizeof(elf_segment_header_t), &nr);
+		if (rc != EOK || nr != sizeof(elf_segment_header_t)) {
 			DPRINTF("Read error.\n");
-			return EE_INVALID;
+			return EE_IO;
 		}
 
-		rc = segment_header(elf, &segment_hdr);
-		if (rc != EE_OK)
-			return rc;
+		ret = segment_header(elf, &segment_hdr);
+		if (ret != EE_OK)
+			return ret;
 	}
 
@@ -218,13 +229,13 @@
 		pos = header->e_shoff + i * sizeof(elf_section_header_t);
 		rc = vfs_read(elf->fd, &pos, &section_hdr,
-		    sizeof(elf_section_header_t));
-		if (rc != sizeof(elf_section_header_t)) {
+		    sizeof(elf_section_header_t), &nr);
+		if (rc != EOK || nr != sizeof(elf_section_header_t)) {
 			DPRINTF("Read error.\n");
-			return EE_INVALID;
+			return EE_IO;
 		}
 
-		rc = section_header(elf, &section_hdr);
-		if (rc != EE_OK)
-			return rc;
+		ret = section_header(elf, &section_hdr);
+		if (ret != EE_OK)
+			return ret;
 	}
 
@@ -330,5 +341,6 @@
 	size_t mem_sz;
 	aoff64_t pos;
-	ssize_t rc;
+	int rc;
+	size_t nr;
 
 	bias = elf->bias;
@@ -388,8 +400,8 @@
 	 */
 	pos = entry->p_offset;
-	rc = vfs_read(elf->fd, &pos, seg_ptr, entry->p_filesz);
-	if (rc < 0) {
+	rc = vfs_read(elf->fd, &pos, seg_ptr, entry->p_filesz, &nr);
+	if (rc != EOK || nr != entry->p_filesz) {
 		DPRINTF("read error\n");
-		return EE_INVALID;
+		return EE_IO;
 	}
 
Index: uspace/lib/c/generic/errno.c
===================================================================
--- uspace/lib/c/generic/errno.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/errno.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,7 +36,7 @@
 #include <fibril.h>
 
-static fibril_local int fibril_errno;
+static fibril_local errno_t fibril_errno;
 
-int *__errno(void)
+errno_t *__errno(void)
 {
 	return &fibril_errno;
Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/fibril.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,5 +39,5 @@
 #include <stack.h>
 #include <tls.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <abi/mm/as.h>
 #include <as.h>
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/fibril_synch.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -629,40 +629,4 @@
 }
 
-/** Delay fibril execution for the specified number of microseconds
- *
- * @param usec Number of microseconds to sleep
- */
-void fibril_usleep(useconds_t usec)
-{
-	fibril_condvar_t cv;
-	fibril_mutex_t lock;
-
-	fibril_condvar_initialize(&cv);
-	fibril_mutex_initialize(&lock);
-	fibril_mutex_lock(&lock);
-	fibril_condvar_wait_timeout(&cv, &lock, usec);
-	fibril_mutex_unlock(&lock);
-}
-
-/** Delay fibril execution for the specified number of seconds
- *
- * @param sec Number of seconds to sleep
- */
-void fibril_sleep(unsigned int sec)
-{
-	/*
-	 * Sleep in 1000 second steps to support
-	 * full argument range
-	 */
-
-	while (sec > 0) {
-		unsigned int period = (sec > 1000) ? 1000 : sec;
-
-		fibril_usleep(period * 1000000);
-		sec -= period;
-	}
-}
-
-
 /** @}
  */
Index: uspace/lib/c/generic/gsort.c
===================================================================
--- uspace/lib/c/generic/gsort.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/gsort.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -43,5 +43,5 @@
 #include <inttypes.h>
 #include <mem.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 /** Immediate buffer size.
Index: uspace/lib/c/generic/inet/addr.c
===================================================================
--- uspace/lib/c/generic/inet/addr.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/inet/addr.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,5 +39,5 @@
 #include <stdio.h>
 #include <stddef.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <bitops.h>
 #include <inttypes.h>
Index: uspace/lib/c/generic/io/chardev.c
===================================================================
--- uspace/lib/c/generic/io/chardev.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/io/chardev.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Jan Vesely
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -27,34 +28,193 @@
  */
 
+/** @addtogroup libc
+ * @{
+ */
+/**
+ * @file
+ * @brief Character device client interface
+ */
+
 #include <errno.h>
 #include <mem.h>
 #include <io/chardev.h>
 #include <ipc/chardev.h>
-
-ssize_t chardev_read(async_exch_t *exch, void *data, size_t size)
-{
-	if (!exch)
-		return EBADMEM;
-	if (size > 4 * sizeof(sysarg_t))
-		return ELIMIT;
-
-	sysarg_t message[4] = { 0 };
-	const ssize_t ret = async_req_1_4(exch, CHARDEV_READ, size,
-	    &message[0], &message[1], &message[2], &message[3]);
-	if (ret > 0 && (size_t)ret <= size)
-		memcpy(data, message, size);
-	return ret;
-}
-
-ssize_t chardev_write(async_exch_t *exch, const void *data, size_t size)
-{
-	if (!exch)
-		return EBADMEM;
-	if (size > 3 * sizeof(sysarg_t))
-		return ELIMIT;
-
-	sysarg_t message[3] = { 0 };
-	memcpy(message, data, size);
-	return async_req_4_0(exch, CHARDEV_WRITE, size,
-	    message[0], message[1], message[2]);
-}
+#include <stddef.h>
+#include <stdlib.h>
+
+/** Open character device.
+ *
+ * @param sess Session with the character device
+ * @param rchardev Place to store pointer to the new character device structure
+ *
+ * @return EOK on success, ENOMEM if out of memory, EIO on I/O error
+ */
+int chardev_open(async_sess_t *sess, chardev_t **rchardev)
+{
+	chardev_t *chardev;
+
+	chardev = calloc(1, sizeof(chardev_t));
+	if (chardev == NULL)
+		return ENOMEM;
+
+	chardev->sess = sess;
+	*rchardev = chardev;
+
+	/* EIO might be used in a future implementation */
+	return EOK;
+}
+
+/** Close character device.
+ *
+ * Frees the character device structure. The underlying session is
+ * not affected.
+ *
+ * @param chardev Character device or @c NULL
+ */
+void chardev_close(chardev_t *chardev)
+{
+	free(chardev);
+}
+
+/** Read from character device.
+ *
+ * Read as much data as is available from character device up to @a size
+ * bytes into @a buf. On success EOK is returned and at least one byte
+ * is read (if no byte is available the function blocks). The number
+ * of bytes read is stored in @a *nread.
+ *
+ * On error a non-zero error code is returned and @a *nread is filled with
+ * the number of bytes that were successfully transferred.
+ *
+ * @param chardev Character device
+ * @param buf Destination buffer
+ * @param size Maximum number of bytes to read
+ * @param nread Place to store actual number of bytes read
+ *
+ * @return EOK on success or non-zero error code
+ */
+int chardev_read(chardev_t *chardev, void *buf, size_t size, size_t *nread)
+{
+	async_exch_t *exch = async_exchange_begin(chardev->sess);
+
+	if (size > DATA_XFER_LIMIT) {
+		/* This should not hurt anything. */
+		size = DATA_XFER_LIMIT;
+	}
+
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, CHARDEV_READ, &answer);
+	int rc = async_data_read_start(exch, buf, size);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		*nread = 0;
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	if (retval != EOK) {
+		*nread = 0;
+		return retval;
+	}
+
+	*nread = IPC_GET_ARG2(answer);
+	/* In case of partial success, ARG1 contains the error code */
+	return IPC_GET_ARG1(answer);
+
+}
+
+/** Write up to DATA_XFER_LIMIT bytes to character device.
+ *
+ * Write up to @a size or DATA_XFER_LIMIT bytes from @a data to character
+ * device. On success EOK is returned, bytes were written and @a *nwritten
+ * is set to min(@a size, DATA_XFER_LIMIT)
+ *
+ * On error a non-zero error code is returned and @a *nwritten is filled with
+ * the number of bytes that were successfully transferred.
+ *
+ * @param chardev Character device
+ * @param buf Destination buffer
+ * @param size Maximum number of bytes to read
+ * @param nwritten Place to store actual number of bytes written
+ *
+ * @return EOK on success or non-zero error code
+ */
+static int chardev_write_once(chardev_t *chardev, const void *data,
+    size_t size, size_t *nwritten)
+{
+	async_exch_t *exch = async_exchange_begin(chardev->sess);
+	ipc_call_t answer;
+	aid_t req;
+	int rc;
+
+	/* Break down large transfers */
+	if (size > DATA_XFER_LIMIT)
+		size = DATA_XFER_LIMIT;
+
+	req = async_send_0(exch, CHARDEV_WRITE, &answer);
+	rc = async_data_write_start(exch, data, size);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		*nwritten = 0;
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	if (retval != EOK) {
+		*nwritten = 0;
+		return retval;
+	}
+
+	*nwritten = IPC_GET_ARG2(answer);
+	/* In case of partial success, ARG1 contains the error code */
+	return IPC_GET_ARG1(answer);
+}
+
+/** Write to character device.
+ *
+ * Write @a size bytes from @a data to character device. On success EOK
+ * is returned, all bytes were written and @a *nwritten is set to @a size.
+ *
+ * On error a non-zero error code is returned and @a *nwritten is filled with
+ * the number of bytes that were successfully transferred.
+ *
+ * @param chardev Character device
+ * @param buf Destination buffer
+ * @param size Maximum number of bytes to read
+ * @param nwritten Place to store actual number of bytes written
+ *
+ * @return EOK on success or non-zero error code
+ */
+int chardev_write(chardev_t *chardev, const void *data, size_t size,
+    size_t *nwritten)
+{
+	size_t nw;
+	size_t p;
+	int rc;
+
+	p = 0;
+	while (p < size) {
+		rc = chardev_write_once(chardev, data + p, size - p, &nw);
+		/* nw is always valid, we can have partial success */
+		p += nw;
+
+		if (rc != EOK) {
+			/* We can return partial success */
+			*nwritten = p;
+			return rc;
+		}
+	}
+
+	*nwritten = p;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/chardev_srv.c
===================================================================
--- uspace/lib/c/generic/io/chardev_srv.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/io/chardev_srv.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -46,21 +46,41 @@
     ipc_call_t *call)
 {
-	size_t size = IPC_GET_ARG1(*call);
+	void *buf;
+	size_t size;
+	size_t nread;
 	int rc;
+	ipc_callid_t rcallid;
 
-	if (srv->srvs->ops->read == NULL) {
-		async_answer_0(callid, ENOTSUP);
+	if (!async_data_read_receive(&rcallid, &size)) {
+		async_answer_0(callid, EINVAL);
 		return;
 	}
 
-	if (size <= 4 * sizeof(sysarg_t)) {
-		sysarg_t message[4] = {};
+	buf = malloc(size);
+	if (buf == NULL) {
+		async_answer_0(rcallid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
 
-		rc = srv->srvs->ops->read(srv, (char *)message, size);
-		async_answer_4(callid, rc, message[0], message[1],
-		    message[2], message[3]);
-	} else {
-		async_answer_0(callid, ELIMIT);
+	if (srv->srvs->ops->read == NULL) {
+		async_answer_0(rcallid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
+		free(buf);
+		return;
 	}
+
+	rc = srv->srvs->ops->read(srv, buf, size, &nread);
+	if (rc != EOK && nread == 0) {
+		async_answer_0(rcallid, rc);
+		async_answer_0(callid, rc);
+		free(buf);
+		return;
+	}
+
+	async_data_read_finalize(rcallid, buf, nread);
+
+	free(buf);
+	async_answer_2(callid, EOK, rc, nread);
 }
 
@@ -68,6 +88,14 @@
     ipc_call_t *call)
 {
-	size_t size = IPC_GET_ARG1(*call);
+	void *data;
+	size_t size;
+	size_t nwr;
 	int rc;
+
+	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
 
 	if (srv->srvs->ops->write == NULL) {
@@ -76,16 +104,12 @@
 	}
 
-	if (size <= 3 * sizeof(sysarg_t)) {
-		const sysarg_t message[3] = {
-			IPC_GET_ARG2(*call),
-			IPC_GET_ARG3(*call),
-			IPC_GET_ARG4(*call)
-		};
+	rc = srv->srvs->ops->write(srv, data, size, &nwr);
+	free(data);
+	if (rc != EOK && nwr == 0) {
+		async_answer_0(callid, rc);
+		return;
+	}
 
-		rc = srv->srvs->ops->write(srv, (char *)message, size);
-		async_answer_0(callid, rc);
-	} else {
-		async_answer_0(callid, ELIMIT);
-	}
+	async_answer_2(callid, EOK, rc, nwr);
 }
 
@@ -145,5 +169,8 @@
 			break;
 		default:
-			async_answer_0(callid, EINVAL);
+			if (srv->srvs->ops->def_handler != NULL)
+				srv->srvs->ops->def_handler(srv, callid, &call);
+			else
+				async_answer_0(callid, ENOTSUP);
 		}
 	}
Index: uspace/lib/c/generic/io/chargrid.c
===================================================================
--- uspace/lib/c/generic/io/chargrid.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/io/chargrid.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -34,5 +34,5 @@
 
 #include <io/style.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <assert.h>
 #include <stdbool.h>
Index: uspace/lib/c/generic/io/con_srv.c
===================================================================
--- uspace/lib/c/generic/io/con_srv.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/io/con_srv.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -93,6 +93,7 @@
 	}
 
-	rc = srv->srvs->ops->read(srv, buf, size);
-	if (rc < 0) {
+	size_t nread;
+	rc = srv->srvs->ops->read(srv, buf, size, &nread);
+	if (rc != EOK) {
 		async_answer_0(rcallid, rc);
 		async_answer_0(callid, rc);
@@ -101,11 +102,8 @@
 	}
 
-	async_data_read_finalize(rcallid, buf, size);
+	async_data_read_finalize(rcallid, buf, nread);
 	free(buf);
 
-	if (rc >= 0)
-		async_answer_1(callid, EOK, rc);
-	else
-		async_answer_0(callid, rc);
+	async_answer_1(callid, EOK, nread);
 }
 
@@ -128,11 +126,9 @@
 	}
 
-	rc = srv->srvs->ops->write(srv, data, size);
+	size_t nwritten = 0;
+	rc = srv->srvs->ops->write(srv, data, size, &nwritten);
 	free(data);
 
-	if (rc >= 0)
-		async_answer_1(callid, EOK, rc);
-	else
-		async_answer_0(callid, rc);
+	async_answer_1(callid, rc, nwritten);
 }
 
Index: uspace/lib/c/generic/io/console.c
===================================================================
--- uspace/lib/c/generic/io/console.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/io/console.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,5 +38,5 @@
 #include <async.h>
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <vfs/vfs_sess.h>
 #include <io/console.h>
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/io/io.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,5 +38,5 @@
 #include <errno.h>
 #include <stdbool.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <async.h>
 #include <io/kio.h>
@@ -108,8 +108,8 @@
 	 * This will probably be removed later.
 	 */
-	 
 	int infd = inbox_get("stdin");
 	if (infd >= 0) {
-		int stdinfd = vfs_clone(infd, -1, false);
+		int stdinfd = -1;
+		(void) vfs_clone(infd, -1, false, &stdinfd);
 		assert(stdinfd == 0);
 		vfs_open(stdinfd, MODE_READ);
@@ -122,8 +122,9 @@
 	int outfd = inbox_get("stdout");
 	if (outfd >= 0) {
-		int stdoutfd = vfs_clone(outfd, -1, false);
+		int stdoutfd = -1;
+		(void) vfs_clone(outfd, -1, false, &stdoutfd);
 		assert(stdoutfd <= 1);
 		while (stdoutfd < 1)
-			stdoutfd = vfs_clone(outfd, -1, false);
+			(void) vfs_clone(outfd, -1, false, &stdoutfd);
 		vfs_open(stdoutfd, MODE_APPEND);
 		stdout = fdopen(stdoutfd, "a");
@@ -135,8 +136,9 @@
 	int errfd = inbox_get("stderr");
 	if (errfd >= 0) {
-		int stderrfd = vfs_clone(errfd, -1, false);
+		int stderrfd = -1;
+		(void) vfs_clone(errfd, -1, false, &stderrfd);
 		assert(stderrfd <= 2);
 		while (stderrfd < 2)
-			stderrfd = vfs_clone(errfd, -1, false);
+			(void) vfs_clone(errfd, -1, false, &stderrfd);
 		vfs_open(stderrfd, MODE_APPEND);
 		stderr = fdopen(stderrfd, "a");
@@ -294,12 +296,13 @@
 	if (create)
 		flags |= WALK_MAY_CREATE;
-	int file = vfs_lookup(path, flags);
-	if (file < 0) {
-		errno = file;
+	int file;
+	int rc = vfs_lookup(path, flags, &file);
+	if (rc != EOK) {
+		errno = rc;
 		free(stream);
 		return NULL;
 	}
 
-	int rc = vfs_open(file, mode);
+	rc = vfs_open(file, mode);
 	if (rc != EOK) {
 		errno = rc;
@@ -373,6 +376,6 @@
 	list_remove(&stream->link);
 	
-	if (rc != 0) {
-		/* errno was set by close() */
+	if (rc != EOK) {
+		errno = rc;
 		return EOF;
 	}
@@ -430,17 +433,19 @@
 static size_t _fread(void *buf, size_t size, size_t nmemb, FILE *stream)
 {
+	int rc;
+	size_t nread;
+
 	if (size == 0 || nmemb == 0)
 		return 0;
 
-	ssize_t rd = vfs_read(stream->fd, &stream->pos, buf, size * nmemb);
-	if (rd < 0) {
-		errno = rd;
+	rc = vfs_read(stream->fd, &stream->pos, buf, size * nmemb, &nread);
+	if (rc != EOK) {
+		errno = rc;
 		stream->error = true;
-		rd = 0;
-	} else if (rd == 0) {
+	} else if (nread == 0) {
 		stream->eof = true;
 	}
-	
-	return (rd / size);
+
+	return (nread / size);
 }
 
@@ -457,30 +462,29 @@
 static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
 {
+	int rc;
+	size_t nwritten;
+
 	if (size == 0 || nmemb == 0)
 		return 0;
 
-	ssize_t wr;
 	if (stream->kio) {
-		size_t nwritten;
-		wr = kio_write(buf, size * nmemb, &nwritten);
-		if (wr != EOK) {
+		rc = kio_write(buf, size * nmemb, &nwritten);
+		if (rc != EOK) {
 			stream->error = true;
-			wr = 0;
-		} else {
-			wr = nwritten;
+			nwritten = 0;
 		}
 	} else {
-		wr = vfs_write(stream->fd, &stream->pos, buf, size * nmemb);
-		if (wr < 0) {
-			errno = wr;
+		rc = vfs_write(stream->fd, &stream->pos, buf, size * nmemb,
+		    &nwritten);
+		if (rc != EOK) {
+			errno = rc;
 			stream->error = true;
-			wr = 0;
 		}
 	}
 
-	if (wr > 0)
+	if (nwritten > 0)
 		stream->need_sync = true;
-	
-	return (wr / size);
+
+	return (nwritten / size);
 }
 
@@ -491,10 +495,12 @@
 static void _ffillbuf(FILE *stream)
 {
-	ssize_t rc;
+	int rc;
+	size_t nread;
 
 	stream->buf_head = stream->buf_tail = stream->buf;
 
-	rc = vfs_read(stream->fd, &stream->pos, stream->buf, stream->buf_size);
-	if (rc < 0) {
+	rc = vfs_read(stream->fd, &stream->pos, stream->buf, stream->buf_size,
+	    &nread);
+	if (rc != EOK) {
 		errno = rc;
 		stream->error = true;
@@ -502,10 +508,10 @@
 	}
 
-	if (rc == 0) {
+	if (nread == 0) {
 		stream->eof = true;
 		return;
 	}
 
-	stream->buf_head += rc;
+	stream->buf_head += nread;
 	stream->buf_state = _bs_read;
 }
Index: uspace/lib/c/generic/io/klog.c
===================================================================
--- uspace/lib/c/generic/io/klog.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/io/klog.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -42,18 +42,14 @@
 #include <abi/log.h>
 
-size_t klog_write(log_level_t lvl, const void *buf, size_t size)
+int klog_write(log_level_t lvl, const void *buf, size_t size)
 {
-	ssize_t ret = (ssize_t) __SYSCALL4(SYS_KLOG, KLOG_WRITE, (sysarg_t) buf,
+	return (int) __SYSCALL4(SYS_KLOG, KLOG_WRITE, (sysarg_t) buf,
 	    size, lvl);
-	
-	if (ret >= 0)
-		return (size_t) ret;
-	
-	return 0;
 }
 
-int klog_read(void *data, size_t size)
+int klog_read(void *data, size_t size, size_t *nread)
 {
-	return (int) __SYSCALL4(SYS_KLOG, KLOG_READ, (uintptr_t) data, size, 0);
+	return (int) __SYSCALL5(SYS_KLOG, KLOG_READ, (uintptr_t) data,
+	    size, 0, (sysarg_t) nread);
 }
 
Index: uspace/lib/c/generic/io/serial.c
===================================================================
--- uspace/lib/c/generic/io/serial.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/lib/c/generic/io/serial.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <io/serial.h>
+#include <ipc/serial_ctl.h>
+#include <ipc/services.h>
+#include <stdlib.h>
+
+/** Open serial port device.
+ *
+ * @param sess Session with the serial port device
+ * @param rchardev Place to store pointer to the new serial port device structure
+ *
+ * @return EOK on success, ENOMEM if out of memory, EIO on I/O error
+ */
+int serial_open(async_sess_t *sess, serial_t **rserial)
+{
+	serial_t *serial;
+
+	serial = calloc(1, sizeof(serial_t));
+	if (serial == NULL)
+		return ENOMEM;
+
+	serial->sess = sess;
+	*rserial = serial;
+
+	return EOK;
+}
+
+/** Close serial port device.
+ *
+ * Frees the serial port device structure. The underlying session is
+ * not affected.
+ *
+ * @param serial Serial port device or @c NULL
+ */
+void serial_close(serial_t *serial)
+{
+	free(serial);
+}
+
+/** Set serial port communication properties. */
+int serial_set_comm_props(serial_t *serial, unsigned rate,
+    serial_parity_t parity, unsigned datab, unsigned stopb)
+{
+	async_exch_t *exch = async_exchange_begin(serial->sess);
+
+	int rc = async_req_4_0(exch, SERIAL_SET_COM_PROPS, rate, parity,
+	    datab, stopb);
+
+	async_exchange_end(exch);
+	return rc;
+}
+
+/** Get serial port communication properties. */
+int serial_get_comm_props(serial_t *serial, unsigned *rrate,
+    serial_parity_t *rparity, unsigned *rdatab, unsigned *rstopb)
+{
+	async_exch_t *exch = async_exchange_begin(serial->sess);
+	sysarg_t rate, parity, datab, stopb;
+
+	int rc = async_req_0_4(exch, SERIAL_GET_COM_PROPS, &rate, &parity,
+	    &datab, &stopb);
+
+	async_exchange_end(exch);
+	if (rc != EOK)
+		return rc;
+
+	*rrate = rate;
+	*rparity = parity;
+	*rdatab = datab;
+	*rstopb = stopb;
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/ipc.c
===================================================================
--- uspace/lib/c/generic/ipc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/ipc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2017 Jakub Jermar
  * All rights reserved.
  *
@@ -42,5 +43,5 @@
 #include <ipc/ipc.h>
 #include <libc.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <errno.h>
 #include <adt/list.h>
@@ -50,49 +51,14 @@
 
 /**
- * Structures of this type are used for keeping track
- * of sent asynchronous calls and queing unsent calls.
- */
-typedef struct {
-	link_t list;
-	
+ * Structures of this type are used for keeping track of sent asynchronous calls.
+ */
+typedef struct async_call {
 	ipc_async_callback_t callback;
 	void *private;
 	
-	union {
-		ipc_callid_t callid;
-		struct {
-			ipc_call_t data;
-			int phoneid;
-		} msg;
-	} u;
-	
-	/** Fibril waiting for sending this call. */
-	fid_t fid;
+	struct {
+		ipc_call_t data;
+	} msg;
 } async_call_t;
-
-LIST_INITIALIZE(dispatched_calls);
-
-/** List of asynchronous calls that were not accepted by kernel.
- *
- * Protected by async_futex, because if the call is not accepted
- * by the kernel, the async framework is used automatically.
- *
- */
-LIST_INITIALIZE(queued_calls);
-
-static futex_t ipc_futex = FUTEX_INITIALIZER;
-
-/** Send asynchronous message via syscall.
- *
- * @param phoneid Phone handle for the call.
- * @param data    Call data with the request.
- *
- * @return Hash of the call or an error code.
- *
- */
-static ipc_callid_t ipc_call_async_internal(int phoneid, ipc_call_t *data)
-{
-	return __SYSCALL2(SYS_IPC_CALL_ASYNC_SLOW, phoneid, (sysarg_t) data);
-}
 
 /** Prologue for ipc_call_async_*() functions.
@@ -124,20 +90,15 @@
 /** Epilogue for ipc_call_async_*() functions.
  *
- * @param callid      Value returned by the SYS_IPC_CALL_ASYNC_* syscall.
- * @param phoneid     Phone handle through which the call was made.
- * @param call        Structure returned by ipc_prepare_async().
- */
-static inline void ipc_finish_async(ipc_callid_t callid, int phoneid,
-    async_call_t *call)
+ * @param rc       Value returned by the SYS_IPC_CALL_ASYNC_* syscall.
+ * @param call     Structure returned by ipc_prepare_async().
+ */
+static inline void ipc_finish_async(int rc, async_call_t *call)
 {
 	if (!call) {
 		/* Nothing to do regardless if failed or not */
-		futex_unlock(&ipc_futex);
 		return;
 	}
 	
-	if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
-		futex_unlock(&ipc_futex);
-		
+	if (rc != EOK) {
 		/* Call asynchronous handler with error code */
 		if (call->callback)
@@ -147,15 +108,9 @@
 		return;
 	}
-	
-	call->u.callid = callid;
-	
-	/* Add call to the list of dispatched calls */
-	list_append(&call->list, &dispatched_calls);
-	futex_unlock(&ipc_futex);
 }
 
 /** Fast asynchronous call.
  *
- * This function can only handle four arguments of payload. It is, however,
+ * This function can only handle three arguments of payload. It is, however,
  * faster than the more generic ipc_call_async_slow().
  *
@@ -166,35 +121,23 @@
  * error code. If the call cannot be temporarily made, it is queued.
  *
- * @param phoneid     Phone handle for the call.
- * @param imethod     Requested interface and method.
- * @param arg1        Service-defined payload argument.
- * @param arg2        Service-defined payload argument.
- * @param arg3        Service-defined payload argument.
- * @param arg4        Service-defined payload argument.
- * @param private     Argument to be passed to the answer/error callback.
- * @param callback    Answer or error callback.
- */
-void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private,
-    ipc_async_callback_t callback)
-{
-	async_call_t *call = NULL;
-	
-	if (callback) {
-		call = ipc_prepare_async(private, callback);
-		if (!call)
-			return;
-	}
-	
-	/*
-	 * We need to make sure that we get callid
-	 * before another thread accesses the queue again.
-	 */
-	
-	futex_lock(&ipc_futex);
-	ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid,
-	    imethod, arg1, arg2, arg3, arg4);
-	
-	ipc_finish_async(callid, phoneid, call);
+ * @param phandle   Phone handle for the call.
+ * @param imethod   Requested interface and method.
+ * @param arg1      Service-defined payload argument.
+ * @param arg2      Service-defined payload argument.
+ * @param arg3      Service-defined payload argument.
+ * @param private   Argument to be passed to the answer/error callback.
+ * @param callback  Answer or error callback.
+ */
+void ipc_call_async_fast(cap_handle_t phandle, sysarg_t imethod, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, void *private, ipc_async_callback_t callback)
+{
+	async_call_t *call = ipc_prepare_async(private, callback);
+	if (!call)
+		return;
+	
+	int rc = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phandle, imethod, arg1,
+	    arg2, arg3, (sysarg_t) call);
+	
+	ipc_finish_async(rc, call);
 }
 
@@ -207,15 +150,15 @@
  * error code. If the call cannot be temporarily made, it is queued.
  *
- * @param phoneid     Phone handle for the call.
- * @param imethod     Requested interface and method.
- * @param arg1        Service-defined payload argument.
- * @param arg2        Service-defined payload argument.
- * @param arg3        Service-defined payload argument.
- * @param arg4        Service-defined payload argument.
- * @param arg5        Service-defined payload argument.
- * @param private     Argument to be passed to the answer/error callback.
- * @param callback    Answer or error callback.
- */
-void ipc_call_async_slow(int phoneid, sysarg_t imethod, sysarg_t arg1,
+ * @param phandle   Phone handle for the call.
+ * @param imethod   Requested interface and method.
+ * @param arg1      Service-defined payload argument.
+ * @param arg2      Service-defined payload argument.
+ * @param arg3      Service-defined payload argument.
+ * @param arg4      Service-defined payload argument.
+ * @param arg5      Service-defined payload argument.
+ * @param private   Argument to be passed to the answer/error callback.
+ * @param callback  Answer or error callback.
+ */
+void ipc_call_async_slow(int phandle, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, void *private,
     ipc_async_callback_t callback)
@@ -225,21 +168,15 @@
 		return;
 	
-	IPC_SET_IMETHOD(call->u.msg.data, imethod);
-	IPC_SET_ARG1(call->u.msg.data, arg1);
-	IPC_SET_ARG2(call->u.msg.data, arg2);
-	IPC_SET_ARG3(call->u.msg.data, arg3);
-	IPC_SET_ARG4(call->u.msg.data, arg4);
-	IPC_SET_ARG5(call->u.msg.data, arg5);
-	
-	/*
-	 * We need to make sure that we get callid
-	 * before another threadaccesses the queue again.
-	 */
-	
-	futex_lock(&ipc_futex);
-	ipc_callid_t callid =
-	    ipc_call_async_internal(phoneid, &call->u.msg.data);
-	
-	ipc_finish_async(callid, phoneid, call);
+	IPC_SET_IMETHOD(call->msg.data, imethod);
+	IPC_SET_ARG1(call->msg.data, arg1);
+	IPC_SET_ARG2(call->msg.data, arg2);
+	IPC_SET_ARG3(call->msg.data, arg3);
+	IPC_SET_ARG4(call->msg.data, arg4);
+	IPC_SET_ARG5(call->msg.data, arg5);
+	
+	int rc = __SYSCALL3(SYS_IPC_CALL_ASYNC_SLOW, phandle,
+	    (sysarg_t) &call->msg.data, (sysarg_t) call);
+	
+	ipc_finish_async(rc, call);
 }
 
@@ -249,10 +186,10 @@
  * registers. If you need to return more, use the ipc_answer_slow() instead.
  *
- * @param callid Hash of the call being answered.
- * @param retval Return value.
- * @param arg1   First return argument.
- * @param arg2   Second return argument.
- * @param arg3   Third return argument.
- * @param arg4   Fourth return argument.
+ * @param chandle  Handle of the call being answered.
+ * @param retval   Return value.
+ * @param arg1     First return argument.
+ * @param arg2     Second return argument.
+ * @param arg3     Third return argument.
+ * @param arg4     Fourth return argument.
  *
  * @return Zero on success.
@@ -260,20 +197,20 @@
  *
  */
-sysarg_t ipc_answer_fast(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
+sysarg_t ipc_answer_fast(cap_handle_t chandle, sysarg_t retval, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
 {
-	return __SYSCALL6(SYS_IPC_ANSWER_FAST, callid, retval, arg1, arg2, arg3,
-	    arg4);
+	return __SYSCALL6(SYS_IPC_ANSWER_FAST, chandle, retval, arg1, arg2,
+	    arg3, arg4);
 }
 
 /** Answer received call (entire payload).
  *
- * @param callid Hash of the call being answered.
- * @param retval Return value.
- * @param arg1   First return argument.
- * @param arg2   Second return argument.
- * @param arg3   Third return argument.
- * @param arg4   Fourth return argument.
- * @param arg5   Fifth return argument.
+ * @param chandle  Handle of the call being answered.
+ * @param retval   Return value.
+ * @param arg1     First return argument.
+ * @param arg2     Second return argument.
+ * @param arg3     Third return argument.
+ * @param arg4     Fourth return argument.
+ * @param arg5     Fifth return argument.
  *
  * @return Zero on success.
@@ -281,5 +218,5 @@
  *
  */
-sysarg_t ipc_answer_slow(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
+sysarg_t ipc_answer_slow(cap_handle_t chandle, sysarg_t retval, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
 {
@@ -293,208 +230,134 @@
 	IPC_SET_ARG5(data, arg5);
 	
-	return __SYSCALL2(SYS_IPC_ANSWER_SLOW, callid, (sysarg_t) &data);
-}
-
-/** Try to dispatch queued calls from the async queue.
- *
- */
-static void dispatch_queued_calls(void)
-{
-	/** @todo
-	 * Integrate intelligently ipc_futex so that it is locked during
-	 * ipc_call_async_*() until it is added to dispatched_calls.
-	 */
-	
-	futex_down(&async_futex);
-	
-	while (!list_empty(&queued_calls)) {
-		async_call_t *call =
-		    list_get_instance(list_first(&queued_calls), async_call_t, list);
-		ipc_callid_t callid =
-		    ipc_call_async_internal(call->u.msg.phoneid, &call->u.msg.data);
-		
-		list_remove(&call->list);
-		
-		futex_up(&async_futex);
-		
-		assert(call->fid);
-		fibril_add_ready(call->fid);
-		
-		if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
-			if (call->callback)
-				call->callback(call->private, ENOENT, NULL);
-			
-			free(call);
-		} else {
-			call->u.callid = callid;
-			
-			futex_lock(&ipc_futex);
-			list_append(&call->list, &dispatched_calls);
-			futex_unlock(&ipc_futex);
-		}
-		
-		futex_down(&async_futex);
+	return __SYSCALL2(SYS_IPC_ANSWER_SLOW, chandle, (sysarg_t) &data);
+}
+
+/** Handle received answer.
+ *
+ * @param data  Call data of the answer.
+ */
+static void handle_answer(ipc_call_t *data)
+{
+	async_call_t *call = data->label;
+
+	if (!call)
+		return;
+
+	if (call->callback)
+		call->callback(call->private, IPC_GET_RETVAL(*data), data);
+	free(call);
+}
+
+/** Wait for first IPC call to come.
+ *
+ * @param call   Incoming call storage.
+ * @param usec   Timeout in microseconds
+ * @param flags  Flags passed to SYS_IPC_WAIT (blocking, nonblocking).
+ * @param[out] out_handle  Call handle.
+ *
+ * @return  Error code.
+ */
+int ipc_wait_cycle(ipc_call_t *call, sysarg_t usec, unsigned int flags)
+{
+	int rc = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
+	
+	/* Handle received answers */
+	if ((rc == EOK) && (call->cap_handle == CAP_NIL) &&
+	    (call->flags & IPC_CALL_ANSWERED)) {
+		handle_answer(call);
 	}
 	
-	futex_up(&async_futex);
-}
-
-/** Handle received answer.
- *
- * Find the hash of the answer and call the answer callback.
- *
- * The answer has the same hash as the request OR'ed with
- * the IPC_CALLID_ANSWERED bit.
- *
- * @todo Use hash table.
- *
- * @param callid Hash of the received answer.
- * @param data   Call data of the answer.
- *
- */
-static void handle_answer(ipc_callid_t callid, ipc_call_t *data)
-{
-	callid &= ~IPC_CALLID_ANSWERED;
-	
-	futex_lock(&ipc_futex);
-	
-	link_t *item;
-	for (item = dispatched_calls.head.next; item != &dispatched_calls.head;
-	    item = item->next) {
-		async_call_t *call =
-		    list_get_instance(item, async_call_t, list);
-		
-		if (call->u.callid == callid) {
-			list_remove(&call->list);
-			
-			futex_unlock(&ipc_futex);
-			
-			if (call->callback)
-				call->callback(call->private,
-				    IPC_GET_RETVAL(*data), data);
-			
-			free(call);
-			return;
-		}
-	}
-	
-	futex_unlock(&ipc_futex);
+	return rc;
+}
+
+/** Interrupt one thread of this task from waiting for IPC.
+ *
+ */
+void ipc_poke(void)
+{
+	__SYSCALL0(SYS_IPC_POKE);
 }
 
 /** Wait for first IPC call to come.
+ *
+ * Only requests are returned, answers are processed internally.
  *
  * @param call  Incoming call storage.
  * @param usec  Timeout in microseconds
- * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking).
- *
- * @return Hash of the call. Note that certain bits have special
- *         meaning: IPC_CALLID_ANSWERED is set in an answer
- *         and IPC_CALLID_NOTIFICATION is used for notifications.
- *
- */
-ipc_callid_t ipc_wait_cycle(ipc_call_t *call, sysarg_t usec,
-    unsigned int flags)
-{
-	ipc_callid_t callid =
-	    __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
-	
-	/* Handle received answers */
-	if (callid & IPC_CALLID_ANSWERED) {
-		handle_answer(callid, call);
-		dispatch_queued_calls();
-	}
-	
-	return callid;
-}
-
-/** Interrupt one thread of this task from waiting for IPC.
- *
- */
-void ipc_poke(void)
-{
-	__SYSCALL0(SYS_IPC_POKE);
-}
-
-/** Wait for first IPC call to come.
+ *
+ * @return  Error code.
+ *
+ */
+int ipc_wait_for_call_timeout(ipc_call_t *call, sysarg_t usec)
+{
+	int rc;
+	
+	do {
+		rc = ipc_wait_cycle(call, usec, SYNCH_FLAGS_NONE);
+	} while ((rc == EOK) && (call->cap_handle == CAP_NIL) && (call->flags & IPC_CALL_ANSWERED));
+	
+	return rc;
+}
+
+/** Check if there is an IPC call waiting to be picked up.
  *
  * Only requests are returned, answers are processed internally.
  *
- * @param call Incoming call storage.
- * @param usec Timeout in microseconds
- *
- * @return Hash of the call.
- *
- */
-ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, sysarg_t usec)
-{
-	ipc_callid_t callid;
+ * @param call  Incoming call storage.
+ *
+ * @return  Error code.
+ *
+ */
+int ipc_trywait_for_call(ipc_call_t *call)
+{
+	int rc;
 	
 	do {
-		callid = ipc_wait_cycle(call, usec, SYNCH_FLAGS_NONE);
-	} while (callid & IPC_CALLID_ANSWERED);
-	
-	return callid;
-}
-
-/** Check if there is an IPC call waiting to be picked up.
- *
- * Only requests are returned, answers are processed internally.
- *
- * @param call Incoming call storage.
- *
- * @return Hash of the call.
- *
- */
-ipc_callid_t ipc_trywait_for_call(ipc_call_t *call)
-{
-	ipc_callid_t callid;
-	
-	do {
-		callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT,
+		rc = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT,
 		    SYNCH_FLAGS_NON_BLOCKING);
-	} while (callid & IPC_CALLID_ANSWERED);
-	
-	return callid;
+	} while ((rc == EOK) && (call->cap_handle == CAP_NIL) && (call->flags & IPC_CALL_ANSWERED));
+	
+	return rc;
 }
 
 /** Hang up a phone.
  *
- * @param phoneid Handle of the phone to be hung up.
- *
- * @return Zero on success or a negative error code.
- *
- */
-int ipc_hangup(int phoneid)
-{
-	return __SYSCALL1(SYS_IPC_HANGUP, phoneid);
+ * @param phandle  Handle of the phone to be hung up.
+ *
+ * @return  Zero on success or a negative error code.
+ *
+ */
+int ipc_hangup(cap_handle_t phandle)
+{
+	return __SYSCALL1(SYS_IPC_HANGUP, phandle);
 }
 
 /** Forward a received call to another destination.
  *
- * For non-system methods, the old method, arg1 and arg2 are rewritten
- * by the new values. For system methods, the new method, arg1 and arg2
- * are written to the old arg1, arg2 and arg3, respectivelly. Calls with
- * immutable methods are forwarded verbatim.
- *
- * @param callid  Hash of the call to forward.
- * @param phoneid Phone handle to use for forwarding.
- * @param imethod New interface and method for the forwarded call.
- * @param arg1    New value of the first argument for the forwarded call.
- * @param arg2    New value of the second argument for the forwarded call.
- * @param mode    Flags specifying mode of the forward operation.
- *
- * @return Zero on success or an error code.
- *
- */
-int ipc_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
-    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
-{
-	return __SYSCALL6(SYS_IPC_FORWARD_FAST, callid, phoneid, imethod, arg1,
+ * For non-system methods, the old method, arg1 and arg2 are rewritten by the
+ * new values. For system methods, the new method, arg1 and arg2 are written to
+ * the old arg1, arg2 and arg3, respectivelly. Calls with immutable methods are
+ * forwarded verbatim.
+ *
+ * @param chandle  Handle of the call to forward.
+ * @param phandle  Phone handle to use for forwarding.
+ * @param imethod  New interface and method for the forwarded call.
+ * @param arg1     New value of the first argument for the forwarded call.
+ * @param arg2     New value of the second argument for the forwarded call.
+ * @param mode     Flags specifying mode of the forward operation.
+ *
+ * @return  Zero on success or an error code.
+ *
+ */
+int ipc_forward_fast(cap_handle_t chandle, cap_handle_t phandle,
+    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
+{
+	return __SYSCALL6(SYS_IPC_FORWARD_FAST, chandle, phandle, imethod, arg1,
 	    arg2, mode);
 }
 
-int ipc_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
-    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
-    unsigned int mode)
+int ipc_forward_slow(cap_handle_t chandle, cap_handle_t phandle,
+    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
+    sysarg_t arg4, sysarg_t arg5, unsigned int mode)
 {
 	ipc_call_t data;
@@ -507,6 +370,6 @@
 	IPC_SET_ARG5(data, arg5);
 	
-	return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data,
-	    mode);
+	return __SYSCALL4(SYS_IPC_FORWARD_SLOW, chandle, phandle,
+	    (sysarg_t) &data, mode);
 }
 
@@ -514,14 +377,7 @@
  *
  */
-int ipc_connect_kbox(task_id_t id)
-{
-#ifdef __32_BITS__
-	sysarg64_t arg = (sysarg64_t) id;
-	return __SYSCALL1(SYS_IPC_CONNECT_KBOX, (sysarg_t) &arg);
-#endif
-	
-#ifdef __64_BITS__
-	return __SYSCALL1(SYS_IPC_CONNECT_KBOX, (sysarg_t) id);
-#endif
+int ipc_connect_kbox(task_id_t id, cap_handle_t *phone)
+{
+	return __SYSCALL2(SYS_IPC_CONNECT_KBOX, (sysarg_t) &id, (sysarg_t) phone);
 }
 
Index: uspace/lib/c/generic/irc.c
===================================================================
--- uspace/lib/c/generic/irc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/irc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -34,6 +34,6 @@
 
 #include <assert.h>
+#include <async.h>
 #include <errno.h>
-#include <fibril_synch.h>
 #include <ipc/irc.h>
 #include <ipc/services.h>
@@ -72,5 +72,5 @@
 
 		// XXX This is just a temporary hack
-		fibril_usleep(500 * 1000);
+		async_usleep(500 * 1000);
 	}
 
Index: uspace/lib/c/generic/irq.c
===================================================================
--- uspace/lib/c/generic/irq.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/irq.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -58,14 +58,17 @@
  * @param ucode  Top-half pseudocode handler.
  *
- * @return IRQ capability handle returned by the kernel.
+ * @param[out] out_handle  IRQ capability handle returned by the kernel.
+ *
  * @return Error code returned by the kernel.
  *
  */
-int ipc_irq_subscribe(int inr, sysarg_t method, const irq_code_t *ucode)
+int ipc_irq_subscribe(int inr, sysarg_t method, const irq_code_t *ucode,
+    cap_handle_t *out_handle)
 {
 	if (ucode == NULL)
 		ucode = &default_ucode;
 	
-	return __SYSCALL3(SYS_IPC_IRQ_SUBSCRIBE, inr, method, (sysarg_t) ucode);
+	return __SYSCALL4(SYS_IPC_IRQ_SUBSCRIBE, inr, method, (sysarg_t) ucode,
+	    (sysarg_t) out_handle);
 }
 
@@ -77,5 +80,5 @@
  *
  */
-int ipc_irq_unsubscribe(int cap)
+int ipc_irq_unsubscribe(cap_handle_t cap)
 {
 	return __SYSCALL1(SYS_IPC_IRQ_UNSUBSCRIBE, cap);
Index: uspace/lib/c/generic/loader.c
===================================================================
--- uspace/lib/c/generic/loader.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/loader.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -52,7 +52,5 @@
  * @param name Symbolic name to set on the newly created task.
  *
- * @return Pointer to the loader connection structure (should be
- *         deallocated using free() after use).
- *
+ * @return Error code.
  */
 int loader_spawn(const char *name)
@@ -198,10 +196,11 @@
 	}
 	
-	int fd = vfs_lookup(path, 0);
-	if (fd < 0) {
-		return fd;
-	}
-	
-	int rc = loader_set_program(ldr, name, fd);
+	int fd;
+	int rc = vfs_lookup(path, 0, &fd);
+	if (rc != EOK) {
+		return rc;
+	}
+	
+	rc = loader_set_program(ldr, name, fd);
 	vfs_put(fd);
 	return rc;
Index: uspace/lib/c/generic/loc.c
===================================================================
--- uspace/lib/c/generic/loc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/loc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,5 @@
 #include <async.h>
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <stdbool.h>
 
Index: uspace/lib/c/generic/pio_trace.c
===================================================================
--- uspace/lib/c/generic/pio_trace.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/pio_trace.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,5 +35,5 @@
 #include <assert.h>
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <adt/list.h>
 #include <fibril_synch.h>
Index: uspace/lib/c/generic/stats.c
===================================================================
--- uspace/lib/c/generic/stats.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/stats.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,5 +39,5 @@
 #include <stdio.h>
 #include <inttypes.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 #define SYSINFO_STATS_MAX_PATH  64
Index: uspace/lib/c/generic/str.c
===================================================================
--- uspace/lib/c/generic/str.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/str.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,10 +37,9 @@
 
 #include <str.h>
+#include <stddef.h>
+#include <stdint.h>
 #include <stdlib.h>
-#include <stddef.h>
 #include <assert.h>
-#include <stdint.h>
 #include <ctype.h>
-#include <malloc.h>
 #include <errno.h>
 #include <align.h>
Index: uspace/lib/c/generic/str_error.c
===================================================================
--- uspace/lib/c/generic/str_error.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/str_error.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,9 +41,32 @@
 #define NOERR_LEN  64
 
+// TODO: this file should be generated from errno declarations
+
+static const char* err_name[] = {
+	"EOK",
+	"ENOENT",
+	"ENOMEM",
+	"ELIMIT",
+	"EREFUSED",
+	"EFORWARD",
+	"EPERM",
+	"EHANGUP",
+	"EPARTY",
+	"EEXIST",
+	"EBADMEM",
+	"ENOTSUP",
+	"EADDRNOTAVAIL",
+	"ETIMEOUT",
+	"EINVAL",
+	"EBUSY",
+	"EOVERFLOW",
+	"EINTR"
+};
+
 static const char* err_desc[] = {
 	"No error",
 	"No such entry",
 	"Not enough memory",
-	"Limit exceeded", 
+	"Limit exceeded",
 	"Connection refused",
 	"Forwarding error",
@@ -64,5 +87,31 @@
 static fibril_local char noerr[NOERR_LEN];
 
-const char *str_error(const int e)
+const char *str_error_name(errno_t e)
+{
+	if ((e <= 0) && (e >= MIN_ERRNO))
+		return err_name[-e];
+
+	/* Ad hoc descriptions of error codes interesting for USB. */
+	// FIXME: integrate these as first-class error values
+	switch (e) {
+		case ENOFS:
+			return "ENOFS";
+		case EBADCHECKSUM:
+			return "EBADCHECKSUM";
+		case ESTALL:
+			return "ESTALL";
+		case EAGAIN:
+			return "EAGAIN";
+		case EEMPTY:
+			return "EEMPTY";
+		default:
+			break;
+	}
+
+	snprintf(noerr, NOERR_LEN, "(%d)", (int)e);
+	return noerr;
+}
+
+const char *str_error(errno_t e)
 {
 	if ((e <= 0) && (e >= MIN_ERRNO))
@@ -86,5 +135,5 @@
 	}
 
-	snprintf(noerr, NOERR_LEN, "Unkown error code %d", e);
+	snprintf(noerr, NOERR_LEN, "Unknown error code (%d)", (int)e);
 	return noerr;
 }
Index: uspace/lib/c/generic/sysinfo.c
===================================================================
--- uspace/lib/c/generic/sysinfo.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/sysinfo.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,5 +37,5 @@
 #include <str.h>
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <stdbool.h>
 #include <stddef.h>
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/task.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -45,5 +45,5 @@
 #include <errno.h>
 #include <ns.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <libc.h>
 #include "private/ns.h"
Index: uspace/lib/c/generic/time.c
===================================================================
--- uspace/lib/c/generic/time.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/time.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -51,5 +51,4 @@
 #include <loc.h>
 #include <device/clock_dev.h>
-#include <malloc.h>
 #include <thread.h>
 
Index: uspace/lib/c/generic/tls.c
===================================================================
--- uspace/lib/c/generic/tls.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/tls.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,5 +39,5 @@
 #include <align.h>
 #include <tls.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <str.h>
 
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -86,5 +86,5 @@
  * and consume system resources.
  *
- * Functions that return int return a negative error code on error and do not
+ * Functions that return int return an error code on error and do not
  * set errno. Depending on function, success is signalled by returning either
  * EOK or a non-negative file handle.
@@ -104,11 +104,12 @@
  * 	aoff64_t pos = 42;
  * 	char buf[512];
- * 	ssize_t size = vfs_read(file, &pos, buf, sizeof(buf));
- * 	if (size < 0) {
+ *	size_t nread;
+ * 	rc = vfs_read(file, &pos, buf, sizeof(buf), &nread);
+ * 	if (rc != EOK) {
  * 		vfs_put(file);
- * 		return size;
+ * 		return rc;
  * 	}
  *
- *	// buf is now filled with data from file
+ *	// buf is now filled with nread bytes from file
  *
  *	vfs_put(file);
@@ -127,5 +128,5 @@
 static int root_fd = -1;
 
-static int get_parent_and_child(const char *path, char **child)
+static int get_parent_and_child(const char *path, int *parent, char **child)
 {
 	size_t size;
@@ -135,14 +136,18 @@
 
 	char *slash = str_rchr(apath, L'/');
-	int parent;
 	if (slash == apath) {
-		parent = vfs_root();
+		*parent = vfs_root();
+		if (*parent < 0) {
+			free(apath);
+			return EBADF;
+		}
 		*child = apath;
+		return EOK;
 	} else {
 		*slash = '\0';
-		parent = vfs_lookup(apath, WALK_DIRECTORY);
-		if (parent < 0) {
+		int rc = vfs_lookup(apath, WALK_DIRECTORY, parent);
+		if (rc != EOK) {
 			free(apath);
-			return parent;
+			return rc;
 		}
 		*slash = '/';
@@ -150,10 +155,11 @@
 		free(apath);
 		if (!*child) {
-			vfs_put(parent);
+			vfs_put(*parent);
 			return ENOMEM;
 		}
-	}
-
-	return parent;
+
+		return rc;
+	}
+
 }
 
@@ -232,10 +238,17 @@
  * @return              New file handle on success or a negative error code
  */
-int vfs_clone(int file_from, int file_to, bool high)
-{
+int vfs_clone(int file_from, int file_to, bool high, int *handle)
+{
+	assert(handle != NULL);
+
 	async_exch_t *vfs_exch = vfs_exchange_begin();
-	int rc = async_req_3_0(vfs_exch, VFS_IN_CLONE, (sysarg_t) file_from,
-	    (sysarg_t) file_to, (sysarg_t) high);
+	sysarg_t ret;
+	int rc = async_req_3_1(vfs_exch, VFS_IN_CLONE, (sysarg_t) file_from,
+	    (sysarg_t) file_to, (sysarg_t) high, &ret);
 	vfs_exchange_end(vfs_exch);
+
+	if (rc == EOK) {
+		*handle = ret;
+	}
 	return rc;
 }
@@ -276,8 +289,9 @@
 		return ENOMEM;
 	
-	int fd = vfs_lookup(abs, WALK_DIRECTORY);
-	if (fd < 0) {
+	int fd;
+	int rc = vfs_lookup(abs, WALK_DIRECTORY, &fd);
+	if (rc != EOK) {
 		free(abs);
-		return fd;
+		return rc;
 	}
 	
@@ -490,8 +504,8 @@
 {
 	int flags = (kind == KIND_DIRECTORY) ? WALK_DIRECTORY : WALK_REGULAR;
-	int file = vfs_walk(parent, child, WALK_MUST_CREATE | flags);
-
-	if (file < 0)
-		return file;
+	int file = -1;
+	int rc = vfs_walk(parent, child, WALK_MUST_CREATE | flags, &file);
+	if (rc != EOK)
+		return rc;
 
 	if (linkedfd)
@@ -520,14 +534,15 @@
 {
 	char *child;
-	int parent = get_parent_and_child(path, &child);
-	if (parent < 0)
-		return parent;
-
-	int rc = vfs_link(parent, child, kind, linkedfd);
+	int parent;
+	int rc = get_parent_and_child(path, &parent, &child);
+	if (rc != EOK)
+		return rc;
+
+	rc = vfs_link(parent, child, kind, linkedfd);
 
 	free(child);
 	vfs_put(parent);
 	return rc;
-}	
+}
 
 /** Lookup a path relative to the local root
@@ -535,9 +550,9 @@
  * @param path  Path to be looked up
  * @param flags Walk flags
- *
- * @return      File handle representing the result on success or a negative
- *              error code on error
- */
-int vfs_lookup(const char *path, int flags)
+ * @param[out] handle Pointer to variable where handle is to be written.
+ *
+ * @return      EOK on success or an error code.
+ */
+int vfs_lookup(const char *path, int flags, int *handle)
 {
 	size_t size;
@@ -545,4 +560,5 @@
 	if (!p)
 		return ENOMEM;
+
 	int root = vfs_root();
 	if (root < 0) {
@@ -550,5 +566,6 @@
 		return ENOENT;
 	}
-	int rc = vfs_walk(root, p, flags);
+
+	int rc = vfs_walk(root, p, flags, handle);
 	vfs_put(root);
 	free(p);
@@ -563,20 +580,23 @@
  * @param flags Walk flags
  * @param mode  Mode in which to open file in
+ * @param[out] handle Pointer to variable where handle is to be written.
  *
  * @return      EOK on success or a negative error code
  */
-int vfs_lookup_open(const char *path, int flags, int mode)
-{
-	int file = vfs_lookup(path, flags);
-	if (file < 0)
-		return file;
-
-	int rc = vfs_open(file, mode);
+int vfs_lookup_open(const char *path, int flags, int mode, int *handle)
+{
+	int file;
+	int rc = vfs_lookup(path, flags, &file);
+	if (rc != EOK)
+		return rc;
+
+	rc = vfs_open(file, mode);
 	if (rc != EOK) {
 		vfs_put(file);
 		return rc;
 	}
-	
-	return file;
+
+	*handle = file;
+	return EOK;
 }
 
@@ -706,11 +726,10 @@
 		}
 		
-		int mpfd = vfs_walk(root_fd, mpa, WALK_DIRECTORY);
-		if (mpfd >= 0) {
+		int mpfd;
+		rc = vfs_walk(root_fd, mpa, WALK_DIRECTORY, &mpfd);
+		if (rc == EOK) {
 			rc = vfs_mount(mpfd, fs_name, service_id, opts, flags,
 			    instance, NULL);
 			vfs_put(mpfd);
-		} else {
-			rc = mpfd;
 		}
 	}
@@ -774,8 +793,9 @@
  * @param high   If true, the received file handle will be allocated from high
  *               indices
+ * @param[out] handle  Received handle.
  *
  * @return       EOK on success or a negative error code
  */
-int vfs_receive_handle(bool high)
+int vfs_receive_handle(bool high, int *handle)
 {
 	ipc_callid_t callid;
@@ -794,7 +814,9 @@
 	async_exchange_end(vfs_exch);
 
-	if (rc != EOK)
-		return rc;
-	return ret;
+	if (rc == EOK) {
+		*handle = (int) ret;
+	}
+
+	return rc;
 }
 
@@ -808,12 +830,14 @@
  * @param buf		Buffer, @a nbytes bytes long
  * @param nbytes	Number of bytes to read
- *
- * @return              On success, non-negative number of bytes read
- * @return              On failure, a negative error code
- */
-ssize_t vfs_read(int file, aoff64_t *pos, void *buf, size_t nbyte)
+ * @param nread		Place to store number of bytes actually read
+ *
+ * @return              On success, EOK and @a *nread is filled with number
+ *			of bytes actually read.
+ * @return              On failure, an error code
+ */
+int vfs_read(int file, aoff64_t *pos, void *buf, size_t nbyte, size_t *nread)
 {
 	ssize_t cnt = 0;
-	size_t nread = 0;
+	size_t nr = 0;
 	uint8_t *bp = (uint8_t *) buf;
 	int rc;
@@ -821,14 +845,18 @@
 	do {
 		bp += cnt;
-		nread += cnt;
+		nr += cnt;
 		*pos += cnt;
-		rc = vfs_read_short(file, *pos, bp, nbyte - nread, &cnt);
-	} while (rc == EOK && cnt > 0 && (nbyte - nread - cnt) > 0);
-	
-	if (rc != EOK)
-		return rc;
-	
+		rc = vfs_read_short(file, *pos, bp, nbyte - nr, &cnt);
+	} while (rc == EOK && cnt > 0 && (nbyte - nr - cnt) > 0);
+	
+	if (rc != EOK) {
+		*nread = nr;
+		return rc;
+	}
+	
+	nr += cnt;
 	*pos += cnt;
-	return nread + cnt;
+	*nread = nr;
+	return EOK;
 }
 
@@ -969,16 +997,20 @@
 /** Return a new file handle representing the local root
  *
- * @return      A clone of the local root file handle or a negative error code
+ * @return      A clone of the local root file handle or -1
  */
 int vfs_root(void)
 {
-	fibril_mutex_lock(&root_mutex);	
-	int r;
-	if (root_fd < 0)
-		r = ENOENT;
-	else
-		r = vfs_clone(root_fd, -1, true);
+	fibril_mutex_lock(&root_mutex);
+	int fd;
+	if (root_fd < 0) {
+		fd = -1;
+	} else {
+		int rc = vfs_clone(root_fd, -1, true, &fd);
+		if (rc != EOK) {
+			fd = -1;
+		}
+	}
 	fibril_mutex_unlock(&root_mutex);
-	return r;
+	return fd;
 }
 
@@ -990,12 +1022,22 @@
  *
  * @param nroot The new local root file handle
- */
-void vfs_root_set(int nroot)
-{
+ *
+ * @return  Error code
+ */
+int vfs_root_set(int nroot)
+{
+	int new_root;
+	int rc = vfs_clone(nroot, -1, true, &new_root);
+	if (rc != EOK) {
+		return rc;
+	}
+
 	fibril_mutex_lock(&root_mutex);
 	if (root_fd >= 0)
 		vfs_put(root_fd);
-	root_fd = vfs_clone(nroot, -1, true);
+	root_fd = new_root;
 	fibril_mutex_unlock(&root_mutex);
+
+	return EOK;
 }
 
@@ -1043,9 +1085,10 @@
 int vfs_stat_path(const char *path, struct stat *stat)
 {
-	int file = vfs_lookup(path, 0);
-	if (file < 0)
-		return file;
-	
-	int rc = vfs_stat(file, stat);
+	int file;
+	int rc = vfs_lookup(path, 0, &file);
+	if (rc != EOK)
+		return rc;
+	
+	rc = vfs_stat(file, stat);
 
 	vfs_put(file);
@@ -1088,9 +1131,10 @@
 int vfs_statfs_path(const char *path, struct statfs *st)
 {
-	int file = vfs_lookup(path, 0);
-	if (file < 0)
-		return file;
-	
-	int rc = vfs_statfs(file, st);
+	int file;
+	int rc = vfs_lookup(path, 0, &file);
+	if (rc != EOK)
+		return rc;
+	
+	rc = vfs_statfs(file, st);
 
 	vfs_put(file);
@@ -1158,16 +1202,18 @@
 int vfs_unlink_path(const char *path)
 {
-	int expect = vfs_lookup(path, 0);
-	if (expect < 0)
-		return expect;
+	int expect;
+	int rc = vfs_lookup(path, 0, &expect);
+	if (rc != EOK)
+		return rc;
 
 	char *child;
-	int parent = get_parent_and_child(path, &child);
-	if (parent < 0) {
+	int parent;
+	rc = get_parent_and_child(path, &parent, &child);
+	if (rc != EOK) {
 		vfs_put(expect);
-		return parent;
-	}
-
-	int rc = vfs_unlink(parent, child, expect);
+		return rc;
+	}
+
+	rc = vfs_unlink(parent, child, expect);
 	
 	free(child);
@@ -1199,9 +1245,10 @@
 int vfs_unmount_path(const char *mpp)
 {
-	int mp = vfs_lookup(mpp, WALK_MOUNT_POINT | WALK_DIRECTORY);
-	if (mp < 0)
-		return mp;
-	
-	int rc = vfs_unmount(mp);
+	int mp;
+	int rc = vfs_lookup(mpp, WALK_MOUNT_POINT | WALK_DIRECTORY, &mp);
+	if (rc != EOK)
+		return rc;
+	
+	rc = vfs_unmount(mp);
 	vfs_put(mp);
 	return rc;
@@ -1213,9 +1260,9 @@
  * @param path          Parent-relative path to be walked
  * @param flags         Flags influencing the walk
- *
- * @retrun              File handle representing the result on success or
- *                      a negative error code on error
- */
-int vfs_walk(int parent, const char *path, int flags)
+ * @param[out] handle   File handle representing the result on success.
+ *
+ * @return              Error code.
+ */
+int vfs_walk(int parent, const char *path, int flags, int *handle)
 {
 	async_exch_t *exch = vfs_exchange_begin();
@@ -1235,5 +1282,6 @@
 		return (int) rc;
 	
-	return (int) IPC_GET_ARG1(answer);
+	*handle = (int) IPC_GET_ARG1(answer);
+	return EOK;
 }
 
@@ -1247,12 +1295,15 @@
  * @param buf           Data, @a nbytes bytes long
  * @param nbytes        Number of bytes to write
- *
- * @return		On success, non-negative number of bytes written
- * @return              On failure, a negative error code
- */
-ssize_t vfs_write(int file, aoff64_t *pos, const void *buf, size_t nbyte)
+ * @param nwritten	Place to store number of bytes written
+ *
+ * @return		On success, EOK, @a *nwr is filled with number
+ *			of bytes written
+ * @return              On failure, an error code
+ */
+int vfs_write(int file, aoff64_t *pos, const void *buf, size_t nbyte,
+    size_t *nwritten)
 {
 	ssize_t cnt = 0;
-	ssize_t nwritten = 0;
+	ssize_t nwr = 0;
 	const uint8_t *bp = (uint8_t *) buf;
 	int rc;
@@ -1260,14 +1311,18 @@
 	do {
 		bp += cnt;
-		nwritten += cnt;
+		nwr += cnt;
 		*pos += cnt;
-		rc = vfs_write_short(file, *pos, bp, nbyte - nwritten, &cnt);
-	} while (rc == EOK && ((ssize_t )nbyte - nwritten - cnt) > 0);
-
-	if (rc != EOK)
-		return rc;
-
+		rc = vfs_write_short(file, *pos, bp, nbyte - nwr, &cnt);
+	} while (rc == EOK && ((ssize_t )nbyte - nwr - cnt) > 0);
+
+	if (rc != EOK) {
+		*nwritten = nwr;
+		return rc;
+	}
+
+	nwr += cnt;
 	*pos += cnt;
-	return nbyte;
+	*nwritten = nwr;
+	return EOK;
 }
 
Index: uspace/lib/c/include/adt/circ_buf.h
===================================================================
--- uspace/lib/c/include/adt/circ_buf.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/lib/c/include/adt/circ_buf.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file Circular buffer
+ */
+
+#ifndef LIBC_CIRC_BUF_H_
+#define LIBC_CIRC_BUF_H_
+
+#include <stddef.h>
+
+/** Circular buffer */
+typedef struct {
+	/** Buffer */
+	void *buf;
+	/** Number of buffer members */
+	size_t nmemb;
+	/** Member size */
+	size_t size;
+	/** Read position */
+	size_t rp;
+	/** Write position */
+	size_t wp;
+	/** Number of used entries */
+	size_t nused;
+} circ_buf_t;
+
+extern void circ_buf_init(circ_buf_t *, void *, size_t, size_t);
+extern size_t circ_buf_nfree(circ_buf_t *);
+extern size_t circ_buf_nused(circ_buf_t *);
+extern int circ_buf_push(circ_buf_t *, const void *);
+extern int circ_buf_pop(circ_buf_t *, void *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/adt/fifo.h
===================================================================
--- uspace/lib/c/include/adt/fifo.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/adt/fifo.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -46,5 +46,5 @@
 #define LIBC_FIFO_H_
 
-#include <malloc.h>
+#include <stdlib.h>
 
 typedef unsigned long fifo_count_t;
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/async.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -49,6 +49,7 @@
 #include <abi/ipc/event.h>
 #include <abi/ipc/interfaces.h>
-
-typedef ipc_callid_t aid_t;
+#include <abi/cap.h>
+
+typedef sysarg_t aid_t;
 typedef sysarg_t port_id_t;
 
@@ -58,16 +59,15 @@
 /** Port connection handler
  *
- * @param callid ID of incoming call or 0 if connection initiated from
- *               inside using async_create_callback_port()
- * @param call   Incoming call or 0 if connection initiated from inside
- *               using async_create_callback_port()
- * @param arg    Local argument.
- *
- */
-typedef void (*async_port_handler_t)(ipc_callid_t, ipc_call_t *, void *);
+ * @param chandle  Handle of the incoming call or CAP_NIL if connection
+ *                 initiated from inside using async_create_callback_port()
+ * @param call     Incoming call or 0 if connection initiated from inside
+ *                 using async_create_callback_port()
+ * @param arg      Local argument.
+ *
+ */
+typedef void (*async_port_handler_t)(cap_handle_t, ipc_call_t *, void *);
 
 /** Notification handler */
-typedef void (*async_notification_handler_t)(ipc_callid_t, ipc_call_t *,
-    void *);
+typedef void (*async_notification_handler_t)(ipc_call_t *, void *);
 
 /** Exchange management style
@@ -119,5 +119,5 @@
 	async_get_call_timeout(data, 0)
 
-extern ipc_callid_t async_get_call_timeout(ipc_call_t *, suseconds_t);
+extern cap_handle_t async_get_call_timeout(ipc_call_t *, suseconds_t);
 
 /*
@@ -151,4 +151,6 @@
 
 extern void async_usleep(suseconds_t);
+extern void async_sleep(unsigned int);
+
 extern void async_create_manager(void);
 extern void async_destroy_manager(void);
@@ -167,5 +169,5 @@
 
 extern int async_irq_subscribe(int, async_notification_handler_t, void *,
-    const irq_code_t *);
+    const irq_code_t *, cap_handle_t *);
 extern int async_irq_unsubscribe(int);
 
@@ -196,12 +198,12 @@
  */
 
-extern sysarg_t async_answer_0(ipc_callid_t, sysarg_t);
-extern sysarg_t async_answer_1(ipc_callid_t, sysarg_t, sysarg_t);
-extern sysarg_t async_answer_2(ipc_callid_t, sysarg_t, sysarg_t, sysarg_t);
-extern sysarg_t async_answer_3(ipc_callid_t, sysarg_t, sysarg_t, sysarg_t,
+extern sysarg_t async_answer_0(cap_handle_t, sysarg_t);
+extern sysarg_t async_answer_1(cap_handle_t, sysarg_t, sysarg_t);
+extern sysarg_t async_answer_2(cap_handle_t, sysarg_t, sysarg_t, sysarg_t);
+extern sysarg_t async_answer_3(cap_handle_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t);
-extern sysarg_t async_answer_4(ipc_callid_t, sysarg_t, sysarg_t, sysarg_t,
+extern sysarg_t async_answer_4(cap_handle_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t);
-extern sysarg_t async_answer_5(ipc_callid_t, sysarg_t, sysarg_t, sysarg_t,
+extern sysarg_t async_answer_5(cap_handle_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, sysarg_t);
 
@@ -210,7 +212,7 @@
  */
 
-extern int async_forward_fast(ipc_callid_t, async_exch_t *, sysarg_t, sysarg_t,
+extern int async_forward_fast(cap_handle_t, async_exch_t *, sysarg_t, sysarg_t,
     sysarg_t, unsigned int);
-extern int async_forward_slow(ipc_callid_t, async_exch_t *, sysarg_t, sysarg_t,
+extern int async_forward_slow(cap_handle_t, async_exch_t *, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, sysarg_t, sysarg_t, unsigned int);
 
@@ -382,10 +384,10 @@
 extern int async_share_in_start(async_exch_t *, size_t, sysarg_t,
     unsigned int *, void **);
-extern bool async_share_in_receive(ipc_callid_t *, size_t *);
-extern int async_share_in_finalize(ipc_callid_t, void *, unsigned int);
+extern bool async_share_in_receive(cap_handle_t *, size_t *);
+extern int async_share_in_finalize(cap_handle_t, void *, unsigned int);
 
 extern int async_share_out_start(async_exch_t *, void *, unsigned int);
-extern bool async_share_out_receive(ipc_callid_t *, size_t *, unsigned int *);
-extern int async_share_out_finalize(ipc_callid_t, void **);
+extern bool async_share_out_receive(cap_handle_t *, size_t *, unsigned int *);
+extern int async_share_out_finalize(cap_handle_t, void **);
 
 /*
@@ -421,7 +423,7 @@
 extern aid_t async_data_read(async_exch_t *, void *, size_t, ipc_call_t *);
 extern int async_data_read_start(async_exch_t *, void *, size_t);
-extern bool async_data_read_receive(ipc_callid_t *, size_t *);
-extern bool async_data_read_receive_call(ipc_callid_t *, ipc_call_t *, size_t *);
-extern int async_data_read_finalize(ipc_callid_t, const void *, size_t);
+extern bool async_data_read_receive(cap_handle_t *, size_t *);
+extern bool async_data_read_receive_call(cap_handle_t *, ipc_call_t *, size_t *);
+extern int async_data_read_finalize(cap_handle_t, const void *, size_t);
 
 extern int async_data_read_forward_fast(async_exch_t *, sysarg_t, sysarg_t,
@@ -460,7 +462,7 @@
 
 extern int async_data_write_start(async_exch_t *, const void *, size_t);
-extern bool async_data_write_receive(ipc_callid_t *, size_t *);
-extern bool async_data_write_receive_call(ipc_callid_t *, ipc_call_t *, size_t *);
-extern int async_data_write_finalize(ipc_callid_t, void *, size_t);
+extern bool async_data_write_receive(cap_handle_t *, size_t *);
+extern bool async_data_write_receive_call(cap_handle_t *, ipc_call_t *, size_t *);
+extern int async_data_write_finalize(cap_handle_t, void *, size_t);
 
 extern int async_data_write_accept(void **, const bool, const size_t,
@@ -476,7 +478,7 @@
 extern int async_state_change_start(async_exch_t *, sysarg_t, sysarg_t,
     sysarg_t, async_exch_t *);
-extern bool async_state_change_receive(ipc_callid_t *, sysarg_t *, sysarg_t *,
+extern bool async_state_change_receive(cap_handle_t *, sysarg_t *, sysarg_t *,
     sysarg_t *);
-extern int async_state_change_finalize(ipc_callid_t, async_exch_t *);
+extern int async_state_change_finalize(cap_handle_t, async_exch_t *);
 
 extern void *async_remote_state_acquire(async_sess_t *);
Index: uspace/lib/c/include/bd.h
===================================================================
--- uspace/lib/c/include/bd.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/bd.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,5 +30,5 @@
  * @{
  */
-/** @file
+/** @file Block device client interface
  */
 
Index: uspace/lib/c/include/device/hw_res.h
===================================================================
--- uspace/lib/c/include/device/hw_res.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/device/hw_res.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -123,5 +123,5 @@
 extern int hw_res_dma_channel_setup(async_sess_t *, unsigned int, uint32_t,
     uint32_t, uint8_t);
-extern int hw_res_dma_channel_remain(async_sess_t *, unsigned);
+extern int hw_res_dma_channel_remain(async_sess_t *, unsigned, size_t *);
 
 #endif
Index: uspace/lib/c/include/elf/elf_mod.h
===================================================================
--- uspace/lib/c/include/elf/elf_mod.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/elf/elf_mod.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -53,4 +53,5 @@
 #define EE_LOADER		5	/* The image is actually a program loader. */
 #define EE_IRRECOVERABLE	6
+#define EE_IO			7	/* Could not read file. */
 
 typedef enum {
Index: uspace/lib/c/include/errno.h
===================================================================
--- uspace/lib/c/include/errno.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/errno.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,35 +40,5 @@
 #define errno  (*(__errno()))
 
-extern int *__errno(void) __attribute__((const));
-
-#define EMFILE        (-18)
-#define ENAMETOOLONG  (-256)
-#define EISDIR        (-257)
-#define ENOTDIR       (-258)
-#define ENOSPC        (-259)
-#define ENOTEMPTY     (-261)
-#define EBADF         (-262)
-#define EDOM          (-263)
-#define ERANGE        (-264)
-#define EXDEV         (-265)
-#define EIO           (-266)
-#define EMLINK        (-267)
-#define ENXIO         (-268)
-#define ENOFS         (-269)
-
-/** Bad checksum. */
-#define EBADCHECKSUM  (-300)
-
-/** USB: stalled operation. */
-#define ESTALL (-301)
-
-/** Empty resource (no data). */
-#define EEMPTY (-302)
-
-/** Negative acknowledgment. */
-#define ENAK (-303)
-
-/** The requested operation was not performed. Try again later. */
-#define EAGAIN  (-11002)
+extern errno_t *__errno(void) __attribute__((const));
 
 #endif
Index: uspace/lib/c/include/fibril_synch.h
===================================================================
--- uspace/lib/c/include/fibril_synch.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/fibril_synch.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -173,6 +173,4 @@
 extern fibril_timer_state_t fibril_timer_clear(fibril_timer_t *);
 extern fibril_timer_state_t fibril_timer_clear_locked(fibril_timer_t *);
-extern void fibril_usleep(useconds_t);
-extern void fibril_sleep(unsigned int);
 
 #endif
Index: uspace/lib/c/include/ieee80211/ieee80211.h
===================================================================
--- uspace/lib/c/include/ieee80211/ieee80211.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/ieee80211/ieee80211.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,5 +38,4 @@
 #define LIBC_IEEE80211_H_
 
-#include <malloc.h>
 #include <adt/list.h>
 #include <nic/nic.h>
Index: uspace/lib/c/include/io/chardev.h
===================================================================
--- uspace/lib/c/include/io/chardev.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/io/chardev.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Jan Vesely
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -33,9 +34,15 @@
 #define LIBC_IO_CHARDEV_H_
 
-#include <types/common.h>
 #include <async.h>
+#include <stddef.h>
 
-ssize_t chardev_read(async_exch_t *, void *, size_t);
-ssize_t chardev_write(async_exch_t *, const void *, size_t);
+typedef struct {
+	async_sess_t *sess;
+} chardev_t;
+
+extern int chardev_open(async_sess_t *, chardev_t **);
+extern void chardev_close(chardev_t *);
+extern int chardev_read(chardev_t *, void *, size_t, size_t *);
+extern int chardev_write(chardev_t *, const void *, size_t, size_t *);
 
 #endif
Index: uspace/lib/c/include/io/chardev_srv.h
===================================================================
--- uspace/lib/c/include/io/chardev_srv.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/io/chardev_srv.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -59,6 +59,7 @@
 	int (*open)(chardev_srvs_t *, chardev_srv_t *);
 	int (*close)(chardev_srv_t *);
-	int (*read)(chardev_srv_t *, void *, size_t);
-	int (*write)(chardev_srv_t *, const void *, size_t);
+	int (*read)(chardev_srv_t *, void *, size_t, size_t *);
+	int (*write)(chardev_srv_t *, const void *, size_t, size_t *);
+	void (*def_handler)(chardev_srv_t *, ipc_callid_t, ipc_call_t *);
 };
 
Index: uspace/lib/c/include/io/con_srv.h
===================================================================
--- uspace/lib/c/include/io/con_srv.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/io/con_srv.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -69,6 +69,6 @@
 	int (*open)(con_srvs_t *, con_srv_t *);
 	int (*close)(con_srv_t *);
-	int (*read)(con_srv_t *, void *, size_t);
-	int (*write)(con_srv_t *, void *, size_t);
+	int (*read)(con_srv_t *, void *, size_t, size_t *);
+	int (*write)(con_srv_t *, void *, size_t, size_t *);
 	void (*sync)(con_srv_t *);
 	void (*clear)(con_srv_t *);
Index: uspace/lib/c/include/io/klog.h
===================================================================
--- uspace/lib/c/include/io/klog.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/io/klog.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,15 +44,10 @@
 #include <abi/log.h>
 
-extern size_t klog_write(log_level_t, const void *, size_t);
-extern int klog_read(void *, size_t);
+extern int klog_write(log_level_t, const void *, size_t);
+extern int klog_read(void *, size_t, size_t *);
 
 #define KLOG_PRINTF(lvl, fmt, ...) ({ \
-	char *_fmt = str_dup(fmt); \
-	size_t _fmtsize = str_size(_fmt); \
-	if (_fmtsize > 0 && _fmt[_fmtsize - 1] == '\n') \
-		_fmt[_fmtsize - 1] = 0; \
 	char *_s; \
-	int _c = asprintf(&_s, _fmt, ##__VA_ARGS__); \
-	free(_fmt); \
+	int _c = asprintf(&_s, fmt, ##__VA_ARGS__); \
 	if (_c >= 0) { \
 		_c = klog_write((lvl), _s, str_size(_s)); \
Index: uspace/lib/c/include/io/serial.h
===================================================================
--- uspace/lib/c/include/io/serial.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/lib/c/include/io/serial.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IO_SERIAL_H_
+#define LIBC_IO_SERIAL_H_
+
+#include <async.h>
+#include <ipc/serial_ctl.h>
+
+typedef struct {
+	async_sess_t *sess;
+} serial_t;
+
+extern int serial_open(async_sess_t *, serial_t **);
+extern void serial_close(serial_t *);
+extern int serial_set_comm_props(serial_t *, unsigned, serial_parity_t,
+    unsigned, unsigned);
+extern int serial_get_comm_props(serial_t *, unsigned *, serial_parity_t *,
+    unsigned *, unsigned *);
+
+#endif
+
+/** @}
+ */
Index: pace/lib/c/include/ipc/char.h
===================================================================
--- uspace/lib/c/include/ipc/char.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libcipc
- * @{
- */
-/** @file
- * @brief Character device interface.
- */
-
-#ifndef LIBC_IPC_CHAR_H_
-#define LIBC_IPC_CHAR_H_
-
-#include <ipc/common.h>
-
-typedef enum {
-	CHAR_WRITE_BYTE = IPC_FIRST_USER_METHOD
-} char_request_t;
-
-typedef enum {
-	CHAR_NOTIF_BYTE = IPC_FIRST_USER_METHOD
-} char_notif_t;
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/ipc/chardev.h
===================================================================
--- uspace/lib/c/include/ipc/chardev.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/ipc/chardev.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,6 +41,10 @@
 typedef enum {
 	CHARDEV_READ = IPC_FIRST_USER_METHOD,
-	CHARDEV_WRITE
+	CHARDEV_WRITE,
 } chardev_request_t;
+
+enum {
+	CHARDEV_LIMIT = CHARDEV_WRITE + 1
+};
 
 #endif
Index: uspace/lib/c/include/ipc/common.h
===================================================================
--- uspace/lib/c/include/ipc/common.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/ipc/common.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,6 +40,9 @@
 #include <abi/proc/task.h>
 #include <futex.h>
+#include <abi/cap.h>
 
 #define IPC_FLAG_BLOCKING  0x01
+
+struct async_call;
 
 typedef struct {
@@ -47,7 +50,10 @@
 	task_id_t in_task_id;
 	sysarg_t in_phone_hash;
+	unsigned flags;
+	struct async_call *label;
+	cap_handle_t cap_handle;
 } ipc_call_t;
 
-typedef sysarg_t ipc_callid_t;
+typedef cap_handle_t ipc_callid_t;
 
 extern futex_t async_futex;
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,5 +30,5 @@
 #define LIBC_IPC_DEV_IFACE_H_
 
-#include <malloc.h>
+#include <stdlib.h>
 #include <types/common.h>
 
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/ipc/devman.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,6 +36,6 @@
 #include <ipc/common.h>
 #include <adt/list.h>
-#include <malloc.h>
 #include <mem.h>
+#include <stdlib.h>
 
 #define DEVMAN_NAME_MAXLEN  256
Index: uspace/lib/c/include/ipc/ipc.h
===================================================================
--- uspace/lib/c/include/ipc/ipc.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/ipc/ipc.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,8 +44,9 @@
 #include <abi/synch.h>
 #include <abi/proc/task.h>
+#include <abi/cap.h>
 
 typedef void (*ipc_async_callback_t)(void *, int, ipc_call_t *);
 
-extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, sysarg_t, unsigned int);
+extern int ipc_wait_cycle(ipc_call_t *, sysarg_t, unsigned int);
 extern void ipc_poke(void);
 
@@ -53,6 +54,6 @@
 	ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT);
 
-extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, sysarg_t);
-extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *);
+extern int ipc_wait_for_call_timeout(ipc_call_t *, sysarg_t);
+extern int ipc_trywait_for_call(ipc_call_t *);
 
 /*
@@ -63,20 +64,21 @@
  */
 
-#define ipc_answer_0(callid, retval) \
-	ipc_answer_fast((callid), (retval), 0, 0, 0, 0)
-#define ipc_answer_1(callid, retval, arg1) \
-	ipc_answer_fast((callid), (retval), (arg1), 0, 0, 0)
-#define ipc_answer_2(callid, retval, arg1, arg2) \
-	ipc_answer_fast((callid), (retval), (arg1), (arg2), 0, 0)
-#define ipc_answer_3(callid, retval, arg1, arg2, arg3) \
-	ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), 0)
-#define ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4) \
-	ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), (arg4))
-#define ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5) \
-	ipc_answer_slow((callid), (retval), (arg1), (arg2), (arg3), (arg4), (arg5))
+#define ipc_answer_0(chandle, retval) \
+	ipc_answer_fast((chandle), (retval), 0, 0, 0, 0)
+#define ipc_answer_1(chandle, retval, arg1) \
+	ipc_answer_fast((chandle), (retval), (arg1), 0, 0, 0)
+#define ipc_answer_2(chandle, retval, arg1, arg2) \
+	ipc_answer_fast((chandle), (retval), (arg1), (arg2), 0, 0)
+#define ipc_answer_3(chandle, retval, arg1, arg2, arg3) \
+	ipc_answer_fast((chandle), (retval), (arg1), (arg2), (arg3), 0)
+#define ipc_answer_4(chandle, retval, arg1, arg2, arg3, arg4) \
+	ipc_answer_fast((chandle), (retval), (arg1), (arg2), (arg3), (arg4))
+#define ipc_answer_5(chandle, retval, arg1, arg2, arg3, arg4, arg5) \
+	ipc_answer_slow((chandle), (retval), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5))
 
-extern sysarg_t ipc_answer_fast(ipc_callid_t, sysarg_t, sysarg_t, sysarg_t,
+extern sysarg_t ipc_answer_fast(cap_handle_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t);
-extern sysarg_t ipc_answer_slow(ipc_callid_t, sysarg_t, sysarg_t, sysarg_t,
+extern sysarg_t ipc_answer_slow(cap_handle_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, sysarg_t);
 
@@ -88,38 +90,37 @@
  */
 
-#define ipc_call_async_0(phoneid, method, private, callback) \
-	ipc_call_async_fast((phoneid), (method), 0, 0, 0, 0, (private), \
+#define ipc_call_async_0(phandle, method, private, callback) \
+	ipc_call_async_fast((phandle), (method), 0, 0, 0, (private), (callback))
+#define ipc_call_async_1(phandle, method, arg1, private, callback) \
+	ipc_call_async_fast((phandle), (method), (arg1), 0, 0, (private), \
 	    (callback))
-#define ipc_call_async_1(phoneid, method, arg1, private, callback) \
-	ipc_call_async_fast((phoneid), (method), (arg1), 0, 0, 0, (private), \
-	    (callback))
-#define ipc_call_async_2(phoneid, method, arg1, arg2, private, callback) \
-	ipc_call_async_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
+#define ipc_call_async_2(phandle, method, arg1, arg2, private, callback) \
+	ipc_call_async_fast((phandle), (method), (arg1), (arg2), 0, \
 	    (private), (callback))
-#define ipc_call_async_3(phoneid, method, arg1, arg2, arg3, private, callback) \
-	ipc_call_async_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, \
+#define ipc_call_async_3(phandle, method, arg1, arg2, arg3, private, callback) \
+	ipc_call_async_fast((phandle), (method), (arg1), (arg2), (arg3), \
 	    (private), (callback))
-#define ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, private, \
+#define ipc_call_async_4(phandle, method, arg1, arg2, arg3, arg4, private, \
     callback) \
-	ipc_call_async_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), (private), (callback))
-#define ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, \
+	ipc_call_async_slow((phandle), (method), (arg1), (arg2), (arg3), \
+	    (arg4), 0, (private), (callback))
+#define ipc_call_async_5(phandle, method, arg1, arg2, arg3, arg4, arg5, \
     private, callback) \
-	ipc_call_async_slow((phoneid), (method), (arg1), (arg2), (arg3), \
+	ipc_call_async_slow((phandle), (method), (arg1), (arg2), (arg3), \
 	    (arg4), (arg5), (private), (callback))
 
-extern void ipc_call_async_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+extern void ipc_call_async_fast(cap_handle_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, void *, ipc_async_callback_t);
-extern void ipc_call_async_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, void *, ipc_async_callback_t);
+extern void ipc_call_async_slow(cap_handle_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, void *, ipc_async_callback_t);
 
-extern int ipc_hangup(int);
+extern int ipc_hangup(cap_handle_t);
 
-extern int ipc_forward_fast(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
-    unsigned int);
-extern int ipc_forward_slow(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, sysarg_t, unsigned int);
+extern int ipc_forward_fast(cap_handle_t, cap_handle_t, sysarg_t, sysarg_t,
+    sysarg_t, unsigned int);
+extern int ipc_forward_slow(cap_handle_t, cap_handle_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t, unsigned int);
 
-extern int ipc_connect_kbox(task_id_t);
+extern int ipc_connect_kbox(task_id_t, cap_handle_t *);
 
 #endif
Index: uspace/lib/c/include/ipc/irq.h
===================================================================
--- uspace/lib/c/include/ipc/irq.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/ipc/irq.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,7 +38,8 @@
 #include <types/common.h>
 #include <abi/ddi/irq.h>
+#include <abi/cap.h>
 
-extern int ipc_irq_subscribe(int, sysarg_t, const irq_code_t *);
-extern int ipc_irq_unsubscribe(int);
+extern int ipc_irq_subscribe(int, sysarg_t, const irq_code_t *, cap_handle_t *);
+extern int ipc_irq_unsubscribe(cap_handle_t);
 
 #endif
Index: uspace/lib/c/include/ipc/serial_ctl.h
===================================================================
--- uspace/lib/c/include/ipc/serial_ctl.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/ipc/serial_ctl.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,5 +30,5 @@
 #define LIBC_IPC_SERIAL_CTL_H_
 
-#include <ipc/dev_iface.h>
+#include <ipc/chardev.h>
 
 /** IPC methods for getting/setting serial communication properties
@@ -41,5 +41,5 @@
  */
 typedef enum {
-	SERIAL_GET_COM_PROPS = DEV_FIRST_CUSTOM_METHOD,
+	SERIAL_GET_COM_PROPS = CHARDEV_LIMIT,
 	SERIAL_SET_COM_PROPS
 } serial_ctl_t;
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/ipc/services.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -49,4 +49,7 @@
 } service_t;
 
+#define SERVICE_NAME_CHARDEV_TEST_SMALLX "chardev-test/smallx"
+#define SERVICE_NAME_CHARDEV_TEST_LARGEX "chardev-test/largex"
+#define SERVICE_NAME_CHARDEV_TEST_PARTIALX "chardev-test/partialx"
 #define SERVICE_NAME_CLIPBOARD "clipboard"
 #define SERVICE_NAME_CORECFG  "corecfg"
Index: uspace/lib/c/include/str_error.h
===================================================================
--- uspace/lib/c/include/str_error.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/str_error.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,8 @@
 #define LIBC_STRERROR_H_
 
-const char *str_error(const int);
+#include <errno.h>
+
+const char *str_error(errno_t);
+const char *str_error_name(errno_t);
 
 #endif
Index: uspace/lib/c/include/vfs/vfs.h
===================================================================
--- uspace/lib/c/include/vfs/vfs.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/include/vfs/vfs.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -85,5 +85,5 @@
 
 extern char *vfs_absolutize(const char *, size_t *);
-extern int vfs_clone(int, int, bool);
+extern int vfs_clone(int, int, bool, int *);
 extern int vfs_cwd_get(char *path, size_t);
 extern int vfs_cwd_set(const char *path);
@@ -95,6 +95,6 @@
 extern int vfs_link(int, const char *, vfs_file_kind_t, int *);
 extern int vfs_link_path(const char *, vfs_file_kind_t, int *);
-extern int vfs_lookup(const char *, int);
-extern int vfs_lookup_open(const char *, int, int);
+extern int vfs_lookup(const char *, int, int *);
+extern int vfs_lookup_open(const char *, int, int, int *);
 extern int vfs_mount_path(const char *, const char *, const char *,
     const char *, unsigned int, unsigned int);
@@ -104,11 +104,11 @@
 extern int vfs_pass_handle(async_exch_t *, int, async_exch_t *);
 extern int vfs_put(int);
-extern ssize_t vfs_read(int, aoff64_t *, void *, size_t);
+extern int vfs_read(int, aoff64_t *, void *, size_t, size_t *);
 extern int vfs_read_short(int, aoff64_t, void *, size_t, ssize_t *);
-extern int vfs_receive_handle(bool);
+extern int vfs_receive_handle(bool, int *);
 extern int vfs_rename_path(const char *, const char *);
 extern int vfs_resize(int, aoff64_t);
 extern int vfs_root(void);
-extern void vfs_root_set(int);
+extern int vfs_root_set(int);
 extern int vfs_stat(int, struct stat *);
 extern int vfs_stat_path(const char *, struct stat *);
@@ -120,6 +120,6 @@
 extern int vfs_unmount(int);
 extern int vfs_unmount_path(const char *);
-extern int vfs_walk(int, const char *, int);
-extern ssize_t vfs_write(int, aoff64_t *, const void *, size_t);
+extern int vfs_walk(int, const char *, int, int *);
+extern int vfs_write(int, aoff64_t *, const void *, size_t, size_t *);
 extern int vfs_write_short(int, aoff64_t, const void *, size_t, ssize_t *);
 
Index: uspace/lib/c/test/adt/circ_buf.c
===================================================================
--- uspace/lib/c/test/adt/circ_buf.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/lib/c/test/adt/circ_buf.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <adt/circ_buf.h>
+#include <pcut/pcut.h>
+
+PCUT_INIT
+
+PCUT_TEST_SUITE(circ_buf);
+
+enum {
+	buffer_size = 16
+};
+
+static int buffer[buffer_size];
+
+/** Basic insertion/deletion test.
+ *
+ * Test initialization, emptiness, pushing buffer until it is full,
+ * then emptying it again.
+ */
+PCUT_TEST(push_pop)
+{
+	circ_buf_t cbuf;
+	int i;
+	int j;
+	int rc;
+
+	circ_buf_init(&cbuf, buffer, buffer_size, sizeof(int));
+
+	for (i = 0; i < buffer_size; i++) {
+		PCUT_ASSERT_INT_EQUALS(buffer_size - i, circ_buf_nfree(&cbuf));
+		PCUT_ASSERT_INT_EQUALS(i, circ_buf_nused(&cbuf));
+		rc = circ_buf_push(&cbuf, &i);
+		PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	}
+
+	rc = circ_buf_push(&cbuf, &i);
+	PCUT_ASSERT_ERRNO_VAL(EAGAIN, rc);
+
+	for (i = 0; i < buffer_size; i++) {
+		PCUT_ASSERT_INT_EQUALS(i, circ_buf_nfree(&cbuf));
+		PCUT_ASSERT_INT_EQUALS(buffer_size - i, circ_buf_nused(&cbuf));
+		rc = circ_buf_pop(&cbuf, &j);
+		PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+		PCUT_ASSERT_INT_EQUALS(i, j);
+	}
+
+	PCUT_ASSERT_INT_EQUALS(buffer_size, circ_buf_nfree(&cbuf));
+	PCUT_ASSERT_INT_EQUALS(0, circ_buf_nused(&cbuf));
+
+	rc = circ_buf_pop(&cbuf, &j);
+	PCUT_ASSERT_ERRNO_VAL(EAGAIN, rc);
+}
+
+PCUT_EXPORT(circ_buf);
Index: uspace/lib/c/test/fibril/timer.c
===================================================================
--- uspace/lib/c/test/fibril/timer.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/test/fibril/timer.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -27,4 +27,5 @@
  */
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <pcut/pcut.h>
@@ -77,5 +78,5 @@
 
 	fibril_timer_set_locked(t, 100 * 1000 * 1000, test_timeout_fn, &cnt);
-	fibril_usleep(1000);
+	async_usleep(1000);
 	fts = fibril_timer_clear_locked(t);
 	PCUT_ASSERT_INT_EQUALS(fts_active, fts);
@@ -100,5 +101,5 @@
 	cnt = 0;
 	fibril_timer_set(t, 100 * 1000 * 1000, test_timeout_fn, &cnt);
-	fibril_usleep(1000);
+	async_usleep(1000);
 	fts = fibril_timer_clear(t);
 	PCUT_ASSERT_INT_EQUALS(fts_active, fts);
@@ -126,5 +127,5 @@
 	fibril_mutex_unlock(&lock);
 
-	fibril_usleep(1000);
+	async_usleep(1000);
 
 	fibril_mutex_lock(&lock);
Index: uspace/lib/c/test/main.c
===================================================================
--- uspace/lib/c/test/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/c/test/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -32,4 +32,5 @@
 PCUT_INIT
 
+PCUT_IMPORT(circ_buf);
 PCUT_IMPORT(fibril_timer);
 PCUT_IMPORT(odict);
Index: uspace/lib/compress/gzip.c
===================================================================
--- uspace/lib/compress/gzip.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/compress/gzip.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -31,6 +31,6 @@
 #include <errno.h>
 #include <mem.h>
-#include <malloc.h>
 #include <byteorder.h>
+#include <stdlib.h>
 #include "gzip.h"
 #include "inflate.h"
Index: uspace/lib/draw/codec/tga.gz.c
===================================================================
--- uspace/lib/draw/codec/tga.gz.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/draw/codec/tga.gz.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,5 @@
 #include <errno.h>
 #include <gzip.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include "tga.gz.h"
 #include "tga.h"
Index: uspace/lib/draw/cursor.c
===================================================================
--- uspace/lib/draw/cursor.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/draw/cursor.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -34,5 +34,5 @@
  */
 
-#include <malloc.h>
+#include <stdlib.h>
 
 #include "cursor.h"
Index: uspace/lib/draw/cursor/embedded.c
===================================================================
--- uspace/lib/draw/cursor/embedded.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/draw/cursor/embedded.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,5 +37,5 @@
 #include <stddef.h>
 #include <stdint.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 #include "../gfx/cursor-11x18.h"
Index: uspace/lib/draw/drawctx.c
===================================================================
--- uspace/lib/draw/drawctx.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/draw/drawctx.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,5 @@
 #include <assert.h>
 #include <adt/list.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 #include "drawctx.h"
Index: uspace/lib/draw/font.c
===================================================================
--- uspace/lib/draw/font.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/draw/font.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,6 +35,6 @@
  */
 
-#include <malloc.h>
 #include <errno.h>
+#include <stdlib.h>
 #include <str.h>
 
Index: uspace/lib/draw/font/bitmap_backend.c
===================================================================
--- uspace/lib/draw/font/bitmap_backend.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/draw/font/bitmap_backend.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,6 +35,6 @@
  */
 
-#include <malloc.h>
 #include <errno.h>
+#include <stdlib.h>
 
 #include "../font.h"
Index: uspace/lib/draw/font/embedded.c
===================================================================
--- uspace/lib/draw/font/embedded.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/draw/font/embedded.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,6 +36,6 @@
 
 #include <stdint.h>
-#include <malloc.h>
 #include <errno.h>
+#include <stdlib.h>
 
 #include "../gfx/font-8x16.h"
Index: uspace/lib/draw/font/pcf.c
===================================================================
--- uspace/lib/draw/font/pcf.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/draw/font/pcf.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,4 @@
 #include <stddef.h>
 #include <stdint.h>
-#include <malloc.h>
 #include <errno.h>
 #include <byteorder.h>
@@ -42,4 +41,5 @@
 #include <align.h>
 #include <offset.h>
+#include <stdlib.h>
 
 #include "pcf.h"
Index: uspace/lib/draw/path.c
===================================================================
--- uspace/lib/draw/path.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/draw/path.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,5 +35,5 @@
 
 #include <assert.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 #include "path.h"
Index: uspace/lib/draw/surface.c
===================================================================
--- uspace/lib/draw/surface.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/draw/surface.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,8 +35,8 @@
  */
 
-#include <malloc.h>
 #include <mem.h>
 #include <as.h>
 #include <assert.h>
+#include <stdlib.h>
 #include "surface.h"
 
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/drv/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -43,5 +43,4 @@
 	generic/remote_hw_res.c \
 	generic/remote_pio_window.c \
-	generic/remote_char_dev.c \
 	generic/remote_nic.c \
 	generic/remote_ieee80211.c \
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/drv/generic/dev_iface.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -42,5 +42,4 @@
 #include "remote_hw_res.h"
 #include "remote_pio_window.h"
-#include "remote_char_dev.h"
 #include "remote_clock_dev.h"
 #include "remote_led_dev.h"
@@ -62,5 +61,4 @@
 		[HW_RES_DEV_IFACE] = &remote_hw_res_iface,
 		[PIO_WINDOW_DEV_IFACE] = &remote_pio_window_iface,
-		[CHAR_DEV_IFACE] = &remote_char_dev_iface,
 		[NIC_DEV_IFACE] = &remote_nic_iface,
 		[IEEE80211_DEV_IFACE] = &remote_ieee80211_iface,
Index: uspace/lib/drv/generic/interrupt.c
===================================================================
--- uspace/lib/drv/generic/interrupt.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/drv/generic/interrupt.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,8 +44,9 @@
 
 int register_interrupt_handler(ddf_dev_t *dev, int irq,
-    interrupt_handler_t *handler, const irq_code_t *irq_code)
+    interrupt_handler_t *handler, const irq_code_t *irq_code,
+    cap_handle_t *handle)
 {
 	return async_irq_subscribe(irq, (async_notification_handler_t) handler,
-	    dev, irq_code);
+	    dev, irq_code, handle);
 }
 
Index: pace/lib/drv/generic/private/remote_char_dev.h
===================================================================
--- uspace/lib/drv/generic/private/remote_char_dev.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,44 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libdrv
- * @{
- */
-/** @file
- */
-
-#ifndef LIBDRV_REMOTE_CHAR_DEV_H_
-#define LIBDRV_REMOTE_CHAR_DEV_H_
-
-extern remote_iface_t remote_char_dev_iface;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/lib/drv/generic/remote_audio_pcm.c
===================================================================
--- uspace/lib/drv/generic/remote_audio_pcm.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/drv/generic/remote_audio_pcm.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -221,18 +221,15 @@
  * @param sess Audio device session.
  * @param cap  Audio device capability.
- * @param val  Place to store queried value.
- *
- * @return Error code.
- */
-int audio_pcm_query_cap(audio_pcm_sess_t *sess, audio_cap_t cap)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	sysarg_t value = 0;
+ * @param[out] val  Place to store queried value.
+ *
+ * @return Error code.
+ */
+int audio_pcm_query_cap(audio_pcm_sess_t *sess, audio_cap_t cap, sysarg_t *value)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
 	const int ret = async_req_2_1(exch,
 	    DEV_IFACE_ID(AUDIO_PCM_BUFFER_IFACE), IPC_M_AUDIO_PCM_QUERY_CAPS,
-	    cap, &value);
-	async_exchange_end(exch);
-	if (ret == EOK)
-		return value;
+	    cap, value);
+	async_exchange_end(exch);
 	return ret;
 }
Index: pace/lib/drv/generic/remote_char_dev.c
===================================================================
--- uspace/lib/drv/generic/remote_char_dev.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,246 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libdrv
- * @{
- */
-/** @file
- */
-
-#include <async.h>
-#include <errno.h>
-#include <macros.h>
-
-#include "ops/char_dev.h"
-#include "char_dev_iface.h"
-#include "ddf/driver.h"
-
-#define MAX_CHAR_RW_COUNT 256
-
-/** Read to or write from device.
- *
- * Helper function to read to or write from a device
- * using its character interface.
- *
- * @param sess Session to the device.
- * @param buf  Buffer for the data read from or written to the device.
- * @param size Maximum size of data (in bytes) to be read or written.
- * @param read Read from the device if true, write to it otherwise.
- *
- * @return Non-negative number of bytes actually read from or
- *         written to the device on success, negative error number
- *         otherwise.
- *
- */
-static ssize_t char_dev_rw(async_sess_t *sess, void *buf, size_t size, bool read)
-{
-	ipc_call_t answer;
-	aid_t req;
-	int ret;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	if (read) {
-		req = async_send_1(exch, DEV_IFACE_ID(CHAR_DEV_IFACE),
-		    CHAR_DEV_READ, &answer);
-		ret = async_data_read_start(exch, buf, size);
-	} else {
-		req = async_send_1(exch, DEV_IFACE_ID(CHAR_DEV_IFACE),
-		    CHAR_DEV_WRITE, &answer);
-		ret = async_data_write_start(exch, buf, size);
-	}
-	
-	async_exchange_end(exch);
-	
-	sysarg_t rc;
-	if (ret != EOK) {
-		async_wait_for(req, &rc);
-		if (rc == EOK)
-			return (ssize_t) ret;
-		
-		return (ssize_t) rc;
-	}
-	
-	async_wait_for(req, &rc);
-	
-	ret = (int) rc;
-	if (ret != EOK)
-		return (ssize_t) ret;
-	
-	return (ssize_t) IPC_GET_ARG1(answer);
-}
-
-/** Read from character device.
- *
- * @param sess Session to the device.
- * @param buf  Output buffer for the data read from the device.
- * @param size Maximum size (in bytes) of the data to be read.
- *
- * @return Non-negative number of bytes actually read from the
- *         device on success, negative error number otherwise.
- *
- */
-ssize_t char_dev_read(async_sess_t *sess, void *buf, size_t size)
-{
-	return char_dev_rw(sess, buf, size, true);
-}
-
-/** Write to character device.
- *
- * @param sess Session to the device.
- * @param buf  Input buffer containg the data to be written to the
- *             device.
- * @param size Maximum size (in bytes) of the data to be written.
- *
- * @return Non-negative number of bytes actually written to the
- *         device on success, negative error number otherwise.
- *
- */
-ssize_t char_dev_write(async_sess_t *sess, void *buf, size_t size)
-{
-	return char_dev_rw(sess, buf, size, false);
-}
-
-static void remote_char_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_char_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-
-/** Remote character interface operations. */
-static const remote_iface_func_ptr_t remote_char_dev_iface_ops[] = {
-	[CHAR_DEV_READ] = remote_char_read,
-	[CHAR_DEV_WRITE] = remote_char_write
-};
-
-/** Remote character interface structure.
- *
- * Interface for processing request from remote clients addressed to the
- * character interface.
- */
-const remote_iface_t remote_char_dev_iface = {
-	.method_count = ARRAY_SIZE(remote_char_dev_iface_ops),
-	.methods = remote_char_dev_iface_ops
-};
-
-/** Process the read request from the remote client.
- *
- * Receive the read request's parameters from the remote client and pass them
- * to the local interface. Return the result of the operation processed by the
- * local interface to the remote client.
- *
- * @param fun		The function from which the data are read.
- * @param ops		The local ops structure.
- */
-static void
-remote_char_read(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	char_dev_ops_t *char_dev_ops = (char_dev_ops_t *) ops;
-	ipc_callid_t cid;
-	
-	size_t len;
-	if (!async_data_read_receive(&cid, &len)) {
-		/* TODO handle protocol error. */
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-	
-	if (!char_dev_ops->read) {
-		async_data_read_finalize(cid, NULL, 0);
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-	
-	if (len > MAX_CHAR_RW_COUNT)
-		len = MAX_CHAR_RW_COUNT;
-	
-	char buf[MAX_CHAR_RW_COUNT];
-	int ret = (*char_dev_ops->read)(fun, buf, len);
-	
-	if (ret < 0) {
-		/* Some error occured. */
-		async_data_read_finalize(cid, buf, 0);
-		async_answer_0(callid, ret);
-		return;
-	}
-	
-	/* The operation was successful, return the number of data read. */
-	async_data_read_finalize(cid, buf, ret);
-	async_answer_1(callid, EOK, ret);
-}
-
-/** Process the write request from the remote client.
- *
- * Receive the write request's parameters from the remote client and pass them
- * to the local interface. Return the result of the operation processed by the
- * local interface to the remote client.
- *
- * @param fun		The function to which the data are written.
- * @param ops		The local ops structure.
- */
-static void
-remote_char_write(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	char_dev_ops_t *char_dev_ops = (char_dev_ops_t *) ops;
-	ipc_callid_t cid;
-	size_t len;
-	
-	if (!async_data_write_receive(&cid, &len)) {
-		/* TODO handle protocol error. */
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-	
-	if (!char_dev_ops->write) {
-		async_data_write_finalize(cid, NULL, 0);
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-	
-	if (len > MAX_CHAR_RW_COUNT)
-		len = MAX_CHAR_RW_COUNT;
-	
-	char buf[MAX_CHAR_RW_COUNT];
-	
-	async_data_write_finalize(cid, buf, len);
-	
-	int ret = (*char_dev_ops->write)(fun, buf, len);
-	if (ret < 0) {
-		/* Some error occured. */
-		async_answer_0(callid, ret);
-	} else {
-		/*
-		 * The operation was successful, return the number of data
-		 * written.
-		 */
-		async_answer_1(callid, EOK, ret);
-	}
-}
-
-/**
- * @}
- */
Index: uspace/lib/drv/include/audio_pcm_iface.h
===================================================================
--- uspace/lib/drv/include/audio_pcm_iface.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/drv/include/audio_pcm_iface.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -83,5 +83,5 @@
 int audio_pcm_test_format(audio_pcm_sess_t *, unsigned *, unsigned *,
     pcm_sample_format_t *);
-int audio_pcm_query_cap(audio_pcm_sess_t *, audio_cap_t);
+int audio_pcm_query_cap(audio_pcm_sess_t *, audio_cap_t, sysarg_t *);
 int audio_pcm_register_event_callback(audio_pcm_sess_t *,
     async_port_handler_t, void *);
Index: pace/lib/drv/include/char_dev_iface.h
===================================================================
--- uspace/lib/drv/include/char_dev_iface.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBDRV_CHAR_DEV_IFACE_H_
-#define LIBDRV_CHAR_DEV_IFACE_H_
-
-#include <async.h>
-
-typedef enum {
-	CHAR_DEV_READ = 0,
-	CHAR_DEV_WRITE
-} char_dev_method_t;
-
-extern ssize_t char_dev_read(async_sess_t *, void *, size_t);
-extern ssize_t char_dev_write(async_sess_t *, void *, size_t);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/drv/include/ddf/interrupt.h
===================================================================
--- uspace/lib/drv/include/ddf/interrupt.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/drv/include/ddf/interrupt.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -48,8 +48,8 @@
  */
 
-typedef void interrupt_handler_t(ipc_callid_t, ipc_call_t *, ddf_dev_t *);
+typedef void interrupt_handler_t(ipc_call_t *, ddf_dev_t *);
 
 extern int register_interrupt_handler(ddf_dev_t *, int, interrupt_handler_t *,
-    const irq_code_t *);
+    const irq_code_t *, cap_handle_t *);
 extern int unregister_interrupt_handler(ddf_dev_t *, int);
 
Index: pace/lib/drv/include/ops/char_dev.h
===================================================================
--- uspace/lib/drv/include/ops/char_dev.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,49 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libdrv
- * @{
- */
-/** @file
- */
-
-#ifndef LIBDRV_OPS_CHAR_DEV_H_
-#define LIBDRV_OPS_CHAR_DEV_H_
-
-#include "../ddf/driver.h"
-
-typedef struct {
-	int (*read)(ddf_fun_t *, char *, size_t);
-	int (*write)(ddf_fun_t *, char *, size_t);
-} char_dev_ops_t;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/lib/ext4/src/directory.c
===================================================================
--- uspace/lib/ext4/src/directory.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/ext4/src/directory.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,6 +38,6 @@
 #include <byteorder.h>
 #include <errno.h>
-#include <malloc.h>
 #include <mem.h>
+#include <stdlib.h>
 #include <str.h>
 #include "ext4/directory.h"
Index: uspace/lib/ext4/src/extent.c
===================================================================
--- uspace/lib/ext4/src/extent.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/ext4/src/extent.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,6 +37,6 @@
 #include <byteorder.h>
 #include <errno.h>
-#include <malloc.h>
 #include <mem.h>
+#include <stdlib.h>
 #include "ext4/balloc.h"
 #include "ext4/extent.h"
Index: uspace/lib/ext4/src/ops.c
===================================================================
--- uspace/lib/ext4/src/ops.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/ext4/src/ops.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -42,6 +42,6 @@
 #include <libfs.h>
 #include <macros.h>
-#include <malloc.h>
 #include <mem.h>
+#include <stdlib.h>
 #include <str.h>
 #include <ipc/loc.h>
Index: uspace/lib/ext4/src/superblock.c
===================================================================
--- uspace/lib/ext4/src/superblock.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/ext4/src/superblock.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,6 +40,6 @@
 #include <byteorder.h>
 #include <errno.h>
-#include <malloc.h>
 #include <mem.h>
+#include <stdlib.h>
 #include "ext4/superblock.h"
 
Index: uspace/lib/fmtutil/fmtutil.c
===================================================================
--- uspace/lib/fmtutil/fmtutil.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/fmtutil/fmtutil.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -29,6 +29,6 @@
 #include <io/console.h>
 #include <errno.h>
-#include <malloc.h>
 #include <fmtutil.h>
+#include <stdlib.h>
 
 typedef struct {
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/fs/libfs.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -656,5 +656,5 @@
 		if (rc == EOK) {
 			aoff64_t size = ops->size_get(cur);
-			async_answer_5(rid, fs_handle, service_id,
+			async_answer_5(rid, EOK, fs_handle,
 			    ops->index_get(cur),
 			    (ops->is_directory(cur) << 16) | last,
@@ -699,5 +699,5 @@
 out1:
 	if (!cur) {
-		async_answer_5(rid, fs_handle, service_id, ops->index_get(par),
+		async_answer_5(rid, EOK, fs_handle, ops->index_get(par),
 		    (ops->is_directory(par) << 16) | last_next,
 		    LOWER32(ops->size_get(par)), UPPER32(ops->size_get(par)));
@@ -705,5 +705,5 @@
 	}
 	
-	async_answer_5(rid, fs_handle, service_id, ops->index_get(cur),
+	async_answer_5(rid, EOK, fs_handle, ops->index_get(cur),
 	    (ops->is_directory(cur) << 16) | last, LOWER32(ops->size_get(cur)),
 	    UPPER32(ops->size_get(cur)));
Index: uspace/lib/graph/graph.c
===================================================================
--- uspace/lib/graph/graph.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/graph/graph.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,6 +38,6 @@
 #include <inttypes.h>
 #include <stdio.h>
-#include <malloc.h>
 #include <as.h>
+#include <stdlib.h>
 #include "graph.h"
 
Index: uspace/lib/gui/button.c
===================================================================
--- uspace/lib/gui/button.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/gui/button.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,5 +35,5 @@
 
 #include <str.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <drawctx.h>
 #include <surface.h>
Index: uspace/lib/gui/canvas.c
===================================================================
--- uspace/lib/gui/canvas.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/gui/canvas.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -34,5 +34,5 @@
  */
 
-#include <malloc.h>
+#include <stdlib.h>
 #include <transform.h>
 #include <source.h>
Index: uspace/lib/gui/connection.c
===================================================================
--- uspace/lib/gui/connection.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/gui/connection.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,5 +35,5 @@
 
 #include <mem.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <adt/list.h>
 #include <adt/prodcons.h>
Index: uspace/lib/gui/grid.c
===================================================================
--- uspace/lib/gui/grid.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/gui/grid.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,5 +37,5 @@
 #include <assert.h>
 #include <mem.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <surface.h>
 #include "window.h"
Index: uspace/lib/gui/label.c
===================================================================
--- uspace/lib/gui/label.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/gui/label.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,6 +35,6 @@
 
 #include <str.h>
-#include <malloc.h>
 #include <drawctx.h>
+#include <stdlib.h>
 #include <surface.h>
 #include <font/embedded.h>
Index: uspace/lib/gui/minimal.c
===================================================================
--- uspace/lib/gui/minimal.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/gui/minimal.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -34,5 +34,5 @@
  */
 
-#include <malloc.h>
+#include <stdlib.h>
 #include <surface.h>
 
Index: uspace/lib/gui/terminal.c
===================================================================
--- uspace/lib/gui/terminal.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/gui/terminal.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,5 +35,5 @@
 
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <io/chargrid.h>
 #include <surface.h>
@@ -64,6 +64,6 @@
 static int term_open(con_srvs_t *, con_srv_t *);
 static int term_close(con_srv_t *);
-static int term_read(con_srv_t *, void *, size_t);
-static int term_write(con_srv_t *, void *, size_t);
+static int term_read(con_srv_t *, void *, size_t, size_t *);
+static int term_write(con_srv_t *, void *, size_t, size_t *);
 static void term_sync(con_srv_t *);
 static void term_clear(con_srv_t *);
@@ -386,5 +386,5 @@
 }
 
-static int term_read(con_srv_t *srv, void *buf, size_t size)
+static int term_read(con_srv_t *srv, void *buf, size_t size, size_t *nread)
 {
 	terminal_t *term = srv_to_terminal(srv);
@@ -431,5 +431,6 @@
 	}
 	
-	return size;
+	*nread = size;
+	return EOK;
 }
 
@@ -462,5 +463,5 @@
 }
 
-static int term_write(con_srv_t *srv, void *data, size_t size)
+static int term_write(con_srv_t *srv, void *data, size_t size, size_t *nwritten)
 {
 	terminal_t *term = srv_to_terminal(srv);
@@ -470,5 +471,6 @@
 		term_write_char(term, str_decode(data, &off, size));
 	
-	return size;
+	*nwritten = size;
+	return EOK;
 }
 
Index: uspace/lib/gui/window.c
===================================================================
--- uspace/lib/gui/window.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/gui/window.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,5 +40,5 @@
 
 #include <as.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <str.h>
 
Index: uspace/lib/hound/include/hound/protocol.h
===================================================================
--- uspace/lib/hound/include/hound/protocol.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/hound/include/hound/protocol.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -58,19 +58,9 @@
 typedef intptr_t hound_context_id_t;
 
-/**
- * Check context id for errors.
- * @param id Context id
- * @return Error code.
- */
-static inline int hound_context_id_err(hound_context_id_t id)
-{
-	return id > 0 ? EOK : (id == 0 ? ENOENT : id);
-}
-
 hound_sess_t *hound_service_connect(const char *service);
 void hound_service_disconnect(hound_sess_t *sess);
 
-hound_context_id_t hound_service_register_context(hound_sess_t *sess,
-    const char *name, bool record);
+int hound_service_register_context(hound_sess_t *sess,
+    const char *name, bool record, hound_context_id_t *id);
 int hound_service_unregister_context(hound_sess_t *sess, hound_context_id_t id);
 
Index: uspace/lib/hound/src/client.c
===================================================================
--- uspace/lib/hound/src/client.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/hound/src/client.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -123,7 +123,8 @@
 			return NULL;
 		}
-		new_context->id = hound_service_register_context(
-		    new_context->session, new_context->name, record);
-		if (hound_context_id_err(new_context->id) != EOK) {
+		int rc = hound_service_register_context(
+		    new_context->session, new_context->name, record,
+		    &new_context->id);
+		if (rc != EOK) {
 			hound_service_disconnect(new_context->session);
 			free(new_context->name);
Index: uspace/lib/hound/src/protocol.c
===================================================================
--- uspace/lib/hound/src/protocol.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/hound/src/protocol.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -115,8 +115,11 @@
  * @param name Valid string identifier
  * @param record True if the application context wishes to receive data.
- * @return Valid ID on success, Error code on failure.
- */
-hound_context_id_t hound_service_register_context(hound_sess_t *sess,
-    const char *name, bool record)
+ *
+ * @param[out] id  Return context ID.
+ *
+ * @return EOK on success, Error code on failure.
+ */
+int hound_service_register_context(hound_sess_t *sess,
+    const char *name, bool record, hound_context_id_t *id)
 {
 	assert(sess);
@@ -126,5 +129,5 @@
 	aid_t mid =
 	    async_send_1(exch, IPC_M_HOUND_CONTEXT_REGISTER, record, &call);
-	int ret = mid ? EOK : EPARTY;
+	sysarg_t ret = mid ? EOK : EPARTY;
 
 	if (ret == EOK)
@@ -134,8 +137,12 @@
 
 	if (ret == EOK)
-		async_wait_for(mid, (sysarg_t *)&ret);
+		async_wait_for(mid, &ret);
 
 	async_exchange_end(exch);
-	return ret == EOK ? (hound_context_id_t)IPC_GET_ARG1(call) : ret;
+	if (ret == EOK) {
+		*id = (hound_context_id_t)IPC_GET_ARG1(call);
+	}
+
+	return ret;
 }
 
@@ -182,7 +189,7 @@
 	ipc_call_t res_call;
 	aid_t mid = async_send_3(exch, IPC_M_HOUND_GET_LIST, flags, *count,
-	    (bool)connection, &res_call);
-
-	int ret = EOK;
+	    connection != NULL, &res_call);
+
+	sysarg_t ret = EOK;
 	if (mid && connection)
 		ret = async_data_write_start(exch, connection,
@@ -190,5 +197,5 @@
 
 	if (ret == EOK)
-		async_wait_for(mid, (sysarg_t*)&ret);
+		async_wait_for(mid, &ret);
 
 	if (ret != EOK) {
@@ -252,10 +259,10 @@
 	ipc_call_t call;
 	aid_t id = async_send_0(exch, IPC_M_HOUND_CONNECT, &call);
-	int ret = id ? EOK : EPARTY;
+	sysarg_t ret = id ? EOK : EPARTY;
 	if (ret == EOK)
 		ret = async_data_write_start(exch, source, str_size(source));
 	if (ret == EOK)
 		ret = async_data_write_start(exch, sink, str_size(sink));
-	async_wait_for(id, (sysarg_t*)&ret);
+	async_wait_for(id, &ret);
 	async_exchange_end(exch);
 	return ret;
@@ -278,10 +285,10 @@
 	ipc_call_t call;
 	aid_t id = async_send_0(exch, IPC_M_HOUND_DISCONNECT, &call);
-	int ret = id ? EOK : EPARTY;
+	sysarg_t ret = id ? EOK : EPARTY;
 	if (ret == EOK)
 		ret = async_data_write_start(exch, source, str_size(source));
 	if (ret == EOK)
 		ret = async_data_write_start(exch, sink, str_size(sink));
-	async_wait_for(id, (sysarg_t*)&ret);
+	async_wait_for(id, &ret);
 	async_exchange_end(exch);
 	return ENOTSUP;
Index: uspace/lib/http/include/http/receive-buffer.h
===================================================================
--- uspace/lib/http/include/http/receive-buffer.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/http/include/http/receive-buffer.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -46,7 +46,8 @@
  * @param buf buffer to store the data
  * @param buf_size buffer size
- * @return number of bytes received or negative error code
+ * @param nrecv number of bytes actually received
+ * @return EOK on success or error code
  */
-typedef ssize_t (*receive_func_t)(void *, void *, size_t);
+typedef int (*receive_func_t)(void *, void *, size_t, size_t *);
 
 typedef struct {
@@ -81,10 +82,10 @@
     receive_buffer_mark_t *, char **);
 extern int recv_char(receive_buffer_t *, char *, bool);
-extern ssize_t recv_buffer(receive_buffer_t *, char *, size_t);
-extern ssize_t recv_discard(receive_buffer_t *, char);
-extern ssize_t recv_discard_str(receive_buffer_t *, const char *);
-extern ssize_t recv_while(receive_buffer_t *, char_class_func_t);
-extern ssize_t recv_eol(receive_buffer_t *);
-extern ssize_t recv_line(receive_buffer_t *, char *, size_t);
+extern int recv_buffer(receive_buffer_t *, char *, size_t, size_t *);
+extern int recv_discard(receive_buffer_t *, char, size_t *);
+extern int recv_discard_str(receive_buffer_t *, const char *, size_t *);
+extern int recv_while(receive_buffer_t *, char_class_func_t);
+extern int recv_eol(receive_buffer_t *, size_t *);
+extern int recv_line(receive_buffer_t *, char *, size_t, size_t *);
 
 #endif
Index: uspace/lib/http/src/headers.c
===================================================================
--- uspace/lib/http/src/headers.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/http/src/headers.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -146,6 +146,7 @@
 			continue;
 		
-		rc = recv_discard(rb, (c == '\r' ? '\n' : '\r'));
-		if (rc < 0)
+		size_t nrecv;
+		rc = recv_discard(rb, (c == '\r' ? '\n' : '\r'), &nrecv);
+		if (rc != EOK)
 			return rc;
 		
Index: uspace/lib/http/src/http.c
===================================================================
--- uspace/lib/http/src/http.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/http/src/http.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -47,15 +47,10 @@
 #include <http/receive-buffer.h>
 
-static ssize_t http_receive(void *client_data, void *buf, size_t buf_size)
+static int http_receive(void *client_data, void *buf, size_t buf_size,
+    size_t *nrecv)
 {
 	http_t *http = client_data;
-	size_t nrecv;
-	int rc;
 
-	rc = tcp_conn_recv_wait(http->conn, buf, buf_size, &nrecv);
-	if (rc != EOK)
-		return rc;
-
-	return nrecv;
+	return tcp_conn_recv_wait(http->conn, buf, buf_size, nrecv);
 }
 
Index: uspace/lib/http/src/receive-buffer.c
===================================================================
--- uspace/lib/http/src/receive-buffer.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/http/src/receive-buffer.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -61,7 +61,9 @@
 }
 
-static ssize_t dummy_receive(void *unused, void *buf, size_t buf_size)
-{
-	return 0;
+static int dummy_receive(void *unused, void *buf, size_t buf_size,
+    size_t *nrecv)
+{
+	*nrecv = 0;
+	return EOK;
 }
 
@@ -167,9 +169,10 @@
 		}
 		
-		ssize_t rc = rb->receive(rb->client_data, rb->buffer + rb->in, free);
-		if (rc <= 0)
+		size_t nrecv;
+		int rc = rb->receive(rb->client_data, rb->buffer + rb->in, free, &nrecv);
+		if (rc != EOK)
 			return rc;
 		
-		rb->in = rc;
+		rb->in = nrecv;
 	}
 	
@@ -180,21 +183,24 @@
 }
 
-ssize_t recv_buffer(receive_buffer_t *rb, char *buf, size_t buf_size)
-{
-	/* Flush any buffered data*/
+int recv_buffer(receive_buffer_t *rb, char *buf, size_t buf_size,
+    size_t *nrecv)
+{
+	/* Flush any buffered data */
 	if (rb->out != rb->in) {
 		size_t size = min(rb->in - rb->out, buf_size);
 		memcpy(buf, rb->buffer + rb->out, size);
 		rb->out += size;
-		return size;
-	}
-	
-	return rb->receive(rb->client_data, buf, buf_size);
+		*nrecv = size;
+		return EOK;
+	}
+	
+	return rb->receive(rb->client_data, buf, buf_size, nrecv);
 }
 
 /** Receive a character and if it is c, discard it from input buffer
- * @return number of characters discarded (0 or 1) or negative error code
- */
-ssize_t recv_discard(receive_buffer_t *rb, char discard)
+ * @param ndisc Place to store number of characters discarded
+ * @return EOK or error code
+ */
+int recv_discard(receive_buffer_t *rb, char discard, size_t *ndisc)
 {
 	char c = 0;
@@ -202,34 +208,39 @@
 	if (rc != EOK)
 		return rc;
-	if (c != discard)
-		return 0;
+	if (c != discard) {
+		*ndisc = 0;
+		return EOK;
+	}
 	rc = recv_char(rb, &c, true);
 	if (rc != EOK)
 		return rc;
-	return 1;
+	*ndisc = 1;
+	return EOK;
 }
 
 /** Receive a prefix of constant string discard and return number of bytes read
- * @return number of characters discarded or negative error code
- */
-ssize_t recv_discard_str(receive_buffer_t *rb, const char *discard)
+ * @param ndisc Place to store number of characters discarded
+ * @return EOK or error code
+ */
+int recv_discard_str(receive_buffer_t *rb, const char *discard, size_t *ndisc)
 {
 	size_t discarded = 0;
 	while (*discard) {
-		ssize_t rc = recv_discard(rb, *discard);
-		if (rc < 0)
-			return rc;
-		if (rc == 0)
+		size_t nd;
+		int rc = recv_discard(rb, *discard, &nd);
+		if (rc != EOK)
+			return rc;
+		if (nd == 0)
 			break;
-		discarded++;
+		discarded += nd;
 		discard++;
 	}
-	return discarded;
-}
-
-ssize_t recv_while(receive_buffer_t *rb, char_class_func_t class)
-{
-	size_t received = 0;
-	
+
+	*ndisc = discarded;
+	return EOK;
+}
+
+int recv_while(receive_buffer_t *rb, char_class_func_t class)
+{
 	while (true) {
 		char c = 0;
@@ -244,17 +255,16 @@
 		if (rc != EOK)
 			return rc;
-		
-		received++;
-	}
-	
-	return received;
+	}
+	
+	return EOK;
 }
 
 /** Receive an end of line, either CR, LF, CRLF or LFCR
  *
- * @return number of bytes read (0 if no newline is present in the stream)
- *         or negative error code
- */
-ssize_t recv_eol(receive_buffer_t *rb)
+ * @param nrecv Place to store number of bytes received (zero if
+ *              no newline is present in the stream)
+ * @return EOK on success or error code
+ */
+int recv_eol(receive_buffer_t *rb, size_t *nrecv)
 {
 	char c = 0;
@@ -263,6 +273,8 @@
 		return rc;
 	
-	if (c != '\r' && c != '\n')
-		return 0;
+	if (c != '\r' && c != '\n') {
+		*nrecv = 0;
+		return EOK;
+	}
 	
 	rc = recv_char(rb, &c, true);
@@ -270,15 +282,18 @@
 		return rc;
 	
-	ssize_t rc2 = recv_discard(rb, (c == '\r' ? '\n' : '\r'));
-	if (rc2 < 0)
-		return rc2;
-	
-	return 1 + rc2;
+	size_t nr;
+	rc = recv_discard(rb, (c == '\r' ? '\n' : '\r'), &nr);
+	if (rc != EOK)
+		return rc;
+	
+	*nrecv = 1 + nr;
+	return EOK;
 }
 
 /* Receive a single line */
-ssize_t recv_line(receive_buffer_t *rb, char *line, size_t size)
+int recv_line(receive_buffer_t *rb, char *line, size_t size, size_t *nrecv)
 {
 	size_t written = 0;
+	size_t nr;
 	
 	while (written < size) {
@@ -288,12 +303,19 @@
 			return rc;
 		if (c == '\n') {
-			recv_discard(rb, '\r');
+			rc = recv_discard(rb, '\r', &nr);
+			if (rc != EOK)
+				return rc;
+
 			line[written++] = 0;
-			return written;
+			*nrecv = written;
+			return EOK;
 		}
 		else if (c == '\r') {
-			recv_discard(rb, '\n');
+			rc = recv_discard(rb, '\n', &nr);
+			if (rc != EOK)
+				return rc;
 			line[written++] = 0;
-			return written;
+			*nrecv = written;
+			return EOK;
 		}
 		line[written++] = c;
Index: uspace/lib/http/src/response.c
===================================================================
--- uspace/lib/http/src/response.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/http/src/response.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -96,8 +96,9 @@
 static int expect(receive_buffer_t *rb, const char *expect)
 {
-	int rc = recv_discard_str(rb, expect);
-	if (rc < 0)
-		return rc;
-	if ((size_t) rc < str_length(expect))
+	size_t ndisc;
+	int rc = recv_discard_str(rb, expect, &ndisc);
+	if (rc != EOK)
+		return rc;
+	if (ndisc < str_length(expect))
 		return HTTP_EPARSE;
 	return EOK;
@@ -168,8 +169,9 @@
 	recv_unmark(rb, &msg_end);
 	
-	rc = recv_eol(rb);
-	if (rc == 0)
+	size_t nrecv;
+	rc = recv_eol(rb, &nrecv);
+	if (rc == EOK && nrecv == 0)
 		rc = HTTP_EPARSE;
-	if (rc < 0) {
+	if (rc != EOK) {
 		free(message);
 		return rc;
@@ -204,8 +206,9 @@
 		goto error;
 	
-	rc = recv_eol(rb);
-	if (rc == 0)
+	size_t nrecv;
+	rc = recv_eol(rb, &nrecv);
+	if (rc == EOK && nrecv == 0)
 		rc = HTTP_EPARSE;
-	if (rc < 0)
+	if (rc != EOK)
 		goto error;
 	
Index: uspace/lib/pcut/helenos.mak
===================================================================
--- uspace/lib/pcut/helenos.mak	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/helenos.mak	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,3 +39,4 @@
 
 EXTRA_CFLAGS = -D__helenos__
+
 LIBRARY = libpcut
Index: uspace/lib/pcut/include/pcut/pcut.h
===================================================================
--- uspace/lib/pcut/include/pcut/pcut.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/include/pcut/pcut.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,3 +36,17 @@
 #include <pcut/tests.h>
 
+
+/** PCUT outcome: test passed. */
+#define PCUT_OUTCOME_PASS 0
+
+/** PCUT outcome: test failed. */
+#define PCUT_OUTCOME_FAIL 1
+
+/** PCUT outcome: test failed unexpectedly. */
+#define PCUT_OUTCOME_INTERNAL_ERROR 2
+
+/** PCUT outcome: invalid invocation of the final program. */
+#define PCUT_OUTCOME_BAD_INVOCATION 3
+
+
 #endif
Index: uspace/lib/pcut/src/assert.c
===================================================================
--- uspace/lib/pcut/src/assert.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/assert.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,6 +35,10 @@
  */
 
-/** We need _BSD_SOURCE because of vsnprintf() when compiling under C89. */
+/*
+ * We need _BSD_SOURCE because of vsnprintf() when compiling under C89.
+ * In newer versions of features.h, _DEFAULT_SOURCE must be defined as well.
+ */
 #define _BSD_SOURCE
+#define _DEFAULT_SOURCE
 
 #include "internal.h"
Index: uspace/lib/pcut/src/internal.h
===================================================================
--- uspace/lib/pcut/src/internal.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/internal.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -79,14 +79,4 @@
 #define PCUT_RUN_MODE_SINGLE 2
 
-/** Test outcome: test passed. */
-#define TEST_OUTCOME_PASS 1
-
-/** Test outcome: test failed. */
-#define TEST_OUTCOME_FAIL 2
-
-/** Test outcome: test failed unexpectedly. */
-#define TEST_OUTCOME_ERROR 3
-
-
 /*
  * Use sprintf_s in Windows but only with Microsoft compiler.
@@ -109,5 +99,5 @@
 int pcut_is_arg_with_number(const char *arg, const char *opt, int *value);
 
-void pcut_run_test_forking(const char *self_path, pcut_item_t *test);
+int pcut_run_test_forking(const char *self_path, pcut_item_t *test);
 int pcut_run_test_forked(pcut_item_t *test);
 int pcut_run_test_single(pcut_item_t *test);
Index: uspace/lib/pcut/src/main.c
===================================================================
--- uspace/lib/pcut/src/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -90,8 +90,11 @@
  * @param last Pointer to first item after this suite is stored here.
  * @param prog_path Path to the current binary (used in forked mode).
- */
-static void run_suite(pcut_item_t *suite, pcut_item_t **last, const char *prog_path) {
+ * @return Error code.
+ */
+static int run_suite(pcut_item_t *suite, pcut_item_t **last, const char *prog_path) {
 	int is_first_test = 1;
 	int total_count = 0;
+	int ret_code = PCUT_OUTCOME_PASS;
+	int ret_code_tmp;
 
 	pcut_item_t *it = pcut_get_real_next(suite);
@@ -114,8 +117,19 @@
 
 		if (pcut_run_mode == PCUT_RUN_MODE_FORKING) {
-			pcut_run_test_forking(prog_path, it);
+			ret_code_tmp = pcut_run_test_forking(prog_path, it);
 		} else {
-			pcut_run_test_single(it);
-		}
+			ret_code_tmp = pcut_run_test_single(it);
+		}
+
+		/*
+		 * Override final return code in case of failure.
+		 *
+		 * In this case we suppress any special error codes as
+		 * to the outside, there was a failure.
+		 */
+		if (ret_code_tmp != PCUT_OUTCOME_PASS) {
+			ret_code = PCUT_OUTCOME_FAIL;
+		}
+
 		total_count++;
 	}
@@ -130,4 +144,6 @@
 		*last = it;
 	}
+
+	return ret_code;
 }
 
@@ -181,4 +197,6 @@
 	int run_only_test = -1;
 
+	int rc, rc_tmp;
+
 	if (main_extras == NULL) {
 		main_extras = empty_main_extra;
@@ -203,5 +221,5 @@
 			if (pcut_str_equals(argv[i], "-l")) {
 				pcut_print_tests(items);
-				return 0;
+				return PCUT_OUTCOME_PASS;
 			}
 			if (pcut_str_equals(argv[i], "-x")) {
@@ -229,5 +247,5 @@
 	if ((run_only_suite >= 0) && (run_only_test >= 0)) {
 		printf("Specify either -s or -t!\n");
-		return 1;
+		return PCUT_OUTCOME_BAD_INVOCATION;
 	}
 
@@ -236,25 +254,24 @@
 		if (suite == NULL) {
 			printf("Suite not found, aborting!\n");
-			return 2;
+			return PCUT_OUTCOME_BAD_INVOCATION;
 		}
 		if (suite->kind != PCUT_KIND_TESTSUITE) {
 			printf("Invalid suite id!\n");
-			return 3;
+			return PCUT_OUTCOME_BAD_INVOCATION;
 		}
 
 		run_suite(suite, NULL, argv[0]);
-		return 0;
+		return PCUT_OUTCOME_PASS;
 	}
 
 	if (run_only_test > 0) {
-		int rc;
 		pcut_item_t *test = pcut_find_by_id(items, run_only_test);
 		if (test == NULL) {
 			printf("Test not found, aborting!\n");
-			return 2;
+			return PCUT_OUTCOME_BAD_INVOCATION;
 		}
 		if (test->kind != PCUT_KIND_TEST) {
 			printf("Invalid test id!\n");
-			return 3;
+			return PCUT_OUTCOME_BAD_INVOCATION;
 		}
 
@@ -271,9 +288,14 @@
 	pcut_report_init(items);
 
+	rc = PCUT_OUTCOME_PASS;
+
 	it = items;
 	while (it != NULL) {
 		if (it->kind == PCUT_KIND_TESTSUITE) {
 			pcut_item_t *tmp;
-			run_suite(it, &tmp, argv[0]);
+			rc_tmp = run_suite(it, &tmp, argv[0]);
+			if (rc_tmp != PCUT_OUTCOME_PASS) {
+				rc = rc_tmp;
+			}
 			it = tmp;
 		} else {
@@ -284,4 +306,4 @@
 	pcut_report_done();
 
-	return 0;
-}
+	return rc;
+}
Index: uspace/lib/pcut/src/os/generic.c
===================================================================
--- uspace/lib/pcut/src/os/generic.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/os/generic.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -34,4 +34,5 @@
 #include <stdlib.h>
 #include <stdio.h>
+#include <sys/types.h>
 #include <errno.h>
 #include <assert.h>
@@ -94,9 +95,9 @@
 static int convert_wait_status_to_outcome(int status) {
 	if (status < 0) {
-		return TEST_OUTCOME_ERROR;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	} else if (status == 0) {
-		return TEST_OUTCOME_PASS;
+		return PCUT_OUTCOME_PASS;
 	} else {
-		return TEST_OUTCOME_FAIL;
+		return PCUT_OUTCOME_FAIL;
 	}
 }
@@ -107,6 +108,6 @@
  * @param test Test to be run.
  */
-void pcut_run_test_forking(const char *self_path, pcut_item_t *test) {
-	int rc;
+int pcut_run_test_forking(const char *self_path, pcut_item_t *test) {
+	int rc, outcome;
 	FILE *tempfile;
 	char tempfile_name[PCUT_TEMP_FILENAME_BUFFER_SIZE];
@@ -126,17 +127,19 @@
 	PCUT_DEBUG("system() returned 0x%04X", rc);
 
-	rc = convert_wait_status_to_outcome(rc);
+	outcome = convert_wait_status_to_outcome(rc);
 
 	tempfile = fopen(tempfile_name, "rb");
 	if (tempfile == NULL) {
 		pcut_report_test_done(test, TEST_OUTCOME_ERROR, "Failed to open temporary file.", NULL, NULL);
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
 	fread(extra_output_buffer, 1, OUTPUT_BUFFER_SIZE, tempfile);
 	fclose(tempfile);
-	unlink(tempfile_name);
+	remove(tempfile_name);
 
-	pcut_report_test_done_unparsed(test, rc, extra_output_buffer, OUTPUT_BUFFER_SIZE);
+	pcut_report_test_done_unparsed(test, outcome, extra_output_buffer, OUTPUT_BUFFER_SIZE);
+
+	return outcome;
 }
 
Index: uspace/lib/pcut/src/os/helenos.c
===================================================================
--- uspace/lib/pcut/src/os/helenos.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/os/helenos.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -154,13 +154,14 @@
  * @param test Test to be run.
  */
-void pcut_run_test_forking(const char *self_path, pcut_item_t *test) {
+int pcut_run_test_forking(const char *self_path, pcut_item_t *test) {
 	before_test_start(test);
 
 	char tempfile_name[PCUT_TEMP_FILENAME_BUFFER_SIZE];
 	snprintf(tempfile_name, PCUT_TEMP_FILENAME_BUFFER_SIZE - 1, "pcut_%lld.tmp", (unsigned long long) task_get_id());
-	int tempfile = vfs_lookup_open(tempfile_name, WALK_REGULAR | WALK_MAY_CREATE, MODE_READ | MODE_WRITE);
-	if (tempfile < 0) {
-		pcut_report_test_done(test, TEST_OUTCOME_ERROR, "Failed to create temporary file.", NULL, NULL);
-		return;
+	int tempfile;
+	int rc = vfs_lookup_open(tempfile_name, WALK_REGULAR | WALK_MAY_CREATE, MODE_READ | MODE_WRITE, &tempfile);
+	if (rc != EOK) {
+		pcut_report_test_done(test, PCUT_OUTCOME_INTERNAL_ERROR, "Failed to create temporary file.", NULL, NULL);
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -174,11 +175,11 @@
 	};
 
-	int status = TEST_OUTCOME_PASS;
+	int status = PCUT_OUTCOME_PASS;
 
 	task_wait_t test_task_wait;
-	int rc = task_spawnvf(&test_task_id, &test_task_wait, self_path, arguments,
+	rc = task_spawnvf(&test_task_id, &test_task_wait, self_path, arguments,
 	    fileno(stdin), tempfile, tempfile);
 	if (rc != EOK) {
-		status = TEST_OUTCOME_ERROR;
+		status = PCUT_OUTCOME_INTERNAL_ERROR;
 		goto leave_close_tempfile;
 	}
@@ -198,11 +199,11 @@
 	rc = task_wait(&test_task_wait, &task_exit, &task_retval);
 	if (rc != EOK) {
-		status = TEST_OUTCOME_ERROR;
+		status = PCUT_OUTCOME_INTERNAL_ERROR;
 		goto leave_close_tempfile;
 	}
 	if (task_exit == TASK_EXIT_UNEXPECTED) {
-		status = TEST_OUTCOME_ERROR;
+		status = PCUT_OUTCOME_INTERNAL_ERROR;
 	} else {
-		status = task_retval == 0 ? TEST_OUTCOME_PASS : TEST_OUTCOME_FAIL;
+		status = task_retval == 0 ? PCUT_OUTCOME_PASS : PCUT_OUTCOME_FAIL;
 	}
 
@@ -213,5 +214,6 @@
 
 	aoff64_t pos = 0;
-	vfs_read(tempfile, &pos, extra_output_buffer, OUTPUT_BUFFER_SIZE);
+	size_t nread;
+	vfs_read(tempfile, &pos, extra_output_buffer, OUTPUT_BUFFER_SIZE, &nread);
 
 leave_close_tempfile:
@@ -220,4 +222,6 @@
 
 	pcut_report_test_done_unparsed(test, status, extra_output_buffer, OUTPUT_BUFFER_SIZE);
+
+	return status;
 }
 
Index: uspace/lib/pcut/src/os/unix.c
===================================================================
--- uspace/lib/pcut/src/os/unix.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/os/unix.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,7 +36,11 @@
 /** We need _BSD_SOURCE because of snprintf() when compiling under C89. */
 #define _BSD_SOURCE
+
+/** Newer versions of features.h needs _DEFAULT_SOURCE. */
+#define _DEFAULT_SOURCE
+
 #include <stdlib.h>
 #include <unistd.h>
-#include <stddef.h>
+#include <sys/types.h>
 #include <signal.h>
 #include <errno.h>
@@ -120,12 +124,12 @@
 	if (WIFEXITED(status)) {
 		if (WEXITSTATUS(status) != 0) {
-			return TEST_OUTCOME_FAIL;
+			return PCUT_OUTCOME_FAIL;
 		} else {
-			return TEST_OUTCOME_PASS;
+			return PCUT_OUTCOME_PASS;
 		}
 	}
 
 	if (WIFSIGNALED(status)) {
-		return TEST_OUTCOME_ERROR;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -138,7 +142,7 @@
  * @param test Test to be run.
  */
-void pcut_run_test_forking(const char *self_path, pcut_item_t *test) {
+int pcut_run_test_forking(const char *self_path, pcut_item_t *test) {
 	int link_stdout[2], link_stderr[2];
-	int rc, status;
+	int rc, status, outcome;
 	size_t stderr_size;
 
@@ -152,6 +156,6 @@
 		snprintf(error_message_buffer, OUTPUT_BUFFER_SIZE - 1,
 				"pipe() failed: %s.", strerror(rc));
-		pcut_report_test_done(test, TEST_OUTCOME_ERROR, error_message_buffer, NULL, NULL);
-		return;
+		pcut_report_test_done(test, PCUT_OUTCOME_INTERNAL_ERROR, error_message_buffer, NULL, NULL);
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 	rc = pipe(link_stderr);
@@ -159,6 +163,6 @@
 		snprintf(error_message_buffer, OUTPUT_BUFFER_SIZE - 1,
 				"pipe() failed: %s.", strerror(rc));
-		pcut_report_test_done(test, TEST_OUTCOME_ERROR, error_message_buffer, NULL, NULL);
-		return;
+		pcut_report_test_done(test, PCUT_OUTCOME_INTERNAL_ERROR, error_message_buffer, NULL, NULL);
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -167,5 +171,5 @@
 		snprintf(error_message_buffer, OUTPUT_BUFFER_SIZE - 1,
 			"fork() failed: %s.", strerror(rc));
-		rc = TEST_OUTCOME_ERROR;
+		outcome = PCUT_OUTCOME_INTERNAL_ERROR;
 		goto leave_close_pipes;
 	}
@@ -178,7 +182,7 @@
 		close(link_stderr[0]);
 
-		rc = pcut_run_test_forked(test);
-
-		exit(rc);
+		outcome = pcut_run_test_forked(test);
+
+		exit(outcome);
 	}
 
@@ -195,5 +199,5 @@
 	alarm(0);
 
-	rc = convert_wait_status_to_outcome(status);
+	outcome = convert_wait_status_to_outcome(status);
 
 	goto leave_close_parent_pipe;
@@ -206,5 +210,7 @@
 	close(link_stderr[0]);
 
-	pcut_report_test_done_unparsed(test, rc, extra_output_buffer, OUTPUT_BUFFER_SIZE);
+	pcut_report_test_done_unparsed(test, outcome, extra_output_buffer, OUTPUT_BUFFER_SIZE);
+
+	return outcome;
 }
 
Index: uspace/lib/pcut/src/os/windows.c
===================================================================
--- uspace/lib/pcut/src/os/windows.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/os/windows.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -144,5 +144,5 @@
  * @param test Test to be run.
  */
-void pcut_run_test_forking(const char *self_path, pcut_item_t *test) {
+int pcut_run_test_forking(const char *self_path, pcut_item_t *test) {
 	/* TODO: clean-up if something goes wrong "in the middle" */
 	BOOL okay = FALSE;
@@ -173,10 +173,10 @@
 	if (!okay) {
 		report_func_fail(test, "CreatePipe(/* stdout */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 	okay = SetHandleInformation(link_stdout[0], HANDLE_FLAG_INHERIT, 0);
 	if (!okay) {
 		report_func_fail(test, "SetHandleInformation(/* stdout */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -185,10 +185,10 @@
 	if (!okay) {
 		report_func_fail(test, "CreatePipe(/* stderr */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 	okay = SetHandleInformation(link_stderr[0], HANDLE_FLAG_INHERIT, 0);
 	if (!okay) {
 		report_func_fail(test, "SetHandleInformation(/* stderr */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -197,10 +197,10 @@
 	if (!okay) {
 		report_func_fail(test, "CreatePipe(/* stdin */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 	okay = SetHandleInformation(link_stdin[1], HANDLE_FLAG_INHERIT, 0);
 	if (!okay) {
 		report_func_fail(test, "SetHandleInformation(/* stdin */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -224,5 +224,5 @@
 	if (!okay) {
 		report_func_fail(test, "CreateProcess()");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -236,15 +236,15 @@
 	if (!okay) {
 		report_func_fail(test, "CloseHandle(/* stdout */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 	okay = CloseHandle(link_stderr[1]);
 	if (!okay) {
 		report_func_fail(test, "CloseHandle(/* stderr */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 	okay = CloseHandle(link_stdin[0]);
 	if (!okay) {
 		report_func_fail(test, "CloseHandle(/* stdin */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -267,5 +267,5 @@
 	if (test_output_thread_reader == NULL) {
 		report_func_fail(test, "CreateThread(/* read test stdout */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -281,5 +281,5 @@
 		if (!okay) {
 			report_func_fail(test, "TerminateProcess(/* PROCESS_INFORMATION.hProcess */)");
-			return;
+			return PCUT_ERROR_INTERNAL_FAILURE;
 		}
 		rc = WaitForSingleObject(process_info.hProcess, INFINITE);
@@ -287,5 +287,5 @@
 	if (rc != WAIT_OBJECT_0) {
 		report_func_fail(test, "WaitForSingleObject(/* PROCESS_INFORMATION.hProcess */)");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -294,13 +294,13 @@
 	if (!okay) {
 		report_func_fail(test, "GetExitCodeProcess()");
-		return;
+		return PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
 	if (rc == 0) {
-		outcome = TEST_OUTCOME_PASS;
+		outcome = PCUT_OUTCOME_PASS;
 	} else if ((rc > 0) && (rc < 10) && !timed_out) {
-		outcome = TEST_OUTCOME_FAIL;
+		outcome = PCUT_OUTCOME_FAIL;
 	} else {
-		outcome = TEST_OUTCOME_ERROR;
+		outcome = PCUT_OUTCOME_INTERNAL_ERROR;
 	}
 
@@ -309,8 +309,10 @@
 	if (rc != WAIT_OBJECT_0) {
 		report_func_fail(test, "WaitForSingleObject(/* stdout reader thread */)");
-		return;
+		return PCUT_ERROR_INTERNAL_FAILURE;
 	}
 
 	pcut_report_test_done_unparsed(test, outcome, extra_output_buffer, OUTPUT_BUFFER_SIZE);
+
+	return outcome;
 }
 
Index: uspace/lib/pcut/src/print.c
===================================================================
--- uspace/lib/pcut/src/print.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/print.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -81,4 +81,8 @@
 			printf("    Test `%s' [%d]\n", it->name, it->id);
 			break;
+		case PCUT_KIND_SETUP:
+		case PCUT_KIND_TEARDOWN:
+			/* Fall-through, do nothing. */
+			break;
 		default:
 			assert(0 && "unreachable case in item-kind switch");
Index: uspace/lib/pcut/src/report/tap.c
===================================================================
--- uspace/lib/pcut/src/report/tap.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/report/tap.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -42,4 +42,7 @@
 static int test_counter;
 
+/** Counter of all failures. */
+static int failed_test_counter;
+
 /** Counter for tests in a current suite. */
 static int tests_in_suite;
@@ -55,4 +58,5 @@
 	int tests_total = pcut_count_tests(all_items);
 	test_counter = 0;
+	failed_test_counter = 0;
 
 	printf("1..%d\n", tests_total);
@@ -75,6 +79,11 @@
  */
 static void tap_suite_done(pcut_item_t *suite) {
-	printf("#> Finished suite %s (failed %d of %d).\n",
-			suite->name, failed_tests_in_suite, tests_in_suite);
+	if (failed_tests_in_suite == 0) {
+		printf("#> Finished suite %s (passed).\n",
+				suite->name);
+	} else {
+		printf("#> Finished suite %s (failed %d of %d).\n",
+				suite->name, failed_tests_in_suite, tests_in_suite);
+	}
 }
 
@@ -129,23 +138,21 @@
 	const char *fail_error_str = NULL;
 
-	if (outcome != TEST_OUTCOME_PASS) {
+	if (outcome != PCUT_OUTCOME_PASS) {
 		failed_tests_in_suite++;
+		failed_test_counter++;
 	}
 
 	switch (outcome) {
-	case TEST_OUTCOME_PASS:
+	case PCUT_OUTCOME_PASS:
 		status_str = "ok";
 		fail_error_str = "";
 		break;
-	case TEST_OUTCOME_FAIL:
+	case PCUT_OUTCOME_FAIL:
 		status_str = "not ok";
 		fail_error_str = " failed";
 		break;
-	case TEST_OUTCOME_ERROR:
+	default:
 		status_str = "not ok";
 		fail_error_str = " aborted";
-		break;
-	default:
-		/* Shall not get here. */
 		break;
 	}
@@ -160,4 +167,9 @@
 /** Report testing done. */
 static void tap_done(void) {
+	if (failed_test_counter == 0) {
+		printf("#> Done: all tests passed.\n");
+	} else {
+		printf("#> Done: %d of %d tests failed.\n", failed_test_counter, test_counter);
+	}
 }
 
Index: uspace/lib/pcut/src/report/xml.c
===================================================================
--- uspace/lib/pcut/src/report/xml.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/report/xml.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -135,20 +135,17 @@
 	const char *status_str = NULL;
 
-	if (outcome != TEST_OUTCOME_PASS) {
+	if (outcome != PCUT_OUTCOME_PASS) {
 		failed_tests_in_suite++;
 	}
 
 	switch (outcome) {
-	case TEST_OUTCOME_PASS:
+	case PCUT_OUTCOME_PASS:
 		status_str = "pass";
 		break;
-	case TEST_OUTCOME_FAIL:
+	case PCUT_OUTCOME_FAIL:
 		status_str = "fail";
 		break;
-	case TEST_OUTCOME_ERROR:
+	default:
 		status_str = "error";
-		break;
-	default:
-		/* Shall not get here. */
 		break;
 	}
Index: uspace/lib/pcut/src/run.c
===================================================================
--- uspace/lib/pcut/src/run.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/src/run.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -73,9 +73,8 @@
 static int default_suite_initialized = 0;
 
-static void init_default_suite_when_needed(void)
-{
-	if (default_suite_initialized)
+static void init_default_suite_when_needed() {
+	if (default_suite_initialized) {
 		return;
-	
+	}
 	default_suite.id = -1;
 	default_suite.kind = PCUT_KIND_TESTSUITE;
@@ -92,13 +91,11 @@
  * @return Always a valid test suite item.
  */
-static pcut_item_t *pcut_find_parent_suite(pcut_item_t *it)
-{
+static pcut_item_t *pcut_find_parent_suite(pcut_item_t *it) {
 	while (it != NULL) {
-		if (it->kind == PCUT_KIND_TESTSUITE)
+		if (it->kind == PCUT_KIND_TESTSUITE) {
 			return it;
-		
+		}
 		it = it->previous;
 	}
-	
 	init_default_suite_when_needed();
 	return &default_suite;
@@ -109,8 +106,8 @@
  * @param func Function to run (can be NULL).
  */
-static void run_setup_teardown(pcut_setup_func_t func)
-{
-	if (func != NULL)
+static void run_setup_teardown(pcut_setup_func_t func) {
+	if (func != NULL) {
 		func();
+	}
 }
 
@@ -122,11 +119,11 @@
  * @param outcome Outcome of the current test.
  */
-static void leave_test(int outcome)
-{
+static void leave_test(int outcome) {
 	PCUT_DEBUG("leave_test(outcome=%d), will_exit=%s", outcome,
-	    leave_means_exit ? "yes" : "no");
-	if (leave_means_exit)
+		leave_means_exit ? "yes" : "no");
+	if (leave_means_exit) {
 		exit(outcome);
-	
+	}
+
 #ifndef PCUT_NO_LONG_JUMP
 	longjmp(start_test_jump, 1);
@@ -141,8 +138,6 @@
  * @param message Message describing the failure.
  */
-void pcut_failed_assertion(const char *message)
-{
+void pcut_failed_assertion(const char *message) {
 	static const char *prev_message = NULL;
-	
 	/*
 	 * The assertion failed. We need to abort the current test,
@@ -150,27 +145,28 @@
 	 * include running the tear-down routine.
 	 */
-	if (print_test_error)
+	if (print_test_error) {
 		pcut_print_fail_message(message);
-	
+	}
+
 	if (execute_teardown_on_failure) {
 		execute_teardown_on_failure = 0;
 		prev_message = message;
 		run_setup_teardown(current_suite->teardown_func);
-		
+
 		/* Tear-down was okay. */
 		if (report_test_result) {
-			pcut_report_test_done(current_test, TEST_OUTCOME_FAIL,
+			pcut_report_test_done(current_test, PCUT_OUTCOME_FAIL,
 				message, NULL, NULL);
 		}
 	} else {
 		if (report_test_result) {
-			pcut_report_test_done(current_test, TEST_OUTCOME_FAIL,
+			pcut_report_test_done(current_test, PCUT_OUTCOME_FAIL,
 				prev_message, message, NULL);
 		}
 	}
-	
+
 	prev_message = NULL;
-	
-	leave_test(TEST_OUTCOME_FAIL); /* No return. */
+
+	leave_test(PCUT_OUTCOME_FAIL); /* No return. */
 }
 
@@ -180,6 +176,5 @@
  * @return Error status (zero means success).
  */
-static int run_test(pcut_item_t *test)
-{
+static int run_test(pcut_item_t *test) {
 	/*
 	 * Set here as the returning point in case of test failure.
@@ -187,19 +182,20 @@
 	 * test execution.
 	 */
-	
 #ifndef PCUT_NO_LONG_JUMP
 	int test_finished = setjmp(start_test_jump);
-	if (test_finished)
-		return 1;
+	if (test_finished) {
+		return PCUT_OUTCOME_FAIL;
+	}
 #endif
-	
-	if (report_test_result)
+
+	if (report_test_result) {
 		pcut_report_test_start(test);
-	
+	}
+
 	current_suite = pcut_find_parent_suite(test);
 	current_test = test;
-	
+
 	pcut_hook_before_test(test);
-	
+
 	/*
 	 * If anything goes wrong, execute the tear-down function
@@ -207,10 +203,10 @@
 	 */
 	execute_teardown_on_failure = 1;
-	
+
 	/*
 	 * Run the set-up function.
 	 */
 	run_setup_teardown(current_suite->setup_func);
-	
+
 	/*
 	 * The setup function was performed, it is time to run
@@ -218,5 +214,5 @@
 	 */
 	test->test_func();
-	
+
 	/*
 	 * Finally, run the tear-down function. We need to clear
@@ -225,14 +221,15 @@
 	execute_teardown_on_failure = 0;
 	run_setup_teardown(current_suite->teardown_func);
-	
+
 	/*
 	 * If we got here, it means everything went well with
 	 * this test.
 	 */
-	if (report_test_result)
-		pcut_report_test_done(current_test, TEST_OUTCOME_PASS,
-		    NULL, NULL, NULL);
-	
-	return 0;
+	if (report_test_result) {
+		pcut_report_test_done(current_test, PCUT_OUTCOME_PASS,
+			NULL, NULL, NULL);
+	}
+
+	return PCUT_OUTCOME_PASS;
 }
 
@@ -245,15 +242,16 @@
  * @return Error status (zero means success).
  */
-int pcut_run_test_forked(pcut_item_t *test)
-{
+int pcut_run_test_forked(pcut_item_t *test) {
+	int rc;
+
 	report_test_result = 0;
 	print_test_error = 1;
 	leave_means_exit = 1;
-	
-	int rc = run_test(test);
-	
+
+	rc = run_test(test);
+
 	current_test = NULL;
 	current_suite = NULL;
-	
+
 	return rc;
 }
@@ -267,15 +265,16 @@
  * @return Error status (zero means success).
  */
-int pcut_run_test_single(pcut_item_t *test)
-{
+int pcut_run_test_single(pcut_item_t *test) {
+	int rc;
+
 	report_test_result = 1;
 	print_test_error = 0;
 	leave_means_exit = 0;
-	
-	int rc = run_test(test);
-	
+
+	rc = run_test(test);
+
 	current_test = NULL;
 	current_suite = NULL;
-	
+
 	return rc;
 }
@@ -286,16 +285,16 @@
  * @return Timeout in seconds.
  */
-int pcut_get_test_timeout(pcut_item_t *test)
-{
+int pcut_get_test_timeout(pcut_item_t *test) {
 	int timeout = PCUT_DEFAULT_TEST_TIMEOUT;
 	pcut_extra_t *extras = test->extras;
-	
+
+
 	while (extras->type != PCUT_EXTRA_LAST) {
-		if (extras->type == PCUT_EXTRA_TIMEOUT)
+		if (extras->type == PCUT_EXTRA_TIMEOUT) {
 			timeout = extras->timeout;
-		
+		}
 		extras++;
 	}
-	
+
 	return timeout;
 }
Index: uspace/lib/pcut/tests/abort.expected
===================================================================
--- uspace/lib/pcut/tests/abort.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/abort.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -3,2 +3,3 @@
 not ok 1 access_null_pointer aborted
 #> Finished suite Default (failed 1 of 1).
+#> Done: 1 of 1 tests failed.
Index: uspace/lib/pcut/tests/asserts.expected
===================================================================
--- uspace/lib/pcut/tests/asserts.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/asserts.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -18,2 +18,3 @@
 # error: asserts.c:72: Expected false but got <42>
 #> Finished suite Default (failed 7 of 9).
+#> Done: 7 of 9 tests failed.
Index: uspace/lib/pcut/tests/beforeafter.c
===================================================================
--- uspace/lib/pcut/tests/beforeafter.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/beforeafter.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -28,4 +28,5 @@
 
 #define _BSD_SOURCE
+#define _DEFAULT_SOURCE
 
 #include <pcut/pcut.h>
Index: uspace/lib/pcut/tests/beforeafter.expected
===================================================================
--- uspace/lib/pcut/tests/beforeafter.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/beforeafter.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -2,6 +2,7 @@
 #> Starting suite suite_with_setup_and_teardown.
 ok 1 test_with_setup_and_teardown
-#> Finished suite suite_with_setup_and_teardown (failed 0 of 1).
+#> Finished suite suite_with_setup_and_teardown (passed).
 #> Starting suite another_without_setup.
 ok 2 test_without_any_setup_or_teardown
-#> Finished suite another_without_setup (failed 0 of 1).
+#> Finished suite another_without_setup (passed).
+#> Done: all tests passed.
Index: uspace/lib/pcut/tests/errno.expected
===================================================================
--- uspace/lib/pcut/tests/errno.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/errno.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -6,2 +6,3 @@
 # error: errno.c:54: Expected error 0 (EOK, *****) but got error ***** (*****)
 #> Finished suite Default (failed 2 of 2).
+#> Done: 2 of 2 tests failed.
Index: uspace/lib/pcut/tests/inithook.expected
===================================================================
--- uspace/lib/pcut/tests/inithook.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/inithook.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -3,3 +3,4 @@
 ok 1 check_init_counter
 ok 2 check_init_counter_2
-#> Finished suite Default (failed 0 of 2).
+#> Finished suite Default (passed).
+#> Done: all tests passed.
Index: uspace/lib/pcut/tests/manytests.expected
===================================================================
--- uspace/lib/pcut/tests/manytests.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/manytests.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -81,3 +81,4 @@
 ok 79 my_test_079
 ok 80 my_test_080
-#> Finished suite Default (failed 0 of 80).
+#> Finished suite Default (passed).
+#> Done: all tests passed.
Index: uspace/lib/pcut/tests/multisuite.expected
===================================================================
--- uspace/lib/pcut/tests/multisuite.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/multisuite.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -11,2 +11,3 @@
 ok 4 test_same_numbers
 #> Finished suite intmin (failed 1 of 2).
+#> Done: 3 of 4 tests failed.
Index: uspace/lib/pcut/tests/preinithook.expected
===================================================================
--- uspace/lib/pcut/tests/preinithook.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/preinithook.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -3,3 +3,4 @@
 ok 1 check_init_counter
 ok 2 check_init_counter_2
-#> Finished suite Default (failed 0 of 2).
+#> Finished suite Default (passed).
+#> Done: all tests passed.
Index: uspace/lib/pcut/tests/printing.expected
===================================================================
--- uspace/lib/pcut/tests/printing.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/printing.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -9,2 +9,3 @@
 # stdio: Printed from a test to stdout!
 #> Finished suite Default (failed 1 of 3).
+#> Done: 1 of 3 tests failed.
Index: uspace/lib/pcut/tests/simple.expected
===================================================================
--- uspace/lib/pcut/tests/simple.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/simple.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -8,2 +8,3 @@
 # error: simple.c:46: Expected <abc> but got <abd> ("abc" != "XXXabd" + 3)
 #> Finished suite Default (failed 3 of 3).
+#> Done: 3 of 3 tests failed.
Index: uspace/lib/pcut/tests/skip.expected
===================================================================
--- uspace/lib/pcut/tests/skip.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/skip.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -3,3 +3,4 @@
 ok 1 normal_test
 ok 2 again_normal_test
-#> Finished suite Default (failed 0 of 2).
+#> Finished suite Default (passed).
+#> Done: all tests passed.
Index: uspace/lib/pcut/tests/suites.expected
===================================================================
--- uspace/lib/pcut/tests/suites.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/suites.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -10,2 +10,3 @@
 # error: suites.c:49: Expected <5> but got <654> (5 != intmin(654, 5))
 #> Finished suite intmin (failed 1 of 1).
+#> Done: 3 of 3 tests failed.
Index: uspace/lib/pcut/tests/teardown.expected
===================================================================
--- uspace/lib/pcut/tests/teardown.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/teardown.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -21,2 +21,3 @@
 # stdio: This is failing teardown-function.
 #> Finished suite with_failing_teardown (failed 3 of 3).
+#> Done: 4 of 5 tests failed.
Index: uspace/lib/pcut/tests/teardownaborts.expected
===================================================================
--- uspace/lib/pcut/tests/teardownaborts.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/teardownaborts.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -5,2 +5,3 @@
 # stdio: Tear-down will cause null pointer access...
 #> Finished suite Default (failed 1 of 1).
+#> Done: 1 of 1 tests failed.
Index: uspace/lib/pcut/tests/timeout.c
===================================================================
--- uspace/lib/pcut/tests/timeout.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/timeout.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -29,10 +29,13 @@
 #include <pcut/pcut.h>
 
+#ifdef __helenos__
+#include <thread.h>
+#else
 #ifdef __unix
-// FIXME
-#include <thread.h>
+#include <unistd.h>
 #endif
 #if defined(__WIN64) || defined(__WIN32) || defined(_WIN32)
 #include <windows.h>
+#endif
 #endif
 
@@ -41,10 +44,13 @@
 
 static void my_sleep(int sec) {
+#ifdef __helenos__
+	thread_sleep(sec);
+#else
 #ifdef __unix
-// FIXME
-	thread_sleep(sec);
+	sleep(sec);
 #endif
 #if defined(__WIN64) || defined(__WIN32) || defined(_WIN32)
 	Sleep(1000 * sec);
+#endif
 #endif
 }
Index: uspace/lib/pcut/tests/timeout.expected
===================================================================
--- uspace/lib/pcut/tests/timeout.expected	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/timeout.expected	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -7,2 +7,3 @@
 # stdio: Text after the sleep.
 #> Finished suite Default (failed 1 of 2).
+#> Done: 1 of 2 tests failed.
Index: uspace/lib/pcut/tests/xmlreport.c
===================================================================
--- uspace/lib/pcut/tests/xmlreport.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/pcut/tests/xmlreport.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -30,4 +30,6 @@
 #include "tested.h"
 
+#include <pcut/pcut.h>
+#include "tested.h"
 
 PCUT_INIT
Index: uspace/lib/posix/source/fcntl.c
===================================================================
--- uspace/lib/posix/source/fcntl.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/posix/source/fcntl.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -135,6 +135,7 @@
 	    ((posix_flags & O_APPEND) ? MODE_APPEND : 0);
 
-	int file = rcerrno(vfs_lookup, pathname, flags);
-	if (file < 0)
+	int file;
+	rc = rcerrno(vfs_lookup, pathname, flags, &file);
+	if (rc != EOK)
 		return -1;
 
Index: uspace/lib/posix/source/stdio.c
===================================================================
--- uspace/lib/posix/source/stdio.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/posix/source/stdio.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -343,7 +343,8 @@
 {
 	const int fildes = *(int *) fd;
-	ssize_t wr = vfs_write(fildes, &posix_pos[fildes], str, size);
-	if (wr < 0)
-		return wr;
+	size_t wr;
+	int rc = vfs_write(fildes, &posix_pos[fildes], str, size, &wr);
+	if (rc != EOK)
+		return rc;
 	return str_nlength(str, wr);
 }
@@ -371,5 +372,6 @@
 		
 		const int fildes = *(int *) fd;
-		if (vfs_write(fildes, &posix_pos[fildes], buf, sz) < 0)
+		size_t nwr;
+		if (vfs_write(fildes, &posix_pos[fildes], buf, sz, &nwr) != EOK)
 			break;
 		
Index: uspace/lib/posix/source/time.c
===================================================================
--- uspace/lib/posix/source/time.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/posix/source/time.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -45,5 +45,5 @@
 #include "posix/assert.h"
 
-#include "libc/fibril_synch.h"
+#include "libc/async.h"
 #include "libc/malloc.h"
 #include "libc/task.h"
@@ -314,8 +314,8 @@
 			// TODO: interruptible sleep
 			if (rqtp->tv_sec != 0) {
-				fibril_sleep(rqtp->tv_sec);
+				async_sleep(rqtp->tv_sec);
 			}
 			if (rqtp->tv_nsec != 0) {
-				fibril_usleep(rqtp->tv_nsec / 1000);
+				async_usleep(rqtp->tv_nsec / 1000);
 			}
 			return 0;
Index: uspace/lib/posix/source/unistd.c
===================================================================
--- uspace/lib/posix/source/unistd.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/posix/source/unistd.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -213,8 +213,11 @@
 ssize_t posix_read(int fildes, void *buf, size_t nbyte)
 {
-	ssize_t size = rcerrno(vfs_read, fildes, &posix_pos[fildes], buf, nbyte);
-	if (size < 0)
-		return -1;
-	return size;
+	size_t nread;
+	int rc;
+
+	rc = rcerrno(vfs_read, fildes, &posix_pos[fildes], buf, nbyte, &nread);
+	if (rc != EOK)
+		return -1;
+	return (ssize_t) nread;
 }
 
@@ -229,8 +232,11 @@
 ssize_t posix_write(int fildes, const void *buf, size_t nbyte)
 {
-	ssize_t size = rcerrno(vfs_write, fildes, &posix_pos[fildes], buf, nbyte);
-	if (size < 0)
-		return -1;
-	return size;
+	size_t nwr;
+	int rc;
+
+	rc = rcerrno(vfs_write, fildes, &posix_pos[fildes], buf, nbyte, &nwr);
+	if (rc != EOK)
+		return -1;
+	return nwr;
 }
 
@@ -349,5 +355,11 @@
 int posix_dup2(int fildes, int fildes2)
 {
-	return negerrno(vfs_clone, fildes, fildes2, false);
+	int file;
+	int rc = vfs_clone(fildes, fildes2, false, &file);
+	if (rc != EOK) {
+		errno = rc < 0 ? -rc : rc;
+		return -1;
+	}
+	return file;
 }
 
Index: uspace/lib/usbhid/src/hiddescriptor.c
===================================================================
--- uspace/lib/usbhid/src/hiddescriptor.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/usbhid/src/hiddescriptor.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,8 +36,8 @@
 #include <errno.h>
 #include <stdio.h>
-#include <malloc.h>
 #include <mem.h>
 #include <usb/debug.h>
 #include <assert.h>
+#include <stdlib.h>
 
 
Index: uspace/lib/usbhid/src/hidparser.c
===================================================================
--- uspace/lib/usbhid/src/hidparser.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/usbhid/src/hidparser.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,5 @@
 #include <errno.h>
 #include <stdio.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <mem.h>
 #include <usb/debug.h>
Index: uspace/lib/usbhid/src/hidpath.c
===================================================================
--- uspace/lib/usbhid/src/hidpath.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/usbhid/src/hidpath.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,6 +36,6 @@
 #include <errno.h>
 #include <stdio.h>
-#include <malloc.h>
 #include <mem.h>
+#include <stdlib.h>
 #include <usb/debug.h>
 #include <assert.h>
Index: uspace/lib/usbhost/include/usb/host/ddf_helpers.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/ddf_helpers.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/usbhost/include/usb/host/ddf_helpers.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -48,5 +48,5 @@
 typedef void (*driver_fini_t)(hcd_t *);
 typedef int (*claim_t)(ddf_dev_t *);
-typedef int (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *);
+typedef int (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *, int *);
 
 typedef struct {
@@ -75,6 +75,7 @@
     const hw_res_list_parsed_t *hw_res,
     interrupt_handler_t handler,
-    int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *));
-void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev);
+    int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *, int *),
+    cap_handle_t *handle);
+void ddf_hcd_gen_irq_handler(ipc_call_t *call, ddf_dev_t *dev);
 
 #endif
Index: uspace/lib/usbhost/include/usb/host/hcd.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/hcd.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/usbhost/include/usb/host/hcd.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -102,5 +102,5 @@
 }
 
-extern usb_address_t hcd_request_address(hcd_t *, usb_speed_t);
+extern int hcd_request_address(hcd_t *, usb_speed_t, usb_address_t *);
 
 extern int hcd_release_address(hcd_t *, usb_address_t);
@@ -123,6 +123,6 @@
     usbhc_iface_transfer_out_callback_t, void *, const char *);
 
-extern ssize_t hcd_send_batch_sync(hcd_t *, usb_target_t, usb_direction_t,
-    void *, size_t, uint64_t, const char *);
+extern int hcd_send_batch_sync(hcd_t *, usb_target_t, usb_direction_t,
+    void *, size_t, uint64_t, const char *, size_t *);
 
 #endif
Index: uspace/lib/usbhost/src/ddf_helpers.c
===================================================================
--- uspace/lib/usbhost/src/ddf_helpers.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/usbhost/src/ddf_helpers.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -481,9 +481,10 @@
 	}};
 
-	const usb_address_t address = hcd_request_address(hcd, speed);
-	if (address < 0) {
+	usb_address_t address;
+	ret = hcd_request_address(hcd, speed, &address);
+	if (ret != EOK) {
 		usb_log_error("Failed to reserve new address: %s.",
-		    str_error(address));
-		return address;
+		    str_error(ret));
+		return ret;
 	}
 
@@ -518,10 +519,14 @@
 	usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
 	    address);
-	ssize_t got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN,
+	size_t got;
+	ret = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN,
 	    &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
-	    "read first 8 bytes of dev descriptor");
-
-	if (got != CTRL_PIPE_MIN_PACKET_SIZE) {
-		ret = got < 0 ? got : EOVERFLOW;
+	    "read first 8 bytes of dev descriptor", &got);
+
+	if (ret == EOK && got != CTRL_PIPE_MIN_PACKET_SIZE) {
+		ret = EOVERFLOW;
+	}
+
+	if (ret != EOK) {
 		usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.",
 		    address, str_error(ret));
@@ -552,16 +557,16 @@
 
 	usb_log_debug("Device(%d): Setting USB address.", address);
-	got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT,
-	    NULL, 0, *(uint64_t *)&set_address, "set address");
+	ret = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT,
+	    NULL, 0, *(uint64_t *)&set_address, "set address", &got);
 
 	usb_log_debug("Device(%d): Removing default (0:0) EP.", address);
 	hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
 
-	if (got != 0) {
+	if (ret != EOK) {
 		usb_log_error("Device(%d): Failed to set new address: %s.",
-		    address, str_error(got));
+		    address, str_error(ret));
 		hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
 		hcd_release_address(hcd, address);
-		return got;
+		return ret;
 	}
 
@@ -572,7 +577,7 @@
 	usb_log_debug("Device(%d): Requesting full device descriptor.",
 	    address);
-	got = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN,
+	ret = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN,
 	    &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
-	    "read device descriptor");
+	    "read device descriptor", &got);
 	if (ret != EOK) {
 		usb_log_error("Device(%d): Failed to set get dev descriptor: %s",
@@ -742,11 +747,13 @@
  * @param[in] gen_irq_code IRQ code generator.
  *
- * @return IRQ capability handle on success.
- * @return Negative error code.
+ * @param[out] handle  IRQ capability handle on success.
+ *
+ * @return Error code.
  */
 int hcd_ddf_setup_interrupts(ddf_dev_t *device,
     const hw_res_list_parsed_t *hw_res,
     interrupt_handler_t handler,
-    int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res))
+    int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *, int *),
+    cap_handle_t *handle)
 {
 
@@ -757,30 +764,30 @@
 	irq_code_t irq_code = {0};
 
-	const int irq = gen_irq_code(&irq_code, hw_res);
-	if (irq < 0) {
+	int irq;
+	int ret = gen_irq_code(&irq_code, hw_res, &irq);
+	if (ret != EOK) {
 		usb_log_error("Failed to generate IRQ code: %s.\n",
-		    str_error(irq));
-		return irq;
+		    str_error(ret));
+		return ret;
 	}
 
 	/* Register handler to avoid interrupt lockup */
-	const int irq_cap = register_interrupt_handler(device, irq, handler,
-	    &irq_code);
+	ret = register_interrupt_handler(device, irq, handler,
+	    &irq_code, handle);
 	irq_code_clean(&irq_code);
-	if (irq_cap < 0) {
-		usb_log_error("Failed to register interrupt handler: %s.\n",
-		    str_error(irq_cap));
-		return irq_cap;
-	}
-
-	/* Enable interrupts */
-	int ret = hcd_ddf_enable_interrupt(device, irq);
 	if (ret != EOK) {
 		usb_log_error("Failed to register interrupt handler: %s.\n",
 		    str_error(ret));
-		unregister_interrupt_handler(device, irq_cap);
-		return ret;
-	}
-	return irq_cap;
+		return ret;
+	}
+
+	/* Enable interrupts */
+	ret = hcd_ddf_enable_interrupt(device, irq);
+	if (ret != EOK) {
+		usb_log_error("Failed to register interrupt handler: %s.\n",
+		    str_error(ret));
+		unregister_interrupt_handler(device, *handle);
+	}
+	return ret;
 }
 
@@ -788,8 +795,7 @@
  *
  * @param[in] dev DDF instance of the device to use.
- * @param[in] iid (Unused).
  * @param[in] call Pointer to the call from kernel.
  */
-void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev)
+void ddf_hcd_gen_irq_handler(ipc_call_t *call, ddf_dev_t *dev)
 {
 	assert(dev);
@@ -877,17 +883,19 @@
 	interrupt_handler_t *irq_handler =
 	    driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;
-	const int irq_cap = hcd_ddf_setup_interrupts(device, &hw_res,
-	    irq_handler, driver->irq_code_gen);
-	bool irqs_enabled = !(irq_cap < 0);
+	int irq_cap;
+	ret = hcd_ddf_setup_interrupts(device, &hw_res,
+	    irq_handler, driver->irq_code_gen, &irq_cap);
+	bool irqs_enabled = (ret == EOK);
 	if (irqs_enabled) {
 		usb_log_debug("Hw interrupts enabled.\n");
 	}
 
-	if (driver->claim)
+	if (driver->claim) {
 		ret = driver->claim(device);
-	if (ret != EOK) {
-		usb_log_error("Failed to claim `%s' for driver `%s'",
-		    ddf_dev_get_name(device), driver->name);
-		return ret;
+		if (ret != EOK) {
+			usb_log_error("Failed to claim `%s' for driver `%s'",
+			    ddf_dev_get_name(device), driver->name);
+			return ret;
+		}
 	}
 
Index: uspace/lib/usbhost/src/hcd.c
===================================================================
--- uspace/lib/usbhost/src/hcd.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/lib/usbhost/src/hcd.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -102,13 +102,8 @@
 }
 
-usb_address_t hcd_request_address(hcd_t *hcd, usb_speed_t speed)
-{
-	assert(hcd);
-	usb_address_t address = 0;
-	const int ret = usb_bus_request_address(
-	    &hcd->bus, &address, false, speed);
-	if (ret != EOK)
-		return ret;
-	return address;
+int hcd_request_address(hcd_t *hcd, usb_speed_t speed, usb_address_t *address)
+{
+	assert(hcd);
+	return usb_bus_request_address(&hcd->bus, address, false, speed);
 }
 
@@ -271,7 +266,7 @@
 
 /** this is really ugly version of sync usb communication */
-ssize_t hcd_send_batch_sync(
+int hcd_send_batch_sync(
     hcd_t *hcd, usb_target_t target, usb_direction_t dir,
-    void *data, size_t size, uint64_t setup_data, const char* name)
+    void *data, size_t size, uint64_t setup_data, const char* name, size_t *out_size)
 {
 	assert(hcd);
@@ -289,5 +284,5 @@
 
 	if (sd.ret == EOK)
-		return sd.size;
+		*out_size = sd.size;
 	return sd.ret;
 }
Index: uspace/srv/audio/hound/audio_data.c
===================================================================
--- uspace/srv/audio/hound/audio_data.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/audio/hound/audio_data.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,5 +35,5 @@
 
 #include <macros.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 #include "audio_data.h"
Index: uspace/srv/audio/hound/audio_device.c
===================================================================
--- uspace/srv/audio/hound/audio_device.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/audio/hound/audio_device.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -62,5 +62,5 @@
 	assert(dev);
 	/* we release buffer on stop so this should be enough */
-	return (bool)dev->buffer.base;
+	return dev->buffer.base != NULL;
 }
 
@@ -121,5 +121,7 @@
 {
 	assert(dev);
-	if (audio_pcm_query_cap(dev->sess, AUDIO_CAP_CAPTURE))
+	sysarg_t val;
+	int rc = audio_pcm_query_cap(dev->sess, AUDIO_CAP_CAPTURE, &val);
+	if (rc == EOK && val)
 		return &dev->source;
 	return NULL;
@@ -135,5 +137,7 @@
 {
 	assert(dev);
-	if (audio_pcm_query_cap(dev->sess, AUDIO_CAP_PLAYBACK))
+	sysarg_t val;
+	int rc = audio_pcm_query_cap(dev->sess, AUDIO_CAP_PLAYBACK, &val);
+	if (rc == EOK && val)
 		return &dev->sink;
 	return NULL;
Index: uspace/srv/audio/hound/connection.c
===================================================================
--- uspace/srv/audio/hound/connection.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/audio/hound/connection.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -34,6 +34,6 @@
  */
 
-#include <malloc.h>
 #include <errno.h>
+#include <stdlib.h>
 
 #include "log.h"
Index: uspace/srv/audio/hound/hound_ctx.c
===================================================================
--- uspace/srv/audio/hound/hound_ctx.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/audio/hound/hound_ctx.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,7 +35,7 @@
  */
 
-#include <malloc.h>
 #include <macros.h>
 #include <errno.h>
+#include <stdlib.h>
 #include <str_error.h>
 
Index: uspace/srv/bd/file_bd/file_bd.c
===================================================================
--- uspace/srv/bd/file_bd/file_bd.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/bd/file_bd/file_bd.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -48,4 +48,5 @@
 #include <stdint.h>
 #include <errno.h>
+#include <str_error.h>
 #include <stdbool.h>
 #include <task.h>
@@ -134,6 +135,6 @@
 	rc = loc_service_register(device_name, &service_id);
 	if (rc != EOK) {
-		printf("%s: Unable to register device '%s'.\n",
-		    NAME, device_name);
+		printf("%s: Unable to register device '%s': %s.\n",
+		    NAME, device_name, str_error(rc));
 		return rc;
 	}
@@ -141,5 +142,5 @@
 	rc = loc_category_get_id("disk", &disk_cat, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
-		printf("%s: Failed resolving category 'disk'.\n", NAME);
+		printf("%s: Failed resolving category 'disk': %s\n", NAME, str_error(rc));
 		return rc;
 	}
@@ -147,6 +148,6 @@
 	rc = loc_service_add_to_cat(service_id, disk_cat);
 	if (rc != EOK) {
-		printf("%s: Failed adding %s to category.",
-		    NAME, device_name);
+		printf("%s: Failed adding %s to category: %s",
+		    NAME, device_name, str_error(rc));
 		return rc;
 	}
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/bd/rd/rd.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -48,4 +48,5 @@
 #include <stdbool.h>
 #include <errno.h>
+#include <str_error.h>
 #include <async.h>
 #include <fibril_synch.h>
@@ -179,5 +180,5 @@
 	ret = loc_server_register(NAME);
 	if (ret != EOK) {
-		printf("%s: Unable to register driver (%d)\n", NAME, ret);
+		printf("%s: Unable to register driver: %s\n", NAME, str_error(ret));
 		return false;
 	}
Index: uspace/srv/bd/sata_bd/sata_bd.c
===================================================================
--- uspace/srv/bd/sata_bd/sata_bd.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/bd/sata_bd/sata_bd.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,4 +41,5 @@
 #include <devman.h>
 #include <errno.h>
+#include <str_error.h>
 #include <stdio.h>
 #include <str.h>
@@ -251,5 +252,5 @@
 	rc = loc_server_register(NAME);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register driver: %s.\n", str_error(rc));
 		return rc;
 	}
@@ -257,4 +258,5 @@
 	rc = get_sata_disks();
 	if (rc != EOK) {
+		// TODO: log the error
 		return rc;
 	}
@@ -262,5 +264,5 @@
 	rc = loc_category_get_id("disk", &disk_cat, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
-		printf("%s: Failed resolving category 'disk'.\n", NAME);
+		printf("%s: Failed resolving category 'disk': %s.\n", NAME, str_error(rc));
 		return rc;
 	}
@@ -271,5 +273,5 @@
 		rc = loc_service_register(name, &disk[i].service_id);
 		if (rc != EOK) {
-			printf(NAME ": Unable to register device %s.\n", name);
+			printf(NAME ": Unable to register device %s: %s\n", name, str_error(rc));
 			return rc;
 		}
@@ -277,6 +279,6 @@
 		rc = loc_service_add_to_cat(disk[i].service_id, disk_cat);
 		if (rc != EOK) {
-			printf("%s: Failed adding %s to category.",
-			    NAME, disk[i].dev_name);
+			printf("%s: Failed adding %s to category: %s.",
+			    NAME, disk[i].dev_name, str_error(rc));
 			return rc;
 		}
Index: uspace/srv/bd/vbd/disk.c
===================================================================
--- uspace/srv/bd/vbd/disk.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/bd/vbd/disk.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,4 +38,5 @@
 #include <block.h>
 #include <errno.h>
+#include <str_error.h>
 #include <io/log.h>
 #include <label/empty.h>
@@ -456,5 +457,5 @@
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback "
-		    "for disk discovery (%d).", rc);
+		    "for disk discovery: %s.", str_error(rc));
 		return rc;
 	}
@@ -1124,5 +1125,5 @@
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering "
-		    "service %s (%d).", name, rc);
+		    "service %s: %s.", name, str_error(rc));
 		free(name);
 		free(part);
Index: uspace/srv/bd/vbd/vbd.c
===================================================================
--- uspace/srv/bd/vbd/vbd.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/bd/vbd/vbd.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,4 +36,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <io/log.h>
 #include <ipc/services.h>
@@ -69,5 +70,5 @@
 	rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server: %s.", str_error(rc));
 		return EEXIST;
 	}
@@ -75,5 +76,5 @@
 	rc = loc_service_register(SERVICE_NAME_VBD, &ctl_sid);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service: %s.", str_error(rc));
 		return EEXIST;
 	}
Index: uspace/srv/clipboard/clipboard.c
===================================================================
--- uspace/srv/clipboard/clipboard.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/clipboard/clipboard.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -29,11 +29,12 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
 #include <ipc/clipboard.h>
 #include <loc.h>
-#include <malloc.h>
 #include <stdio.h>
 #include <stdbool.h>
+#include <stdlib.h>
 #include <task.h>
 
@@ -188,5 +189,5 @@
 	rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		printf("%s: Failed registering server. (%d)\n", NAME, rc);
+		printf("%s: Failed registering server: %s\n", NAME, str_error(rc));
 		return rc;
 	}
@@ -194,5 +195,5 @@
 	rc = loc_service_register(SERVICE_NAME_CLIPBOARD, &svc_id);
 	if (rc != EOK) {
-		printf("%s: Failed registering service. (%d)\n", NAME, rc);
+		printf("%s: Failed registering service : %s\n", NAME, str_error(rc));
 		return rc;
 	}
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/devman/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -42,4 +42,5 @@
 #include <stdio.h>
 #include <errno.h>
+#include <str_error.h>
 #include <stdbool.h>
 #include <fibril_synch.h>
@@ -318,5 +319,5 @@
 	int rc = log_init(NAME);
 	if (rc != EOK) {
-		printf("%s: Error initializing logging subsystem.\n", NAME);
+		printf("%s: Error initializing logging subsystem: %s\n", NAME, str_error(rc));
 		return rc;
 	}
@@ -329,21 +330,29 @@
 	rc = async_create_port(INTERFACE_DDF_DRIVER,
 	    devman_connection_driver, NULL, &port);
-	if (rc != EOK)
-		return rc;
+	if (rc != EOK) {
+		printf("%s: Error creating DDF driver port: %s\n", NAME, str_error(rc));
+		return rc;
+	}
 	
 	rc = async_create_port(INTERFACE_DDF_CLIENT,
 	    devman_connection_client, NULL, &port);
-	if (rc != EOK)
-		return rc;
+	if (rc != EOK) {
+		printf("%s: Error creating DDF client port: %s\n", NAME, str_error(rc));
+		return rc;
+	}
 	
 	rc = async_create_port(INTERFACE_DEVMAN_DEVICE,
 	    devman_connection_device, NULL, &port);
-	if (rc != EOK)
-		return rc;
+	if (rc != EOK) {
+		printf("%s: Error creating devman device port: %s\n", NAME, str_error(rc));
+		return rc;
+	}
 	
 	rc = async_create_port(INTERFACE_DEVMAN_PARENT,
 	    devman_connection_parent, NULL, &port);
-	if (rc != EOK)
-		return rc;
+	if (rc != EOK) {
+		printf("%s: Error creating devman parent port: %s\n", NAME, str_error(rc));
+		return rc;
+	}
 	
 	async_set_fallback_port_handler(devman_forward, NULL);
@@ -357,5 +366,5 @@
 	rc = service_register(SERVICE_DEVMAN);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering as a service.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering as a service: %s", str_error(rc));
 		return rc;
 	}
Index: uspace/srv/devman/match.c
===================================================================
--- uspace/srv/devman/match.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/devman/match.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -202,15 +202,16 @@
 	struct stat st;
 	
-	fd = vfs_lookup_open(conf_path, WALK_REGULAR, MODE_READ);
-	if (fd < 0) {
+	int rc = vfs_lookup_open(conf_path, WALK_REGULAR, MODE_READ, &fd);
+	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to open `%s' for reading: %s.",
-		    conf_path, str_error(errno));
+		    conf_path, str_error(rc));
 		goto cleanup;
 	}
 	opened = true;
 	
-	if (vfs_stat(fd, &st) != EOK) {
+	rc = vfs_stat(fd, &st);
+	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to fstat %d: %s.", fd,
-		    str_error(errno));
+		    str_error(rc));
 		goto cleanup;
 	}
@@ -229,8 +230,9 @@
 	}
 	
-	ssize_t read_bytes = vfs_read(fd, (aoff64_t []) {0}, buf, len);
-	if (read_bytes <= 0) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to read file '%s' (%d).", conf_path,
-		    errno);
+	size_t read_bytes;
+	rc = vfs_read(fd, (aoff64_t []) {0}, buf, len, &read_bytes);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to read file '%s': %s.", conf_path,
+		    str_error(rc));
 		goto cleanup;
 	}
Index: uspace/srv/devman/util.h
===================================================================
--- uspace/srv/devman/util.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/devman/util.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,6 +35,6 @@
 
 #include <ctype.h>
+#include <stdlib.h>
 #include <str.h>
-#include <malloc.h>
 
 extern char *get_abs_path(const char *, const char *, const char *);
Index: uspace/srv/fs/cdfs/cdfs.c
===================================================================
--- uspace/srv/fs/cdfs/cdfs.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/cdfs/cdfs.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,4 +41,5 @@
 #include <ns.h>
 #include <errno.h>
+#include <str_error.h>
 #include <stdio.h>
 #include <libfs.h>
@@ -83,5 +84,5 @@
 	    &cdfs_libfs_ops);
 	if (rc != EOK) {
-		printf("%s: Failed to register file system (%d)\n", NAME, rc);
+		printf("%s: Failed to register file system: %s\n", NAME, str_error(rc));
 		return rc;
 	}
Index: uspace/srv/fs/cdfs/cdfs_ops.c
===================================================================
--- uspace/srv/fs/cdfs/cdfs_ops.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/cdfs/cdfs_ops.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -42,5 +42,4 @@
 #include <adt/hash_table.h>
 #include <adt/hash.h>
-#include <malloc.h>
 #include <mem.h>
 #include <loc.h>
@@ -49,4 +48,5 @@
 #include <block.h>
 #include <scsi/mmc.h>
+#include <stdlib.h>
 #include <str.h>
 #include <byteorder.h>
@@ -566,5 +566,5 @@
 }
 
-static bool cdfs_readdir(cdfs_t *fs, fs_node_t *fs_node)
+static int cdfs_readdir(cdfs_t *fs, fs_node_t *fs_node)
 {
 	cdfs_node_t *node = CDFS_NODE(fs_node);
@@ -572,5 +572,5 @@
 	
 	if (node->processed)
-		return true;
+		return EOK;
 	
 	uint32_t blocks = node->size / BLOCK_SIZE;
@@ -582,5 +582,5 @@
 		int rc = block_get(&block, fs->service_id, node->lba + i, BLOCK_FLAGS_NONE);
 		if (rc != EOK)
-			return false;
+			return rc;
 		
 		cdfs_dir_t *dir;
@@ -616,6 +616,8 @@
 			int rc = create_node(&fn, fs, dentry_type,
 			    (node->lba + i) * BLOCK_SIZE + offset);
-			if ((rc != EOK) || (fn == NULL))
-				return false;
+			if (rc != EOK)
+				return rc;
+
+			assert(fn != NULL);
 			
 			cdfs_node_t *cur = CDFS_NODE(fn);
@@ -626,5 +628,5 @@
 			    dir->name_length, node->fs->enc, dentry_type);
 			if (name == NULL)
-				return false;
+				return EIO;
 			
 			// FIXME: check return value
@@ -641,5 +643,5 @@
 	
 	node->processed = true;
-	return true;
+	return EOK;
 }
 
@@ -961,5 +963,5 @@
 
 /** Read the volume descriptors. */
-static bool iso_read_vol_desc(service_id_t sid, cdfs_lba_t altroot,
+static int iso_read_vol_desc(service_id_t sid, cdfs_lba_t altroot,
     uint32_t *rlba, uint32_t *rsize, cdfs_enc_t *enc, char **vol_ident)
 {
@@ -968,5 +970,5 @@
 	int rc = block_get(&block, sid, altroot + 16, BLOCK_FLAGS_NONE);
 	if (rc != EOK)
-		return false;
+		return rc;
 	
 	cdfs_vol_desc_t *vol_desc = (cdfs_vol_desc_t *) block->data;
@@ -980,5 +982,5 @@
 	    (vol_desc->version != 1)) {
 		block_put(block);
-		return false;
+		return ENOTSUP;
 	}
 	
@@ -1000,5 +1002,5 @@
 		 */
 		block_put(block);
-		return false;
+		return ENOTSUP;
 	}
 	
@@ -1006,5 +1008,5 @@
 	if (block_size != BLOCK_SIZE) {
 		block_put(block);
-		return false;
+		return ENOTSUP;
 	}
 	
@@ -1031,15 +1033,16 @@
 	
 	block_put(block);
-	return true;
-}
-
-static bool iso_readfs(cdfs_t *fs, fs_node_t *rfn,
+	return EOK;
+}
+
+static int iso_readfs(cdfs_t *fs, fs_node_t *rfn,
     cdfs_lba_t altroot)
 {
 	cdfs_node_t *node = CDFS_NODE(rfn);
 	
-	if (!iso_read_vol_desc(fs->service_id, altroot, &node->lba,
-	    &node->size, &fs->enc, &fs->vol_ident))
-		return false;
+	int rc = iso_read_vol_desc(fs->service_id, altroot, &node->lba,
+	    &node->size, &fs->enc, &fs->vol_ident);
+	if (rc != EOK)
+		return rc;
 	
 	return cdfs_readdir(fs, rfn);
@@ -1072,5 +1075,5 @@
 	
 	/* Check if there is cdfs in given session */
-	if (!iso_readfs(fs, rfn, altroot))
+	if (iso_readfs(fs, rfn, altroot) != EOK)
 		goto error;
 	
@@ -1125,9 +1128,10 @@
 	uint32_t rsize;
 	cdfs_enc_t enc;
-	if (!iso_read_vol_desc(service_id, altroot, &rlba, &rsize, &enc,
-	    &vol_ident)) {
+	rc = iso_read_vol_desc(service_id, altroot, &rlba, &rsize, &enc,
+	    &vol_ident);
+	if (rc != EOK) {
 		block_cache_fini(service_id);
 		block_fini(service_id);
-		return EIO;
+		return rc;
 	}
 	
Index: uspace/srv/fs/exfat/exfat.c
===================================================================
--- uspace/srv/fs/exfat/exfat.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/exfat/exfat.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -43,4 +43,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <task.h>
 #include <stdio.h>
@@ -95,5 +96,5 @@
 
 err:
-	printf(NAME ": Failed to register file system (%d)\n", rc);
+	printf(NAME ": Failed to register file system: %s\n", str_error(rc));
 	return rc;
 }
Index: uspace/srv/fs/exfat/exfat_directory.c
===================================================================
--- uspace/srv/fs/exfat/exfat_directory.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/exfat/exfat_directory.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -43,5 +43,5 @@
 #include <byteorder.h>
 #include <mem.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <str.h>
 #include <align.h>
Index: uspace/srv/fs/exfat/exfat_fat.c
===================================================================
--- uspace/srv/fs/exfat/exfat_fat.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/exfat/exfat_fat.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -48,6 +48,6 @@
 #include <assert.h>
 #include <fibril_synch.h>
-#include <malloc.h>
 #include <mem.h>
+#include <stdlib.h>
 #include <str.h>
 
Index: uspace/srv/fs/exfat/exfat_idx.c
===================================================================
--- uspace/srv/fs/exfat/exfat_idx.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/exfat/exfat_idx.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -45,5 +45,5 @@
 #include <assert.h>
 #include <fibril_synch.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 /** Each instance of this type describes one interval of freed VFS indices. */
Index: uspace/srv/fs/exfat/exfat_ops.c
===================================================================
--- uspace/srv/fs/exfat/exfat_ops.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/exfat/exfat_ops.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -59,6 +59,6 @@
 #include <fibril_synch.h>
 #include <align.h>
-#include <malloc.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 /** Mutex protecting the list of cached free FAT nodes. */
Index: uspace/srv/fs/fat/fat.c
===================================================================
--- uspace/srv/fs/fat/fat.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/fat/fat.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -43,4 +43,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <task.h>
 #include <stdio.h>
@@ -95,5 +96,5 @@
 	
 err:
-	printf(NAME ": Failed to register file system (%d)\n", rc);
+	printf(NAME ": Failed to register file system: %s\n", str_error(rc));
 	return rc;
 }
Index: uspace/srv/fs/fat/fat_fat.c
===================================================================
--- uspace/srv/fs/fat/fat_fat.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/fat/fat_fat.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -48,6 +48,6 @@
 #include <assert.h>
 #include <fibril_synch.h>
-#include <malloc.h>
 #include <mem.h>
+#include <stdlib.h>
 
 #define IS_ODD(number)	(number & 0x1)
Index: uspace/srv/fs/fat/fat_idx.c
===================================================================
--- uspace/srv/fs/fat/fat_idx.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/fat/fat_idx.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -45,5 +45,5 @@
 #include <assert.h>
 #include <fibril_synch.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 /** Each instance of this type describes one interval of freed VFS indices. */
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -56,5 +56,5 @@
 #include <fibril_synch.h>
 #include <align.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 #define FAT_NODE(node)	((node) ? (fat_node_t *) (node)->data : NULL)
Index: uspace/srv/fs/locfs/locfs.c
===================================================================
--- uspace/srv/fs/locfs/locfs.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/locfs/locfs.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,4 +44,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <task.h>
 #include <libfs.h>
@@ -87,5 +88,5 @@
 	    &locfs_libfs_ops);
 	if (rc != EOK) {
-		printf("%s: Failed to register file system (%d)\n", NAME, rc);
+		printf("%s: Failed to register file system: %s\n", NAME, str_error(rc));
 		return rc;
 	}
Index: uspace/srv/fs/locfs/locfs_ops.c
===================================================================
--- uspace/srv/fs/locfs/locfs_ops.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/locfs/locfs_ops.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,5 +39,5 @@
 #include <stdbool.h>
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <str.h>
 #include <libfs.h>
Index: uspace/srv/fs/mfs/mfs.c
===================================================================
--- uspace/srv/fs/mfs/mfs.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/mfs/mfs.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,4 +44,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <task.h>
 #include <stdio.h>
@@ -97,5 +98,5 @@
 
 err:
-	printf(NAME ": Failed to register file system (%d)\n", rc);
+	printf(NAME ": Failed to register file system: %s\n", str_error(rc));
 	return rc;
 }
Index: uspace/srv/fs/mfs/mfs.h
===================================================================
--- uspace/srv/fs/mfs/mfs.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/mfs/mfs.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,7 +39,7 @@
 #include <libfs.h>
 #include <adt/list.h>
-#include <malloc.h>
 #include <mem.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
 #include <assert.h>
Index: uspace/srv/fs/tmpfs/tmpfs.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/tmpfs/tmpfs.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -46,4 +46,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <stdio.h>
 #include <task.h>
@@ -89,5 +90,5 @@
 	    &tmpfs_libfs_ops);
 	if (rc != EOK) {
-		printf(NAME ": Failed to register file system (%d)\n", rc);
+		printf(NAME ": Failed to register file system: %s\n", str_error(rc));
 		return rc;
 	}
Index: uspace/srv/fs/udf/udf.c
===================================================================
--- uspace/srv/fs/udf/udf.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/udf/udf.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,4 +41,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <task.h>
 #include <libfs.h>
@@ -96,5 +97,5 @@
 	
 err:
-	log_msg(LOG_DEFAULT, LVL_FATAL, "Failed to register file system (%d)", rc);
+	log_msg(LOG_DEFAULT, LVL_FATAL, "Failed to register file system: %s", str_error(rc));
 	return rc;
 }
Index: uspace/srv/fs/udf/udf_file.c
===================================================================
--- uspace/srv/fs/udf/udf_file.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/udf/udf_file.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,5 +38,5 @@
 #include <libfs.h>
 #include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <inttypes.h>
 #include <io/log.h>
Index: uspace/srv/fs/udf/udf_idx.c
===================================================================
--- uspace/srv/fs/udf/udf_idx.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/udf/udf_idx.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -40,5 +40,5 @@
 #include <assert.h>
 #include <fibril_synch.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <adt/hash_table.h>
 #include <adt/hash.h>
Index: uspace/srv/fs/udf/udf_ops.c
===================================================================
--- uspace/srv/fs/udf/udf_ops.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/udf/udf_ops.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -51,5 +51,5 @@
 #include <fibril_synch.h>
 #include <align.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <inttypes.h>
 #include <io/log.h>
Index: uspace/srv/fs/udf/udf_osta.c
===================================================================
--- uspace/srv/fs/udf/udf_osta.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/udf/udf_osta.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -45,5 +45,5 @@
  */
 
-#include <malloc.h>
+#include <stdlib.h>
 #include <str.h>
 #include <macros.h>
Index: uspace/srv/fs/udf/udf_volume.c
===================================================================
--- uspace/srv/fs/udf/udf_volume.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/fs/udf/udf_volume.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,6 +39,6 @@
 #include <libfs.h>
 #include <errno.h>
+#include <stdlib.h>
 #include <str.h>
-#include <malloc.h>
 #include <mem.h>
 #include <inttypes.h>
Index: uspace/srv/hid/compositor/compositor.c
===================================================================
--- uspace/srv/hid/compositor/compositor.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/compositor/compositor.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,5 +44,5 @@
 #include <align.h>
 #include <as.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 #include <atomic.h>
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/console/console.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -47,8 +47,8 @@
 #include <io/output.h>
 #include <align.h>
-#include <malloc.h>
 #include <as.h>
 #include <task.h>
 #include <fibril_synch.h>
+#include <stdlib.h>
 #include "console.h"
 
@@ -119,6 +119,6 @@
 static int cons_open(con_srvs_t *, con_srv_t *);
 static int cons_close(con_srv_t *);
-static int cons_read(con_srv_t *, void *, size_t);
-static int cons_write(con_srv_t *, void *, size_t);
+static int cons_read(con_srv_t *, void *, size_t, size_t *);
+static int cons_write(con_srv_t *, void *, size_t, size_t *);
 static void cons_sync(con_srv_t *);
 static void cons_clear(con_srv_t *);
@@ -338,5 +338,5 @@
 }
 
-static int cons_read(con_srv_t *srv, void *buf, size_t size)
+static int cons_read(con_srv_t *srv, void *buf, size_t size, size_t *nread)
 {
 	uint8_t *bbuf = buf;
@@ -378,8 +378,9 @@
 	}
 	
-	return size;
-}
-
-static int cons_write(con_srv_t *srv, void *data, size_t size)
+	*nread = size;
+	return EOK;
+}
+
+static int cons_write(con_srv_t *srv, void *data, size_t size, size_t *nwritten)
 {
 	console_t *cons = srv_to_console(srv);
@@ -389,5 +390,6 @@
 		cons_write_char(cons, str_decode(data, &off, size));
 	
-	return size;
+	*nwritten = size;
+	return EOK;
 }
 
Index: uspace/srv/hid/input/input.c
===================================================================
--- uspace/srv/hid/input/input.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/input/input.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,30 +37,31 @@
  */
 
+#include <adt/fifo.h>
 #include <adt/list.h>
-#include <stdbool.h>
+#include <async.h>
+#include <config.h>
+#include <errno.h>
+#include <fibril.h>
 #include <fibril_synch.h>
+#include <io/chardev.h>
+#include <io/console.h>
+#include <io/keycode.h>
 #include <ipc/services.h>
 #include <ipc/input.h>
-#include <config.h>
+#include <loc.h>
+#include <ns.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <ns.h>
-#include <async.h>
-#include <errno.h>
-#include <adt/fifo.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <loc.h>
 #include <str_error.h>
-#include <char_dev_iface.h>
-#include <fibril.h>
-#include "layout.h"
+
+#include "input.h"
 #include "kbd.h"
 #include "kbd_port.h"
 #include "kbd_ctl.h"
+#include "layout.h"
 #include "mouse.h"
 #include "mouse_proto.h"
 #include "serial.h"
-#include "input.h"
 
 #define NUM_LAYOUTS  4
@@ -364,6 +365,5 @@
 }
 
-static void kconsole_event_handler(ipc_callid_t callid, ipc_call_t *call,
-    void *arg)
+static void kconsole_event_handler(ipc_call_t *call, void *arg)
 {
 	if (IPC_GET_ARG1(*call)) {
@@ -536,6 +536,8 @@
 	while (true) {
 		uint8_t data;
-
-		char_dev_read(sdev->sess, &data, sizeof(data));
+		size_t nread;
+
+		chardev_read(sdev->chardev, &data, sizeof(data), &nread);
+		/* XXX Handle error */
 		kbd_push_data(sdev->kdev, data);
 	}
@@ -552,4 +554,5 @@
 {
 	bool match = false;
+	int rc;
 
 	serial_dev_t *sdev = serial_dev_new();
@@ -559,5 +562,5 @@
 	sdev->kdev->svc_id = service_id;
 	
-	int rc = loc_service_get_name(service_id, &sdev->kdev->svc_name);
+	rc = loc_service_get_name(service_id, &sdev->kdev->svc_name);
 	if (rc != EOK)
 		goto fail;
@@ -582,4 +585,12 @@
 		sdev->sess = loc_service_connect(service_id, INTERFACE_DDF,
 		    IPC_FLAG_BLOCKING);
+
+		rc = chardev_open(sdev->sess, &sdev->chardev);
+		if (rc != EOK) {
+			async_hangup(sdev->sess);
+			sdev->sess = NULL;
+			list_remove(&sdev->link);
+			goto fail;
+		}
 
 		fid_t fid = fibril_create(serial_consumer, sdev);
@@ -816,6 +827,6 @@
 	int rc = loc_register_cat_change_cb(cat_change_cb);
 	if (rc != EOK) {
-		printf("%s: Failed registering callback for device discovery. "
-		    "(%d)\n", NAME, rc);
+		printf("%s: Failed registering callback for device discovery: "
+		    "%s\n", NAME, str_error(rc));
 		return rc;
 	}
Index: uspace/srv/hid/input/port/chardev.c
===================================================================
--- uspace/srv/hid/input/port/chardev.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/input/port/chardev.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,8 +35,9 @@
  */
 
-#include <ipc/char.h>
 #include <async.h>
+#include <errno.h>
+#include <fibril.h>
+#include <io/chardev.h>
 #include <loc.h>
-#include <errno.h>
 #include <stdio.h>
 #include "../input.h"
@@ -44,8 +45,8 @@
 #include "../kbd.h"
 
-static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+static int kbd_port_fibril(void *);
 
 static int chardev_port_init(kbd_dev_t *);
-static void chardev_port_write(uint8_t data);
+static void chardev_port_write(uint8_t);
 
 kbd_port_ops_t chardev_port = {
@@ -56,4 +57,5 @@
 static kbd_dev_t *kbd_dev;
 static async_sess_t *dev_sess;
+static chardev_t *chardev;
 
 /** List of devices to try connecting to. */
@@ -70,6 +72,6 @@
 {
 	service_id_t service_id;
-	async_exch_t *exch;
 	unsigned int i;
+	fid_t fid;
 	int rc;
 	
@@ -96,22 +98,20 @@
 	}
 	
-	exch = async_exchange_begin(dev_sess);
-	if (exch == NULL) {
-		printf("%s: Failed starting exchange with device\n", NAME);
+	rc = chardev_open(dev_sess, &chardev);
+	if (rc != EOK) {
+		printf("%s: Failed opening character device\n", NAME);
 		async_hangup(dev_sess);
 		return ENOMEM;
 	}
 	
-	port_id_t port;
-	rc = async_create_callback_port(exch, INTERFACE_CHAR_CB, 0, 0,
-	    kbd_port_events, NULL, &port);
-	
-	async_exchange_end(exch);
-	
-	if (rc != 0) {
-		printf("%s: Failed to create callback from device\n", NAME);
+	fid = fibril_create(kbd_port_fibril, NULL);
+	if (fid == 0) {
+		printf("%s: Failed creating fibril\n", NAME);
+		chardev_close(chardev);
 		async_hangup(dev_sess);
-		return -1;
+		return ENOMEM;
 	}
+
+	fibril_add_ready(fid);
 	
 	printf("%s: Found input device '%s'\n", NAME, in_devs[i]);
@@ -121,40 +121,32 @@
 static void chardev_port_write(uint8_t data)
 {
-	async_exch_t *exch = async_exchange_begin(dev_sess);
-	if (exch == NULL) {
-		printf("%s: Failed starting exchange with device\n", NAME);
+	int rc;
+	size_t nwr;
+
+	rc = chardev_write(chardev, &data, sizeof(data), &nwr);
+	if (rc != EOK || nwr != sizeof(data)) {
+		printf("%s: Failed writing to character device\n", NAME);
 		return;
-	}
-
-	async_msg_1(exch, CHAR_WRITE_BYTE, data);
-	async_exchange_end(exch);
-}
-
-static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			/* TODO: Handle hangup */
-			return;
-		}
-
-		int retval = EOK;
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case CHAR_NOTIF_BYTE:
-			kbd_push_data(kbd_dev, IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
 	}
 }
 
+static int kbd_port_fibril(void *arg)
+{
+	int rc;
+	size_t nread;
+	uint8_t b;
+
+	while (true) {
+		rc = chardev_read(chardev, &b, sizeof(b), &nread);
+		if (rc != EOK || nread != sizeof(b)) {
+			printf("%s: Error reading data", NAME);
+			continue;
+		}
+
+		kbd_push_data(kbd_dev, b);
+	}
+
+	return 0;
+}
 
 /**
Index: uspace/srv/hid/input/proto/mousedev.c
===================================================================
--- uspace/srv/hid/input/proto/mousedev.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/input/proto/mousedev.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,9 +38,9 @@
 #include <stdio.h>
 #include <vfs/vfs_sess.h>
-#include <malloc.h>
 #include <async.h>
 #include <errno.h>
 #include <ipc/mouseev.h>
 #include <loc.h>
+#include <stdlib.h>
 #include "../mouse.h"
 #include "../mouse_port.h"
Index: uspace/srv/hid/input/serial.h
===================================================================
--- uspace/srv/hid/input/serial.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/input/serial.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,4 +39,5 @@
 
 #include <async.h>
+#include <io/chardev.h>
 #include "kbd.h"
 
@@ -45,4 +46,5 @@
 	link_t link;
 	async_sess_t *sess;
+	chardev_t *chardev;
 } serial_dev_t;
 
Index: uspace/srv/hid/isdv4_tablet/isdv4.c
===================================================================
--- uspace/srv/hid/isdv4_tablet/isdv4.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/isdv4_tablet/isdv4.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -27,9 +27,11 @@
  */
 
-#include <char_dev_iface.h>
+#include <async.h>
 #include <errno.h>
+#include <io/chardev.h>
+#include <mem.h>
+#include <stdbool.h>
+#include <stdint.h>
 #include <stdlib.h>
-#include <mem.h>
-#include <thread.h>
 
 #include "isdv4.h"
@@ -296,9 +298,12 @@
 	bool reading = true;
 	while (reading) {
-		ssize_t read = char_dev_read(state->sess, state->buf + state->buf_end,
-		    state->buf_size - state->buf_end);
-		if (read < 0)
+		size_t nread;
+		int rc;
+
+		rc = chardev_read(state->chardev, state->buf + state->buf_end,
+		    state->buf_size - state->buf_end, &nread);
+		if (rc != EOK && nread == 0)
 			return EIO;
-		state->buf_end += read;
+		state->buf_end += nread;
 
 		size_t i = 0;
@@ -355,7 +360,12 @@
 	return EOK;
 }
-static bool write_command(async_sess_t *sess, uint8_t command)
-{
-	return char_dev_write(sess, &command, 1) == 1;
+
+static bool write_command(chardev_t *chardev, uint8_t command)
+{
+	int rc;
+	size_t nwr;
+
+	rc = chardev_write(chardev, &command, 1, &nwr);
+	return rc == EOK;
 }
 
@@ -363,9 +373,22 @@
     isdv4_event_fn event_fn)
 {
+	chardev_t *chardev;
+	int rc;
+
+	rc = chardev_open(sess, &chardev);
+	if (rc != EOK)
+		return rc;
+
 	memset(state, 0, sizeof(isdv4_state_t));
+
 	state->sess = sess;
+	state->chardev = chardev;
+
 	state->buf = malloc(BUF_SIZE);
-	if (state->buf == NULL)
+	if (state->buf == NULL) {
+		chardev_close(chardev);
 		return ENOMEM;
+	}
+
 	state->buf_size = BUF_SIZE;
 	state->emit_event_fn = event_fn;
@@ -375,11 +398,11 @@
 int isdv4_init_tablet(isdv4_state_t *state)
 {
-	if (!write_command(state->sess, CMD_STOP))
+	if (!write_command(state->chardev, CMD_STOP))
 		return EIO;
 
-	thread_usleep(250000); /* 250 ms */
+	async_usleep(250000); /* 250 ms */
 
 	// FIXME: Read all possible garbage before sending commands
-	if (!write_command(state->sess, CMD_QUERY_STYLUS))
+	if (!write_command(state->chardev, CMD_QUERY_STYLUS))
 		return EIO;
 
@@ -388,5 +411,5 @@
 		return rc;
 
-	if (!write_command(state->sess, CMD_QUERY_TOUCH))
+	if (!write_command(state->chardev, CMD_QUERY_TOUCH))
 		return EIO;
 
@@ -395,5 +418,5 @@
 		return rc;
 
-	if (!write_command(state->sess, CMD_START))
+	if (!write_command(state->chardev, CMD_START))
 		return EIO;
 
Index: uspace/srv/hid/isdv4_tablet/isdv4.h
===================================================================
--- uspace/srv/hid/isdv4_tablet/isdv4.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/isdv4_tablet/isdv4.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -27,6 +27,9 @@
  */
 
-#ifndef __ISDV4_H__
-#define __ISDV4_H__
+#ifndef ISDV4_H_
+#define ISDV4_H_
+
+#include <async.h>
+#include <io/chardev.h>
 
 typedef struct isdv4_event isdv4_event_t;
@@ -56,6 +59,8 @@
 	bool finger1_pressed; /* Reported as touch button 1 */
 
-	/* Session to the serial device */
+	/** Session with the serial device */
 	async_sess_t *sess;
+	/** Character device */
+	chardev_t *chardev;
 
 	/* Receive buffer state */
@@ -64,5 +69,5 @@
 	size_t buf_end;
 
-	/* Callbacks */
+	/** Callbacks */
 	isdv4_event_fn emit_event_fn;
 } isdv4_state_t;
Index: uspace/srv/hid/isdv4_tablet/main.c
===================================================================
--- uspace/srv/hid/isdv4_tablet/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/isdv4_tablet/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -27,13 +27,12 @@
  */
 
-#include <char_dev_iface.h>
+#include <async.h>
 #include <errno.h>
-#include <ipc/serial_ctl.h>
+#include <fibril_synch.h>
+#include <io/serial.h>
+#include <ipc/mouseev.h>
 #include <loc.h>
+#include <stddef.h>
 #include <stdio.h>
-#include <fibril_synch.h>
-#include <abi/ipc/methods.h>
-#include <ipc/mouseev.h>
-#include <inttypes.h>
 #include <task.h>
 
@@ -179,4 +178,5 @@
 	sysarg_t baud = 38400;
 	service_id_t svc_id;
+	serial_t *serial;
 	char *serial_port_name = NULL;
 
@@ -268,11 +268,14 @@
 	if (!sess) {
 		fprintf(stderr, "Failed connecting to service\n");
-	}
-
-	async_exch_t *exch = async_exchange_begin(sess);
-	rc = async_req_4_0(exch, SERIAL_SET_COM_PROPS, baud,
-	    SERIAL_NO_PARITY, 8, 1);
-	async_exchange_end(exch);
-
+		return 2;
+	}
+
+	rc = serial_open(sess, &serial);
+	if (rc != EOK) {
+		fprintf(stderr, "Failed opening serial port\n");
+		return 2;
+	}
+
+	rc = serial_set_comm_props(serial, baud, SERIAL_NO_PARITY, 8, 1);
 	if (rc != EOK) {
 		fprintf(stderr, "Failed setting serial properties\n");
Index: uspace/srv/hid/output/Makefile
===================================================================
--- uspace/srv/hid/output/Makefile	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/output/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,7 +35,4 @@
 	ctl/serial.c \
 	port/ega.c \
-	port/kchar.c \
-	port/niagara.c \
-	port/ski.c \
 	port/chardev.c \
 	proto/vt100.c \
Index: uspace/srv/hid/output/ctl/serial.c
===================================================================
--- uspace/srv/hid/output/ctl/serial.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/output/ctl/serial.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -105,4 +105,11 @@
 }
 
+static void serial_flush(outdev_t *dev)
+{
+	vt100_state_t *state = (vt100_state_t *) dev->data;
+
+	vt100_flush(state);
+}
+
 static outdev_ops_t serial_ops = {
 	.yield = serial_yield,
@@ -111,13 +118,14 @@
 	.get_caps = serial_get_caps,
 	.cursor_update = serial_cursor_update,
-	.char_update = serial_char_update
+	.char_update = serial_char_update,
+	.flush = serial_flush
 };
 
 int serial_init(vt100_putchar_t putchar_fn,
-    vt100_control_puts_t control_puts_fn)
+    vt100_control_puts_t control_puts_fn, vt100_flush_t flush_fn)
 {
 	vt100_state_t *state =
 	    vt100_state_create(SERIAL_COLS, SERIAL_ROWS, putchar_fn,
-	    control_puts_fn);
+	    control_puts_fn, flush_fn);
 	if (state == NULL)
 		return ENOMEM;
Index: uspace/srv/hid/output/ctl/serial.h
===================================================================
--- uspace/srv/hid/output/ctl/serial.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/output/ctl/serial.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,5 @@
 #include "../proto/vt100.h"
 
-extern int serial_init(vt100_putchar_t, vt100_control_puts_t);
+extern int serial_init(vt100_putchar_t, vt100_control_puts_t, vt100_flush_t);
 
 #endif
Index: uspace/srv/hid/output/output.c
===================================================================
--- uspace/srv/hid/output/output.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/output/output.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -27,7 +27,7 @@
  */
 
+#include <errno.h>
 #include <stddef.h>
-#include <errno.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <macros.h>
 #include <as.h>
@@ -36,7 +36,4 @@
 #include <config.h>
 #include "port/ega.h"
-#include "port/kchar.h"
-#include "port/niagara.h"
-#include "port/ski.h"
 #include "port/chardev.h"
 #include "output.h"
@@ -222,4 +219,6 @@
 		dev->ops.cursor_update(dev, prev_col, prev_row, col, row,
 		    visible);
+		dev->ops.flush(dev);
+
 	}
 	
@@ -345,5 +344,8 @@
 			}
 		}
-	}
+		
+		dev->ops.flush(dev);
+	}
+	
 	
 	async_answer_0(iid, EOK);
@@ -383,6 +385,7 @@
 			}
 		}
-	}
-	
+		dev->ops.flush(dev);
+
+	}
 	async_answer_0(iid, EOK);
 }
@@ -479,10 +482,7 @@
 	if (!config_key_exists("console")) {
 		ega_init();
-		kchar_init();
-		niagara_init();
-		ski_init();
-	} else {
-		chardev_init();
-	}
+	}
+	
+	chardev_init();
 	
 	printf("%s: Accepting connections\n", NAME);
Index: uspace/srv/hid/output/output.h
===================================================================
--- uspace/srv/hid/output/output.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/output/output.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -52,4 +52,5 @@
 	    sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible);
 	void (* char_update)(struct outdev *dev, sysarg_t col, sysarg_t row);
+	void (* flush)(struct outdev *dev);
 } outdev_ops_t;
 
Index: uspace/srv/hid/output/port/chardev.c
===================================================================
--- uspace/srv/hid/output/port/chardev.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/output/port/chardev.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2016 Jakub Jermar
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -30,23 +31,32 @@
  */
 
+#include <async.h>
+#include <config.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/chardev.h>
+#include <loc.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <char_dev_iface.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <async.h>
-#include <fibril_synch.h>
-#include <loc.h>
-#include <errno.h>
 #include <str.h>
-#include <config.h>
 #include "../ctl/serial.h"
 #include "../output.h"
 #include "chardev.h"
 
+enum {
+	chardev_buf_size = 4096
+};
+
 static char *console;
 
 static async_sess_t *sess;
+static chardev_t *chardev;
 static service_id_t serial_cat_id;
+static service_id_t console_cat_id;
+
+static uint8_t chardev_buf[chardev_buf_size];
+static size_t chardev_bused;
 
 static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
@@ -54,13 +64,87 @@
 static FIBRIL_CONDVAR_INITIALIZE(discovery_cv);
 
+static void chardev_flush(void)
+{
+	size_t nwr;
+
+	if (chardev_bused == 0)
+		return;
+
+	chardev_write(chardev, chardev_buf, chardev_bused, &nwr);
+	/* XXX Handle error */
+
+	chardev_bused = 0;
+}
+
 static void chardev_putchar(wchar_t ch)
 {
-	uint8_t byte = (uint8_t) ch;
-	char_dev_write(sess, &byte, 1); 
+	if (chardev_bused == chardev_buf_size)
+		chardev_flush();
+	if (!ascii_check(ch))
+		ch = '?';
+	chardev_buf[chardev_bused++] = (uint8_t) ch;
 }
 
 static void chardev_control_puts(const char *str)
 {
-	char_dev_write(sess, (void *) str, str_size(str));
+	const char *p;
+
+	p = str;
+	while (*p != '\0')
+		chardev_putchar(*p++);
+}
+
+static bool find_output_dev(service_id_t *svcid)
+{
+	service_id_t *svc;
+	size_t svcs;
+	int rc;
+
+	rc = loc_category_get_svcs(serial_cat_id, &svc, &svcs);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&discovery_lock);
+		printf("%s: Failed to get services\n", NAME);
+		return false;
+	}
+
+	for (size_t i = 0; i < svcs; i++) {
+		char *name;
+
+		rc = loc_service_get_name(svc[i], &name);
+		if (rc != EOK)
+			continue;
+
+		if (!str_cmp(console, name)) {
+			/*
+			 * This is the serial console service that the user
+			 * wanted to use.
+			 */
+			*svcid = svc[i];
+			free(svc);
+			return true;
+		}
+
+		free(name);
+	}
+
+	free(svc);
+
+	/* Look for any service in the 'console' category */
+
+	rc = loc_category_get_svcs(console_cat_id, &svc, &svcs);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&discovery_lock);
+		printf("%s: Failed to get services\n", NAME);
+		return false;
+	}
+
+	if (svcs > 0) {
+		*svcid = svc[0];
+		free(svc);
+		return true;
+	}
+
+	free(svc);
+	return false;
 }
 
@@ -74,4 +158,6 @@
 {
 	int rc;
+	bool found;
+	service_id_t sid;
 
 	fibril_mutex_lock(&discovery_lock);
@@ -82,41 +168,19 @@
 	}
 
-	service_id_t *svc;
-	size_t svcs;
-	rc = loc_category_get_svcs(serial_cat_id, &svc, &svcs);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&discovery_lock);
-		printf("%s: Failed to get services\n", NAME);
-		return;
-	}
-
-	service_id_t sid;
-	bool found = false;
-
-	for (size_t i = 0; i < svcs && !found; i++) {
-		char *name;
-		
-		rc = loc_service_get_name(svc[i], &name);
-		if (rc != EOK)
-			continue;
-
-		if (!str_cmp(console, name)) {
-			/*
-			 * This is the serial console service that the user
-			 * wanted to use.
-			 */
-			found = true;
-			sid = svc[i];
-		}
-			
-		free(name);
-	}
-
-	free(svc);
-
+	found = find_output_dev(&sid);
 	if (!found) {
 		fibril_mutex_unlock(&discovery_lock);
 		return;
 	}
+
+	printf("%s: Connecting service %zu\n", NAME, sid);
+	char *name;
+	rc = loc_service_get_name(sid, &name);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&discovery_lock);
+		return;
+	}
+	printf("%s: Service name is %s\n", NAME, name);
+	free(name);
 
 	sess = loc_service_connect(sid, INTERFACE_DDF, IPC_FLAG_BLOCKING);
@@ -126,5 +190,13 @@
 		return;
 	}
-	serial_init(chardev_putchar, chardev_control_puts);
+
+	rc = chardev_open(sess, &chardev);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&discovery_lock);
+		printf("%s: Failed opening character device\n", NAME);
+		return;
+	}
+
+	serial_init(chardev_putchar, chardev_control_puts, chardev_flush);
 
 	discovery_finished = true;
@@ -135,10 +207,19 @@
 int chardev_init(void)
 {
-	console = config_get_value("console");
-	if (!console) {
-		/*
-		 * The system is not configured to use serial console.
-		 */
+	if (!config_key_exists("console")) {
+		console = NULL;
+#ifdef MACHINE_ski
+		/* OK */
+#elif defined(UARCH_sparc64) && defined(PROCESSOR_sun4v)
+		/* OK */
+#elif defined(MACHINE_msim)
+		/* OK */
+#else
 		return EOK;
+#endif
+	} else {
+		console = config_get_value("console");
+		if (!console)
+			return EOK;
 	}
 
@@ -149,4 +230,10 @@
 	} 
 
+	rc = loc_category_get_id("console", &console_cat_id, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf("%s: Failed to get \"console\" category ID.\n", NAME);
+		return rc;
+	} 
+
 	rc = loc_register_cat_change_cb(check_for_dev);
 	if (rc != EOK) {
@@ -155,4 +242,6 @@
 		return rc;
 	}
+
+	check_for_dev();
 
 	fibril_mutex_lock(&discovery_lock);
Index: uspace/srv/hid/output/port/ega.c
===================================================================
--- uspace/srv/hid/output/port/ega.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/output/port/ega.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -169,4 +169,8 @@
 }
 
+static void ega_flush(outdev_t *dev)
+{
+}
+
 static outdev_ops_t ega_ops = {
 	.yield = ega_yield,
@@ -175,5 +179,6 @@
 	.get_caps = ega_get_caps,
 	.cursor_update = ega_cursor_update,
-	.char_update = ega_char_update
+	.char_update = ega_char_update,
+	.flush = ega_flush
 };
 
Index: pace/srv/hid/output/port/kchar.c
===================================================================
--- uspace/srv/hid/output/port/kchar.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,98 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * Copyright (c) 2008 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.
- */
-
-/** @file
- */
-
-#include <stdint.h>
-#include <errno.h>
-#include <str.h>
-#include <sysinfo.h>
-#include <ddi.h>
-#include <align.h>
-#include <as.h>
-#include "../ctl/serial.h"
-#include "kchar.h"
-
-typedef struct {
-	uint8_t *addr;
-} kchar_t;
-
-static kchar_t kchar;
-
-static void kchar_putchar(wchar_t ch)
-{
-	if (ascii_check(ch))
-		*kchar.addr = ch;
-	else
-		*kchar.addr = '?';
-}
-
-static void kchar_control_puts(const char *str)
-{
-	while (*str)
-		*kchar.addr = *(str++);
-}
-
-int kchar_init(void)
-{
-	sysarg_t present;
-	int rc = sysinfo_get_value("fb", &present);
-	if (rc != EOK)
-		present = false;
-	
-	if (!present)
-		return ENOENT;
-	
-	sysarg_t kind;
-	rc = sysinfo_get_value("fb.kind", &kind);
-	if (rc != EOK)
-		kind = (sysarg_t) -1;
-	
-	if (kind != 3)
-		return EINVAL;
-	
-	sysarg_t paddr;
-	rc = sysinfo_get_value("fb.address.physical", &paddr);
-	if (rc != EOK)
-		return rc;
-	
-	kchar.addr = AS_AREA_ANY;
-	
-	rc = physmem_map(paddr,
-	    ALIGN_UP(1, PAGE_SIZE) >> PAGE_WIDTH,
-	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kchar.addr);
-	if (rc != EOK)
-		return rc;
-	
-	return serial_init(kchar_putchar, kchar_control_puts);
-}
-
-/** @}
- */
Index: pace/srv/hid/output/port/kchar.h
===================================================================
--- uspace/srv/hid/output/port/kchar.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,41 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * Copyright (c) 2008 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.
- */
-
-/** @file
- */
-
-#ifndef OUTPUT_PORT_KCHAR_H_
-#define OUTPUT_PORT_KCHAR_H_
-
-extern int kchar_init(void);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/hid/output/port/kfb.c
===================================================================
--- uspace/srv/hid/output/port/kfb.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/output/port/kfb.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,5 +41,5 @@
 #include <sysinfo.h>
 #include <ddi.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <mem.h>
 #include <as.h>
Index: pace/srv/hid/output/port/niagara.c
===================================================================
--- uspace/srv/hid/output/port/niagara.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,117 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * Copyright (c) 2008 Martin Decky
- * Copyright (c) 2008 Pavel Rimsky
- * 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.
- */
-
-/** @file
- */
-
-#include <stdint.h>
-#include <errno.h>
-#include <sysinfo.h>
-#include <ddi.h>
-#include <as.h>
-#include <align.h>
-#include <str.h>
-#include "../ctl/serial.h"
-#include "niagara.h"
-
-#define OUTPUT_FIFO_SIZE  ((PAGE_SIZE) - 2 * sizeof(uint64_t))
-
-typedef volatile struct {
-	uint64_t read_ptr;
-	uint64_t write_ptr;
-	char data[OUTPUT_FIFO_SIZE];
-} __attribute__((packed)) output_fifo_t;
-
-typedef struct {
-	output_fifo_t *fifo;
-} niagara_t;
-
-static niagara_t niagara;
-
-static void niagara_putc(const char c)
-{
-	while (niagara.fifo->write_ptr ==
-	    (niagara.fifo->read_ptr + OUTPUT_FIFO_SIZE - 1)
-	    % OUTPUT_FIFO_SIZE);
-	
-	niagara.fifo->data[niagara.fifo->write_ptr] = c;
-	niagara.fifo->write_ptr =
-	    ((niagara.fifo->write_ptr) + 1) % OUTPUT_FIFO_SIZE;
-}
-
-static void niagara_putchar(wchar_t ch)
-{
-	if (ascii_check(ch))
-		niagara_putc(ch);
-	else
-		niagara_putc('?');
-}
-
-static void niagara_control_puts(const char *str)
-{
-	while (*str)
-		niagara_putc(*(str++));
-}
-
-int niagara_init(void)
-{
-	sysarg_t present;
-	int rc = sysinfo_get_value("fb", &present);
-	if (rc != EOK)
-		present = false;
-	
-	if (!present)
-		return ENOENT;
-	
-	sysarg_t kind;
-	rc = sysinfo_get_value("fb.kind", &kind);
-	if (rc != EOK)
-		kind = (sysarg_t) -1;
-	
-	if (kind != 5)
-		return EINVAL;
-	
-	sysarg_t paddr;
-	rc = sysinfo_get_value("niagara.outbuf.address", &paddr);
-	if (rc != EOK)
-		return rc;
-	
-	niagara.fifo = (output_fifo_t *) AS_AREA_ANY;
-	
-	rc = physmem_map(paddr, 1, AS_AREA_READ | AS_AREA_WRITE,
-	    (void *) &niagara.fifo);
-	if (rc != EOK)
-		return rc;
-	
-	return serial_init(niagara_putchar, niagara_control_puts);
-}
-
-/** @}
- */
Index: pace/srv/hid/output/port/niagara.h
===================================================================
--- uspace/srv/hid/output/port/niagara.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,40 +1,0 @@
-/*
- * Copyright (c) 2008 Pavel Rimsky
- * 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.
- */
-
-/** @file
- */
-
-#ifndef OUTPUT_PORT_NIAGARA_H_
-#define OUTPUT_PORT_NIAGARA_H_
-
-extern int niagara_init(void);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hid/output/port/ski.c
===================================================================
--- uspace/srv/hid/output/port/ski.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,110 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * Copyright (c) 2008 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.
- */
-
-/** @file
- */
-
-#include <errno.h>
-#include <sysinfo.h>
-#include "../ctl/serial.h"
-#include "ski.h"
-
-#ifdef UARCH_ia64
-
-#define SKI_PUTCHAR  31
-
-/** Display character on ski debug console
- *
- * Use SSC (Simulator System Call) to
- * display character on debug console.
- *
- * @param c Character to be printed.
- *
- */
-static void ski_putc(const char c)
-{
-	asm volatile (
-		"mov r15 = %0\n"
-		"mov r32 = %1\n"   /* r32 is in0 */
-		"break 0x80000\n"  /* modifies r8 */
-		:
-		: "i" (SKI_PUTCHAR), "r" (c)
-		: "r15", "in0", "r8"
-	);
-	
-	if (c == '\n')
-		ski_putc('\r');
-}
-
-static void ski_putchar(wchar_t ch)
-{
-	if ((ch >= 0) && (ch < 128))
-		ski_putc(ch);
-	else
-		ski_putc('?');
-}
-
-static void ski_control_puts(const char *str)
-{
-	while (*str)
-		ski_putc(*(str++));
-}
-
-int ski_init(void)
-{
-	sysarg_t present;
-	int rc = sysinfo_get_value("fb", &present);
-	if (rc != EOK)
-		present = false;
-	
-	if (!present)
-		return ENOENT;
-	
-	sysarg_t kind;
-	rc = sysinfo_get_value("fb.kind", &kind);
-	if (rc != EOK)
-		kind = (sysarg_t) -1;
-	
-	if (kind != 6)
-		return EINVAL;
-	
-	return serial_init(ski_putchar, ski_control_puts);
-}
-
-#else /* UARCH_ia64 */
-
-int ski_init(void)
-{
-	return ENOENT;
-}
-
-#endif
-
-/** @}
- */
Index: pace/srv/hid/output/port/ski.h
===================================================================
--- uspace/srv/hid/output/port/ski.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ 	(revision )
@@ -1,44 +1,0 @@
-/*
- * Copyright (c) 2008 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 console
- * @{
- */
-/**
- * @file
- */
-
-#ifndef OUTPUT_PORT_SKI_H_
-#define OUTPUT_PORT_SKI_H_
-
-extern int ski_init(void);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/hid/output/proto/vt100.c
===================================================================
--- uspace/srv/hid/output/proto/vt100.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/output/proto/vt100.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -32,7 +32,7 @@
 #include <inttypes.h>
 #include <errno.h>
+#include <stddef.h>
 #include <stdio.h>
-#include <stddef.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <io/color.h>
 #include <types/common.h>
@@ -139,5 +139,6 @@
 
 vt100_state_t *vt100_state_create(sysarg_t cols, sysarg_t rows,
-    vt100_putchar_t putchar_fn, vt100_control_puts_t control_puts_fn)
+    vt100_putchar_t putchar_fn, vt100_control_puts_t control_puts_fn,
+	vt100_flush_t flush_fn)
 {
 	vt100_state_t *state = malloc(sizeof(vt100_state_t));
@@ -147,4 +148,5 @@
 	state->putchar = putchar_fn;
 	state->control_puts = control_puts_fn;
+	state->flush = flush_fn;
 	
 	state->cols = cols;
@@ -228,4 +230,9 @@
 }
 
+void vt100_flush(vt100_state_t *state)
+{
+	state->flush();
+}
+
 /** @}
  */
Index: uspace/srv/hid/output/proto/vt100.h
===================================================================
--- uspace/srv/hid/output/proto/vt100.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/output/proto/vt100.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,4 +37,5 @@
 typedef void (* vt100_putchar_t)(wchar_t ch);
 typedef void (* vt100_control_puts_t)(const char *str);
+typedef void (* vt100_flush_t)(void);
 
 typedef struct {
@@ -48,8 +49,9 @@
 	vt100_putchar_t putchar;
 	vt100_control_puts_t control_puts;
+	vt100_flush_t flush;
 } vt100_state_t;
 
 extern vt100_state_t *vt100_state_create(sysarg_t, sysarg_t, vt100_putchar_t,
-    vt100_control_puts_t);
+    vt100_control_puts_t, vt100_flush_t);
 extern void vt100_state_destroy(vt100_state_t *);
 
@@ -62,4 +64,5 @@
 extern void vt100_cursor_visibility(vt100_state_t *, bool);
 extern void vt100_putchar(vt100_state_t *, wchar_t);
+extern void vt100_flush(vt100_state_t *);
 
 #endif
Index: uspace/srv/hid/remcons/remcons.c
===================================================================
--- uspace/srv/hid/remcons/remcons.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/remcons/remcons.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -72,5 +72,5 @@
 static int remcons_open(con_srvs_t *, con_srv_t *);
 static int remcons_close(con_srv_t *);
-static int remcons_write(con_srv_t *, void *, size_t);
+static int remcons_write(con_srv_t *, void *, size_t, size_t *);
 static void remcons_sync(con_srv_t *);
 static void remcons_clear(con_srv_t *);
@@ -137,5 +137,5 @@
 }
 
-static int remcons_write(con_srv_t *srv, void *data, size_t size)
+static int remcons_write(con_srv_t *srv, void *data, size_t size, size_t *nwritten)
 {
 	telnet_user_t *user = srv_to_user(srv);
@@ -146,5 +146,6 @@
 		return rc;
 
-	return size;
+	*nwritten = size;
+	return EOK;
 }
 
Index: uspace/srv/hid/remcons/user.c
===================================================================
--- uspace/srv/hid/remcons/user.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/remcons/user.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -34,4 +34,5 @@
 #include <async.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <adt/prodcons.h>
 #include <errno.h>
@@ -40,5 +41,4 @@
 #include <io/keycode.h>
 #include <align.h>
-#include <malloc.h>
 #include <as.h>
 #include <fibril_synch.h>
Index: uspace/srv/hid/rfb/rfb.c
===================================================================
--- uspace/srv/hid/rfb/rfb.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/rfb/rfb.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -418,8 +418,8 @@
 }
 
-static ssize_t rfb_tile_encode_raw(rfb_t *rfb, cpixel_ctx_t *cpixel,
+static size_t rfb_tile_encode_raw(rfb_t *rfb, cpixel_ctx_t *cpixel,
     rfb_rectangle_t *tile, void *buf)
 {
-	ssize_t size = tile->width * tile->height * cpixel->size;
+	size_t size = tile->width * tile->height * cpixel->size;
 	if (buf == NULL)
 		return size;
@@ -435,6 +435,6 @@
 }
 
-static ssize_t rfb_tile_encode_solid(rfb_t *rfb, cpixel_ctx_t *cpixel,
-    rfb_rectangle_t *tile, void *buf)
+static size_t rfb_tile_encode_solid(rfb_t *rfb, cpixel_ctx_t *cpixel,
+    rfb_rectangle_t *tile, void *buf, size_t *size)
 {
 	/* Check if it is single color */
@@ -443,5 +443,5 @@
 		for (uint16_t x = tile->x; x < tile->x + tile->width; x++) {
 			if (pixelmap_get_pixel(&rfb->framebuffer, x, y) != the_color)
-				return -1;
+				return EINVAL;
 		}
 	}
@@ -450,5 +450,6 @@
 	if (buf)
 		cpixel_encode(rfb, cpixel, buf, the_color);
-	return cpixel->size;
+	*size = cpixel->size;
+	return EOK;
 }
 
@@ -474,6 +475,8 @@
 			
 			uint8_t tile_enctype = RFB_TILE_ENCODING_SOLID;
-			ssize_t tile_size = rfb_tile_encode_solid(rfb, &cpixel, &tile, buf);
-			if (tile_size < 0) {
+			size_t tile_size;
+			int rc = rfb_tile_encode_solid(rfb, &cpixel, &tile, buf,
+			    &tile_size);
+			if (rc != EOK) {
 				tile_size = rfb_tile_encode_raw(rfb, &cpixel, &tile, buf);
 				tile_enctype = RFB_TILE_ENCODING_RAW;
@@ -598,5 +601,6 @@
 	int rc = tcp_conn_send(conn, "RFB 003.008\n", 12);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending server version %d", rc);
+		log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending server version: %s",
+		    str_error(rc));
 		return;
 	}
@@ -605,5 +609,6 @@
 	rc = recv_chars(conn, client_version, 12);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving client version: %d", rc);
+		log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving client version: %s",
+		    str_error(rc));
 		return;
 	}
@@ -623,5 +628,5 @@
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_WARN,
-		    "Failed sending security handshake: %d", rc);
+		    "Failed sending security handshake: %s", str_error(rc));
 		return;
 	}
@@ -630,5 +635,6 @@
 	rc = recv_char(conn, &selected_sec_type);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving security type: %d", rc);
+		log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving security type: %s",
+		    str_error(rc));
 		return;
 	}
@@ -641,5 +647,6 @@
 	rc = tcp_conn_send(conn, &security_result, sizeof(uint32_t));
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending security result: %d", rc);
+		log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending security result: %s",
+		    str_error(rc));
 		return;
 	}
@@ -649,5 +656,6 @@
 	rc = recv_char(conn, &shared_flag);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving client init: %d", rc);
+		log_msg(LOG_DEFAULT, LVL_WARN, "Failed receiving client init: %s",
+		    str_error(rc));
 		return;
 	}
@@ -672,5 +680,6 @@
 	rc = tcp_conn_send(conn, server_init, msg_length);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending server init: %d", rc);
+		log_msg(LOG_DEFAULT, LVL_WARN, "Failed sending server init: %s",
+		    str_error(rc));
 		return;
 	}
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -71,5 +71,5 @@
 static void s3c24xx_ts_connection(ipc_callid_t iid, ipc_call_t *icall,
     void *arg);
-static void s3c24xx_ts_irq_handler(ipc_callid_t iid, ipc_call_t *call, void *);
+static void s3c24xx_ts_irq_handler(ipc_call_t *call, void *);
 static void s3c24xx_ts_pen_down(s3c24xx_ts_t *ts);
 static void s3c24xx_ts_pen_up(s3c24xx_ts_t *ts);
@@ -137,5 +137,5 @@
 	    (void *) ts->paddr, inr);
 
-	async_irq_subscribe(inr, s3c24xx_ts_irq_handler, NULL, &ts_irq_code);
+	async_irq_subscribe(inr, s3c24xx_ts_irq_handler, NULL, &ts_irq_code, NULL);
 
 	s3c24xx_ts_wait_for_int_mode(ts, updn_down);
@@ -202,10 +202,9 @@
 
 /** Handle touchscreen interrupt */
-static void s3c24xx_ts_irq_handler(ipc_callid_t iid, ipc_call_t *call,
-    void *arg)
+static void s3c24xx_ts_irq_handler(ipc_call_t *call, void *arg)
 {
 	ts_updn_t updn;
 
-	(void) iid; (void) call;
+	(void) call;
 
 	/* Read up/down interrupt flags. */
Index: uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c
===================================================================
--- uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -27,7 +27,4 @@
  */
 
-/** @addtogroup driver_serial
- * @{
- */
 /**
  * @file
@@ -37,13 +34,13 @@
  */
 
+#include <async.h>
 #include <ddi.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <io/chardev_srv.h>
 #include <loc.h>
-#include <ipc/char.h>
-#include <async.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sysinfo.h>
-#include <errno.h>
-#include <inttypes.h>
 #include "s3c24xx_uart.h"
 
@@ -68,13 +65,21 @@
 
 static void s3c24xx_uart_connection(ipc_callid_t, ipc_call_t *, void *);
-static void s3c24xx_uart_irq_handler(ipc_callid_t, ipc_call_t *, void *);
+static void s3c24xx_uart_irq_handler(ipc_call_t *, void *);
 static int s3c24xx_uart_init(s3c24xx_uart_t *);
 static void s3c24xx_uart_sendb(s3c24xx_uart_t *, uint8_t);
 
+static int s3c24xx_uart_read(chardev_srv_t *, void *, size_t, size_t *);
+static int s3c24xx_uart_write(chardev_srv_t *, const void *, size_t, size_t *);
+
+static chardev_ops_t s3c24xx_uart_chardev_ops = {
+	.read = s3c24xx_uart_read,
+	.write = s3c24xx_uart_write
+};
+
 int main(int argc, char *argv[])
 {
 	printf("%s: S3C24xx on-chip UART driver\n", NAME);
 	
-	async_set_fallback_port_handler(s3c24xx_uart_connection, NULL);
+	async_set_fallback_port_handler(s3c24xx_uart_connection, uart);
 	int rc = loc_server_register(NAME);
 	if (rc != EOK) {
@@ -111,45 +116,14 @@
     void *arg)
 {
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		sysarg_t method = IPC_GET_IMETHOD(call);
-		
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		async_sess_t *sess =
-		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
-		if (sess != NULL) {
-			if (uart->client_sess == NULL) {
-				uart->client_sess = sess;
-				async_answer_0(callid, EOK);
-			} else
-				async_answer_0(callid, ELIMIT);
-		} else {
-			switch (method) {
-			case CHAR_WRITE_BYTE:
-				printf(NAME ": write %" PRIun " to device\n",
-				    IPC_GET_ARG1(call));
-				s3c24xx_uart_sendb(uart, (uint8_t) IPC_GET_ARG1(call));
-				async_answer_0(callid, EOK);
-				break;
-			default:
-				async_answer_0(callid, EINVAL);
-			}
-		}
-	}
-}
-
-static void s3c24xx_uart_irq_handler(ipc_callid_t iid, ipc_call_t *call,
-    void *arg)
-{
-	(void) iid;
+	s3c24xx_uart_t *uart = (s3c24xx_uart_t *) arg;
+
+	chardev_conn(iid, icall, &uart->cds);
+}
+
+
+static void s3c24xx_uart_irq_handler(ipc_call_t *call, void *arg)
+{
+	int rc;
+
 	(void) call;
 	(void) arg;
@@ -159,9 +133,12 @@
 		uint32_t status = pio_read_32(&uart->io->uerstat);
 
-		if (uart->client_sess != NULL) {
-			async_exch_t *exch = async_exchange_begin(uart->client_sess);
-			async_msg_1(exch, CHAR_NOTIF_BYTE, data);
-			async_exchange_end(exch);
-		}
+		fibril_mutex_lock(&uart->buf_lock);
+
+		rc = circ_buf_push(&uart->cbuf, &data);
+		if (rc != EOK)
+			printf(NAME ": Buffer overrun\n");
+
+		fibril_mutex_unlock(&uart->buf_lock);
+		fibril_condvar_broadcast(&uart->buf_cv);
 
 		if (status != 0)
@@ -176,4 +153,8 @@
 	sysarg_t inr;
 
+	circ_buf_init(&uart->cbuf, uart->buf, s3c24xx_uart_buf_size, 1);
+	fibril_mutex_initialize(&uart->buf_lock);
+	fibril_condvar_initialize(&uart->buf_cv);
+
 	if (sysinfo_get_value("s3c24xx_uart.address.physical",
 	    &uart->paddr) != EOK)
@@ -188,10 +169,9 @@
 
 	uart->io = vaddr;
-	uart->client_sess = NULL;
 
 	printf(NAME ": device at physical address %p, inr %" PRIun ".\n",
 	    (void *) uart->paddr, inr);
 
-	async_irq_subscribe(inr, s3c24xx_uart_irq_handler, NULL, &uart_irq_code);
+	async_irq_subscribe(inr, s3c24xx_uart_irq_handler, NULL, &uart_irq_code, NULL);
 
 	/* Enable FIFO, Tx trigger level: empty, Rx trigger level: 1 byte. */
@@ -203,4 +183,8 @@
 	    pio_read_32(&uart->io->ucon) & ~UCON_RX_INT_LEVEL);
 
+	chardev_srvs_init(&uart->cds);
+	uart->cds.ops = &s3c24xx_uart_chardev_ops;
+	uart->cds.sarg = uart;
+
 	return EOK;
 }
@@ -216,4 +200,46 @@
 }
 
+static int s3c24xx_uart_read(chardev_srv_t *srv, void *buf, size_t size,
+    size_t *nread)
+{
+	s3c24xx_uart_t *uart = (s3c24xx_uart_t *) srv->srvs->sarg;
+	size_t p;
+	uint8_t *bp = (uint8_t *) buf;
+	int rc;
+
+	fibril_mutex_lock(&uart->buf_lock);
+
+	while (circ_buf_nused(&uart->cbuf) == 0)
+		fibril_condvar_wait(&uart->buf_cv, &uart->buf_lock);
+
+	p = 0;
+	while (p < size) {
+		rc = circ_buf_pop(&uart->cbuf, &bp[p]);
+		if (rc != EOK)
+			break;
+		++p;
+	}
+
+	fibril_mutex_unlock(&uart->buf_lock);
+
+	*nread = p;
+	return EOK;
+}
+
+static int s3c24xx_uart_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwr)
+{
+	s3c24xx_uart_t *uart = (s3c24xx_uart_t *) srv->srvs->sarg;
+	size_t i;
+	uint8_t *dp = (uint8_t *) data;
+
+	for (i = 0; i < size; i++)
+		s3c24xx_uart_sendb(uart, dp[i]); 
+
+	*nwr = size;
+	return EOK;
+}
+
+
 /** @}
  */
Index: uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.h
===================================================================
--- uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,6 +38,9 @@
 #define S3C24XX_UART_H_
 
+#include <adt/circ_buf.h>
+#include <async.h>
+#include <fibril_synch.h>
+#include <io/chardev_srv.h>
 #include <stdint.h>
-#include <async.h>
 
 /** S3C24xx UART I/O */
@@ -76,4 +79,7 @@
 #define UFCON_FIFO_ENABLE		0x01
 
+enum {
+	s3c24xx_uart_buf_size = 64
+};
 
 /** S3C24xx UART instance */
@@ -85,9 +91,18 @@
 	s3c24xx_uart_io_t *io;
 
-	/** Callback session to the client */
-	async_sess_t *client_sess;
+	/** Character device service */
+	chardev_srvs_t cds;
 
 	/** Service ID */
 	service_id_t service_id;
+
+	/** Circular buffer */
+	circ_buf_t cbuf;
+	/** Buffer */
+	uint8_t buf[s3c24xx_uart_buf_size];
+	/** Buffer lock */
+	fibril_mutex_t buf_lock;
+	/** Signal newly added data in buffer */
+	fibril_condvar_t buf_cv;
 } s3c24xx_uart_t;
 
Index: uspace/srv/klog/klog.c
===================================================================
--- uspace/srv/klog/klog.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/klog/klog.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,5 +44,5 @@
 #include <io/klog.h>
 #include <sysinfo.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <fibril_synch.h>
 #include <adt/list.h>
@@ -100,13 +100,12 @@
 static void producer(void)
 {
-	int read = klog_read(buffer, BUFFER_SIZE);
-	
-	if (read < 0) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "klog_read failed, rc = %d",
-		    read);
+	size_t len = 0;
+	int rc = klog_read(buffer, BUFFER_SIZE, &len);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "klog_read failed, rc = %s",
+		    str_error_name(rc));
 		return;
 	}
 	
-	size_t len = read;
 	size_t offset = 0;
 	while (offset < len) {
@@ -189,11 +188,9 @@
  * Receives kernel klog notifications.
  *
- * @param callid IPC call ID
  * @param call   IPC call structure
  * @param arg    Local argument
  *
  */
-static void klog_notification_received(ipc_callid_t callid, ipc_call_t *call,
-    void *arg)
+static void klog_notification_received(ipc_call_t *call, void *arg)
 {
 	/*
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/loader/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -152,6 +152,7 @@
 	}
 
-	int file = vfs_receive_handle(true);
-	if (file < 0) {
+	int file;
+	rc = vfs_receive_handle(true, &file);
+	if (rc != EOK) {
 		async_answer_0(rid, EINVAL);
 		return;
@@ -254,6 +255,7 @@
 	}
 
-	int file = vfs_receive_handle(true);
-	if (file < 0) {
+	int file;
+	rc = vfs_receive_handle(true, &file);
+	if (rc != EOK) {
 		async_answer_0(rid, EINVAL);
 		return;
Index: uspace/srv/locsrv/locsrv.c
===================================================================
--- uspace/srv/locsrv/locsrv.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/locsrv/locsrv.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -47,4 +47,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <str_error.h>
 #include <ipc/loc.h>
 #include <assert.h>
@@ -1347,4 +1348,7 @@
 	categ_dir_add_cat(&cdir, cat);
 
+	cat = category_new("console");
+	categ_dir_add_cat(&cdir, cat);
+
 	cat = category_new("clock");
 	categ_dir_add_cat(&cdir, cat);
@@ -1526,11 +1530,15 @@
 	int rc = async_create_port(INTERFACE_LOC_SUPPLIER,
 	    loc_connection_supplier, NULL, &port);
-	if (rc != EOK)
+	if (rc != EOK) {
+		printf("%s: Error while creating supplier port: %s\n", NAME, str_error(rc));
 		return rc;
+	}
 	
 	rc = async_create_port(INTERFACE_LOC_CONSUMER,
 	    loc_connection_consumer, NULL, &port);
-	if (rc != EOK)
+	if (rc != EOK) {
+		printf("%s: Error while creating consumer port: %s\n", NAME, str_error(rc));
 		return rc;
+	}
 	
 	/* Set a handler of incomming connections */
@@ -1539,6 +1547,8 @@
 	/* Register location service at naming service */
 	rc = service_register(SERVICE_LOC);
-	if (rc != EOK)
+	if (rc != EOK) {
+		printf("%s: Error while registering service: %s\n", NAME, str_error(rc));
 		return rc;
+	}
 	
 	printf("%s: Accepting connections\n", NAME);
Index: uspace/srv/logger/ctl.c
===================================================================
--- uspace/srv/logger/ctl.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/logger/ctl.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -35,6 +35,6 @@
  */
 
-#include <malloc.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
 #include <io/logctl.h>
@@ -87,7 +87,11 @@
 		}
 		case LOGGER_CONTROL_SET_ROOT: {
-			int fd = vfs_receive_handle(true);
-			vfs_root_set(fd);
-			async_answer_0(callid, fd >= 0 ? EOK : fd);
+			int fd;
+			int rc = vfs_receive_handle(true, &fd);
+			if (rc == EOK) {
+				rc = vfs_root_set(fd);
+				vfs_put(fd);
+			}
+			async_answer_0(callid, rc);
 			break;
 		}
Index: uspace/srv/logger/logs.c
===================================================================
--- uspace/srv/logger/logs.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/logger/logs.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -31,8 +31,8 @@
  */
 #include <assert.h>
-#include <malloc.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <str.h>
-#include <stdio.h>
-#include <errno.h>
 #include "logger.h"
 
Index: uspace/srv/logger/main.c
===================================================================
--- uspace/srv/logger/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/logger/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -43,7 +43,7 @@
 #include <async.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
 #include <str_error.h>
-#include <malloc.h>
 #include "logger.h"
 
@@ -72,11 +72,15 @@
 	int rc = async_create_port(INTERFACE_LOGGER_CONTROL,
 	    connection_handler_control, NULL, &port);
-	if (rc != EOK)
+	if (rc != EOK) {
+		printf("%s: Error while creating control port: %s\n", NAME, str_error(rc));
 		return rc;
+	}
 	
 	rc = async_create_port(INTERFACE_LOGGER_WRITER,
 	    connection_handler_writer, NULL, &port);
-	if (rc != EOK)
+	if (rc != EOK) {
+		printf("%s: Error while creating writer port: %s\n", NAME, str_error(rc));
 		return rc;
+	}
 	
 	rc = service_register(SERVICE_LOGGER);
Index: uspace/srv/logger/writer.c
===================================================================
--- uspace/srv/logger/writer.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/logger/writer.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -43,8 +43,8 @@
 #include <ns.h>
 #include <async.h>
+#include <errno.h>
 #include <stdio.h>
-#include <errno.h>
+#include <stdlib.h>
 #include <str_error.h>
-#include <malloc.h>
 #include "logger.h"
 
@@ -80,5 +80,5 @@
 	}
 
-	KLOG_PRINTF(level, "[%s] %s: %s\n",
+	KLOG_PRINTF(level, "[%s] %s: %s",
 	    log->full_name, log_level_str(level),
 	    (const char *) message);
Index: uspace/srv/net/dhcp/dhcp.c
===================================================================
--- uspace/srv/net/dhcp/dhcp.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/dhcp/dhcp.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,4 +39,5 @@
 #include <byteorder.h>
 #include <errno.h>
+#include <str_error.h>
 #include <fibril_synch.h>
 #include <inet/addr.h>
@@ -370,5 +371,5 @@
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR,
-		    "Error creating IP address %s (%d)", "dhcp4a", rc);
+		    "Error creating IP address %s: %s", "dhcp4a", str_error(rc));
 		return rc;
 	}
@@ -380,5 +381,5 @@
 		if (rc != EOK) {
 			log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating "
-			    "default route %s (%d).", "dhcpdef", rc);
+			    "default route %s: %s.", "dhcpdef", str_error(rc));
 			return rc;
 		}
@@ -389,5 +390,5 @@
 		if (rc != EOK) {
 			log_msg(LOG_DEFAULT, LVL_ERROR, "Error setting "
-			    "nameserver address (%d))", rc);
+			    "nameserver address: %s)", str_error(rc));
 			return rc;
 		}
Index: uspace/srv/net/dhcp/main.c
===================================================================
--- uspace/srv/net/dhcp/main.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/dhcp/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,4 +36,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <io/log.h>
 #include <inet/inetcfg.h>
@@ -69,5 +70,5 @@
 	rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server: %s.", str_error(rc));
 		return EEXIST;
 	}
@@ -76,5 +77,5 @@
 	rc = loc_service_register(SERVICE_NAME_DHCP, &sid);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service: %s.", str_error(rc));
 		return EEXIST;
 	}
Index: uspace/srv/net/dnsrsrv/dnsrsrv.c
===================================================================
--- uspace/srv/net/dnsrsrv/dnsrsrv.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/dnsrsrv/dnsrsrv.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,4 +36,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <io/log.h>
 #include <ipc/dnsr.h>
@@ -68,5 +69,5 @@
 	rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server: %s.", str_error(rc));
 		transport_fini();
 		return EEXIST;
@@ -76,5 +77,5 @@
 	rc = loc_service_register(SERVICE_NAME_DNSR, &sid);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service: %s.", str_error(rc));
 		transport_fini();
 		return EEXIST;
Index: uspace/srv/net/dnsrsrv/transport.c
===================================================================
--- uspace/srv/net/dnsrsrv/transport.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/dnsrsrv/transport.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,4 +36,5 @@
 #include <adt/list.h>
 #include <errno.h>
+#include <str_error.h>
 #include <fibril_synch.h>
 #include <inet/addr.h>
@@ -199,5 +200,5 @@
 		    req_size);
 		if (rc != EOK) {
-			log_msg(LOG_DEFAULT, LVL_DEBUG, "Error %d sending message", rc);
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Error sending message: %s", str_error(rc));
 			goto error;
 		}
Index: uspace/srv/net/ethip/ethip_nic.c
===================================================================
--- uspace/srv/net/ethip/ethip_nic.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/ethip/ethip_nic.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -39,4 +39,5 @@
 #include <stdbool.h>
 #include <errno.h>
+#include <str_error.h>
 #include <fibril_synch.h>
 #include <inet/iplink_srv.h>
@@ -280,5 +281,5 @@
 	free(data);
 
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_received() done, rc=%d", rc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_received() done, rc=%s", str_error_name(rc));
 	async_answer_0(callid, rc);
 }
@@ -328,5 +329,5 @@
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback for NIC "
-		    "discovery (%d).", rc);
+		    "discovery: %s.", str_error(rc));
 		return rc;
 	}
@@ -357,5 +358,5 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_send(size=%zu)", size);
 	rc = nic_send_frame(nic->sess, data, size);
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "nic_send_frame -> %d", rc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "nic_send_frame -> %s", str_error_name(rc));
 	return rc;
 }
Index: uspace/srv/net/inetsrv/inet_link.c
===================================================================
--- uspace/srv/net/inetsrv/inet_link.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/inetsrv/inet_link.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,4 +37,5 @@
 #include <stdbool.h>
 #include <errno.h>
+#include <str_error.h>
 #include <fibril_synch.h>
 #include <inet/iplink.h>
@@ -114,5 +115,5 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet()");
 	rc = inet_recv_packet(&packet);
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet -> %d", rc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet -> %s", str_error_name(rc));
 	free(packet.data);
 
Index: uspace/srv/net/inetsrv/inetsrv.c
===================================================================
--- uspace/srv/net/inetsrv/inetsrv.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/inetsrv/inetsrv.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,4 +38,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <fibril_synch.h>
 #include <io/log.h>
@@ -105,5 +106,5 @@
 	rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server: %s.", str_error(rc));
 		return EEXIST;
 	}
@@ -112,5 +113,5 @@
 	rc = loc_service_register(SERVICE_NAME_INET, &sid);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service: %s.", str_error(rc));
 		return EEXIST;
 	}
Index: uspace/srv/net/inetsrv/ndp.c
===================================================================
--- uspace/srv/net/inetsrv/ndp.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/inetsrv/ndp.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,5 +37,5 @@
 #include <errno.h>
 #include <mem.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <io/log.h>
 #include "ntrans.h"
Index: uspace/srv/net/loopip/loopip.c
===================================================================
--- uspace/srv/net/loopip/loopip.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/loopip/loopip.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,4 +38,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <inet/iplink_srv.h>
 #include <inet/addr.h>
@@ -251,11 +252,13 @@
 	int rc = log_init(NAME);
 	if (rc != EOK) {
-		printf("%s: Failed to initialize logging.\n", NAME);
+		printf("%s: Failed to initialize logging: %s.\n", NAME, str_error(rc));
 		return rc;
 	}
 	
 	rc = loopip_init();
-	if (rc != EOK)
-		return rc;
+	if (rc != EOK) {
+		printf("%s: Failed to initialize loopip: %s.\n", NAME, str_error(rc));
+		return rc;
+	}
 	
 	printf("%s: Accepting connections.\n", NAME);
Index: uspace/srv/net/nconfsrv/iplink.c
===================================================================
--- uspace/srv/net/nconfsrv/iplink.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/nconfsrv/iplink.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,4 +37,5 @@
 #include <stdbool.h>
 #include <errno.h>
+#include <str_error.h>
 #include <fibril_synch.h>
 #include <inet/dhcp.h>
@@ -181,5 +182,5 @@
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback for IP link "
-		    "discovery (%d).", rc);
+		    "discovery: %s.", str_error(rc));
 		return rc;
 	}
Index: uspace/srv/net/nconfsrv/nconfsrv.c
===================================================================
--- uspace/srv/net/nconfsrv/nconfsrv.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/nconfsrv/nconfsrv.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,4 +38,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <fibril_synch.h>
 #include <inet/dhcp.h>
@@ -80,5 +81,5 @@
 	rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server: %s.", str_error(rc));
 		return EEXIST;
 	}
@@ -86,5 +87,5 @@
 	rc = loc_service_register(SERVICE_NAME_NETCONF, &sid);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service: %s.", str_error(rc));
 		return EEXIST;
 	}
Index: uspace/srv/net/slip/slip.c
===================================================================
--- uspace/srv/net/slip/slip.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/slip/slip.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,10 +37,12 @@
 #include <stdio.h>
 #include <stdint.h>
+#include <stdlib.h>
 #include <loc.h>
 #include <inet/addr.h>
 #include <inet/iplink_srv.h>
-#include <char_dev_iface.h>
+#include <io/chardev.h>
 #include <io/log.h>
 #include <errno.h>
+#include <str_error.h>
 #include <task.h>
 
@@ -96,29 +98,29 @@
 }
 
-static void write_flush(async_sess_t *sess)
+static void write_flush(chardev_t *chardev)
 {
 	size_t written = 0;
 
 	while (slip_send_pending > 0) {
-		ssize_t size;
-
-		size = char_dev_write(sess, &slip_send_buf[written],
-		    slip_send_pending);
-		if (size < 0) {
+		int rc;
+		size_t nwr;
+
+		rc = chardev_write(chardev, &slip_send_buf[written],
+		    slip_send_pending, &nwr);
+		if (rc != EOK) {
 			log_msg(LOG_DEFAULT, LVL_ERROR,
-			    "char_dev_write() returned %d",
-			    (int) size);
+			    "chardev_write() -> %s", str_error_name(rc));
 			slip_send_pending = 0;
 			break;
 		}
-		written += size;
-		slip_send_pending -= size;
-	}
-}
-
-static void write_buffered(async_sess_t *sess, uint8_t ch)
+		written += nwr;
+		slip_send_pending -= nwr;
+	}
+}
+
+static void write_buffered(chardev_t *chardev, uint8_t ch)
 {
 	if (slip_send_pending == sizeof(slip_send_buf))
-		write_flush(sess);
+		write_flush(chardev);
 	slip_send_buf[slip_send_pending++] = ch;
 }
@@ -128,5 +130,5 @@
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "slip_send()");
 	
-	async_sess_t *sess = (async_sess_t *) srv->arg;
+	chardev_t *chardev = (chardev_t *) srv->arg;
 	uint8_t *data = sdu->data;
 	
@@ -136,24 +138,24 @@
 	 * measure for dealing with previous possible noise on the line.
 	 */
-	write_buffered(sess, SLIP_END);
+	write_buffered(chardev, SLIP_END);
 	
 	for (size_t i = 0; i < sdu->size; i++) {
 		switch (data[i]) {
 		case SLIP_END:
-			write_buffered(sess, SLIP_ESC);
-			write_buffered(sess, SLIP_ESC_END);
+			write_buffered(chardev, SLIP_ESC);
+			write_buffered(chardev, SLIP_ESC_END);
 			break;
 		case SLIP_ESC:
-			write_buffered(sess, SLIP_ESC);
-			write_buffered(sess, SLIP_ESC_ESC);
+			write_buffered(chardev, SLIP_ESC);
+			write_buffered(chardev, SLIP_ESC_ESC);
 			break;
 		default:
-			write_buffered(sess, data[i]);
+			write_buffered(chardev, data[i]);
 			break;
 		}
 	}
 	
-	write_buffered(sess, SLIP_END);
-	write_flush(sess);
+	write_buffered(chardev, SLIP_END);
+	write_flush(chardev);
 	
 	return EOK;
@@ -203,17 +205,21 @@
 }
 
-static uint8_t read_buffered(async_sess_t *sess)
+static uint8_t read_buffered(chardev_t *chardev)
 {
 	while (slip_recv_pending == 0) {
-		ssize_t size;
-
-		size = char_dev_read(sess, slip_recv_buf,
-		    sizeof(slip_recv_buf));
-		if (size < 0) {
+		int rc;
+		size_t nread;
+
+		rc = chardev_read(chardev, slip_recv_buf,
+		    sizeof(slip_recv_buf), &nread);
+		if (rc != EOK) {
 			log_msg(LOG_DEFAULT, LVL_ERROR,
-			    "char_dev_read() returned %d", (int) size);
+			    "char_dev_read() -> %s", str_error_name(rc));
+		}
+
+		if (nread == 0)
 			return SLIP_END;
-		}
-		slip_recv_pending = size;
+
+		slip_recv_pending = nread;
 		slip_recv_read = 0;
 	}
@@ -224,5 +230,5 @@
 static int slip_recv_fibril(void *arg)
 {
-	async_sess_t *sess = (async_sess_t *) arg;
+	chardev_t *chardev = (chardev_t *) arg;
 	static uint8_t recv_final[SLIP_MTU];
 	iplink_recv_sdu_t sdu;
@@ -234,5 +240,5 @@
 	while (true) {
 		for (sdu.size = 0; sdu.size < sizeof(recv_final); /**/) {
-			ch = read_buffered(sess);
+			ch = read_buffered(chardev);
 			switch (ch) {
 			case SLIP_END:
@@ -246,9 +252,9 @@
 
 			case SLIP_ESC:
-				ch = read_buffered(sess);
+				ch = read_buffered(chardev);
 				if (ch == SLIP_ESC_END) {
 					recv_final[sdu.size++] = SLIP_END;
 					break;
-				} else if (ch ==  SLIP_ESC_ESC) {
+				} else if (ch == SLIP_ESC_ESC) {
 					recv_final[sdu.size++] = SLIP_ESC;
 					break;
@@ -281,5 +287,5 @@
 		if (rc != EOK) {
 			log_msg(LOG_DEFAULT, LVL_ERROR,
-			    "iplink_ev_recv() returned %d", rc);
+			    "iplink_ev_recv() -> %s", str_error_name(rc));
 		}
 	}
@@ -295,4 +301,6 @@
 	async_sess_t *sess_in = NULL;
 	async_sess_t *sess_out = NULL;
+	chardev_t *chardev_in = NULL;
+	chardev_t *chardev_out = NULL;
 	fid_t fid;
 	int rc;
@@ -336,5 +344,13 @@
 		return ENOENT;
 	}
-	slip_iplink.arg = sess_out;
+
+	rc = chardev_open(sess_out, &chardev_out);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR,
+		    "Failed opening character device.");
+		return ENOENT;
+	}
+
+	slip_iplink.arg = chardev_out;
 
 	sess_in = loc_service_connect(svcid, INTERFACE_DDF, 0);
@@ -347,4 +363,11 @@
 	}
 
+	rc = chardev_open(sess_in, &chardev_in);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR,
+		    "Failed opening character device.");
+		return ENOENT;
+	}
+
 	rc = loc_service_register(linkstr, &linksid);
 	if (rc != EOK) {
@@ -363,5 +386,5 @@
 	}
 
-	fid = fibril_create(slip_recv_fibril, sess_in);
+	fid = fibril_create(slip_recv_fibril, chardev_in);
 	if (!fid) {
 		log_msg(LOG_DEFAULT, LVL_ERROR,
@@ -375,6 +398,8 @@
 
 fail:
+	chardev_close(chardev_out);
 	if (sess_out)
 		async_hangup(sess_out);
+	chardev_close(chardev_in);
 	if (sess_in)
 		async_hangup(sess_in);
Index: uspace/srv/net/tcp/service.c
===================================================================
--- uspace/srv/net/tcp/service.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/tcp/service.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,4 +37,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <inet/endpoint.h>
 #include <inet/inet.h>
@@ -1095,5 +1096,5 @@
 	rc = tcp_conn_recv_impl(client, conn_id, data, size, &rsize);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv - recv_impl failed rc=%d", rc);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv - recv_impl failed rc=%s", str_error_name(rc));
 		async_answer_0(callid, rc);
 		async_answer_0(iid, rc);
Index: uspace/srv/net/udp/service.c
===================================================================
--- uspace/srv/net/udp/service.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/net/udp/service.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -570,5 +570,5 @@
 
 	rc = async_data_read_finalize(callid, &enext->epp.remote,
-	    max(size, (ssize_t)sizeof(inet_ep_t)));
+	    max(size, (size_t)sizeof(inet_ep_t)));
 	if (rc != EOK) {
 		async_answer_0(iid, rc);
@@ -596,9 +596,9 @@
 {
 	ipc_callid_t callid;
-	ssize_t msg_size;
+	size_t msg_size;
 	udp_crcv_queue_entry_t *enext;
 	void *data;
 	size_t size;
-	ssize_t off;
+	size_t off;
 	int rc;
 
@@ -623,6 +623,11 @@
 	msg_size = enext->msg->data_size;
 
-	rc = async_data_read_finalize(callid, data, max(msg_size - off,
-	    (ssize_t)size));
+	if (off > msg_size) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	rc = async_data_read_finalize(callid, data, min(msg_size - off, size));
 	if (rc != EOK) {
 		async_answer_0(iid, rc);
Index: uspace/srv/ns/clonable.c
===================================================================
--- uspace/srv/ns/clonable.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/ns/clonable.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -38,5 +38,5 @@
 #include <assert.h>
 #include <stdio.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <loader/loader.h>
 #include "clonable.h"
Index: uspace/srv/ns/service.c
===================================================================
--- uspace/srv/ns/service.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/ns/service.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,5 +36,5 @@
 #include <errno.h>
 #include <stdio.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include "service.h"
 #include "ns.h"
Index: uspace/srv/ns/task.c
===================================================================
--- uspace/srv/ns/task.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/ns/task.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,7 +37,7 @@
 #include <errno.h>
 #include <assert.h>
+#include <macros.h>
 #include <stdio.h>
-#include <macros.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <types/task.h>
 #include "task.h"
Index: uspace/srv/taskmon/taskmon.c
===================================================================
--- uspace/srv/taskmon/taskmon.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/taskmon/taskmon.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -51,5 +51,5 @@
 static void corecfg_client_conn(ipc_callid_t , ipc_call_t *, void *);
 
-static void fault_event(ipc_callid_t callid, ipc_call_t *call, void *arg)
+static void fault_event(ipc_call_t *call, void *arg)
 {
 	const char *fname;
@@ -150,6 +150,6 @@
 	int rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		printf("%s: Failed registering server (%d).\n",
-		    NAME, rc);
+		printf("%s: Failed registering server: %s.\n",
+		    NAME, str_error(rc));
 		return -1;
 	}
@@ -158,6 +158,6 @@
 	rc = loc_service_register(SERVICE_NAME_CORECFG, &sid);
 	if (rc != EOK) {
-		printf("%s: Failed registering service (%d).\n",
-		    NAME, rc);
+		printf("%s: Failed registering service: %s.\n",
+		    NAME, str_error(rc));
 		return -1;
 	}
Index: uspace/srv/test/chardev-test/Makefile
===================================================================
--- uspace/srv/test/chardev-test/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/srv/test/chardev-test/Makefile	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2017 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 = chardev-test
+
+SOURCES = \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/test/chardev-test/main.c
===================================================================
--- uspace/srv/test/chardev-test/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
+++ uspace/srv/test/chardev-test/main.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2017 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <str_error.h>
+#include <io/chardev_srv.h>
+#include <ipc/services.h>
+#include <loc.h>
+#include <mem.h>
+#include <stdio.h>
+#include <task.h>
+
+#define NAME  "chardev-test"
+
+static int smallx_open(chardev_srvs_t *, chardev_srv_t *);
+static int smallx_close(chardev_srv_t *);
+static int smallx_write(chardev_srv_t *, const void *, size_t, size_t *);
+static int smallx_read(chardev_srv_t *, void *, size_t, size_t *);
+
+static int largex_open(chardev_srvs_t *, chardev_srv_t *);
+static int largex_close(chardev_srv_t *);
+static int largex_write(chardev_srv_t *, const void *, size_t, size_t *);
+static int largex_read(chardev_srv_t *, void *, size_t, size_t *);
+
+static int partialx_open(chardev_srvs_t *, chardev_srv_t *);
+static int partialx_close(chardev_srv_t *);
+static int partialx_write(chardev_srv_t *, const void *, size_t, size_t *);
+static int partialx_read(chardev_srv_t *, void *, size_t, size_t *);
+
+static service_id_t smallx_svc_id;
+static chardev_srvs_t smallx_srvs;
+
+static service_id_t largex_svc_id;
+static chardev_srvs_t largex_srvs;
+
+static service_id_t partialx_svc_id;
+static chardev_srvs_t partialx_srvs;
+
+static chardev_ops_t chardev_test_smallx_ops = {
+	.open = smallx_open,
+	.close = smallx_close,
+	.write = smallx_write,
+	.read = smallx_read
+};
+
+static chardev_ops_t chardev_test_largex_ops = {
+	.open = largex_open,
+	.close = largex_close,
+	.write = largex_write,
+	.read = largex_read
+};
+
+static chardev_ops_t chardev_test_partialx_ops = {
+	.open = partialx_open,
+	.close = partialx_close,
+	.write = partialx_write,
+	.read = partialx_read
+};
+
+static void chardev_test_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	chardev_srvs_t *svc;
+	sysarg_t svcid;
+
+	svcid = IPC_GET_ARG2(*icall);
+	if (svcid == smallx_svc_id) {
+		svc = &smallx_srvs;
+	} else if (svcid == largex_svc_id) {
+		svc = &largex_srvs;
+	} else if (svcid == partialx_svc_id) {
+		svc = &partialx_srvs;
+	} else {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	chardev_conn(iid, icall, svc);
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+
+	printf("%s: Character device test service\n", NAME);
+	async_set_fallback_port_handler(chardev_test_connection, NULL);
+
+	rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		printf("%s: Failed registering server.: %s\n", NAME, str_error(rc));
+		return rc;
+	}
+
+	chardev_srvs_init(&smallx_srvs);
+	smallx_srvs.ops = &chardev_test_smallx_ops;
+	smallx_srvs.sarg = NULL;
+
+	chardev_srvs_init(&largex_srvs);
+	largex_srvs.ops = &chardev_test_largex_ops;
+	largex_srvs.sarg = NULL;
+
+	chardev_srvs_init(&partialx_srvs);
+	partialx_srvs.ops = &chardev_test_partialx_ops;
+	partialx_srvs.sarg = NULL;
+
+	rc = loc_service_register(SERVICE_NAME_CHARDEV_TEST_SMALLX, &smallx_svc_id);
+	if (rc != EOK) {
+		printf("%s: Failed registering service.: %s\n", NAME, str_error(rc));
+		return rc;
+	}
+
+	rc = loc_service_register(SERVICE_NAME_CHARDEV_TEST_LARGEX, &largex_svc_id);
+	if (rc != EOK) {
+		printf("%s: Failed registering service.: %s\n", NAME, str_error(rc));
+		return rc;
+	}
+
+	rc = loc_service_register(SERVICE_NAME_CHARDEV_TEST_PARTIALX, &partialx_svc_id);
+	if (rc != EOK) {
+		printf("%s: Failed registering service.: %s\n", NAME, str_error(rc));
+		return rc;
+	}
+
+
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+static int smallx_open(chardev_srvs_t *srvs, chardev_srv_t *srv)
+{
+	return EOK;
+}
+
+static int smallx_close(chardev_srv_t *srv)
+{
+	return EOK;
+}
+
+static int smallx_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwritten)
+{
+	if (size < 1) {
+		*nwritten = 0;
+		return EOK;
+	}
+
+	*nwritten = 1;
+	return EOK;
+}
+
+static int smallx_read(chardev_srv_t *srv, void *buf, size_t size,
+    size_t *nread)
+{
+	if (size < 1) {
+		*nread = 0;
+		return EOK;
+	}
+
+	memset(buf, 0, 1);
+	*nread = 1;
+	return EOK;
+}
+
+static int largex_open(chardev_srvs_t *srvs, chardev_srv_t *srv)
+{
+	return EOK;
+}
+
+static int largex_close(chardev_srv_t *srv)
+{
+	return EOK;
+}
+
+static int largex_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwritten)
+{
+	if (size < 1) {
+		*nwritten = 0;
+		return EOK;
+	}
+
+	*nwritten = size;
+	return EOK;
+}
+
+static int largex_read(chardev_srv_t *srv, void *buf, size_t size,
+    size_t *nread)
+{
+	if (size < 1) {
+		*nread = 0;
+		return EOK;
+	}
+
+	memset(buf, 0, size);
+	*nread = size;
+	return EOK;
+}
+
+static int partialx_open(chardev_srvs_t *srvs, chardev_srv_t *srv)
+{
+	return EOK;
+}
+
+static int partialx_close(chardev_srv_t *srv)
+{
+	return EOK;
+}
+
+static int partialx_write(chardev_srv_t *srv, const void *data, size_t size,
+    size_t *nwritten)
+{
+	if (size < 1) {
+		*nwritten = 0;
+		return EOK;
+	}
+
+	*nwritten = 1;
+	return EIO;
+}
+
+static int partialx_read(chardev_srv_t *srv, void *buf, size_t size,
+    size_t *nread)
+{
+	if (size < 1) {
+		*nread = 0;
+		return EOK;
+	}
+
+	memset(buf, 0, 1);
+	*nread = 1;
+	return EIO;
+}
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/vfs/vfs.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -44,4 +44,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <stdio.h>
 #include <stdbool.h>
@@ -76,5 +77,5 @@
 }
 
-static void notification_handler(ipc_callid_t callid, ipc_call_t *call, void *arg)
+static void notification_handler(ipc_call_t *call, void *arg)
 {
 	if (IPC_GET_ARG1(*call) == VFS_PASS_HANDLE)
@@ -122,7 +123,9 @@
 	port_id_t port;
 	rc = async_create_port(INTERFACE_PAGER, vfs_pager, NULL, &port);
-	if (rc != EOK)
+	if (rc != EOK) {
+		printf("%s: Cannot create pager port: %s\n", NAME, str_error(rc));
 		return rc;
-		
+	}
+
 	/*
 	 * Set a connection handling function/fibril.
@@ -141,5 +144,5 @@
 	rc = service_register(SERVICE_VFS);
 	if (rc != EOK) {
-		printf("%s: Cannot register VFS service\n", NAME);
+		printf("%s: Cannot register VFS service: %s\n", NAME, str_error(rc));
 		return rc;
 	}
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/vfs/vfs.h	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -194,10 +194,10 @@
 
 extern void vfs_op_pass_handle(task_id_t, task_id_t, int);
-extern int vfs_wait_handle_internal(bool);
+extern int vfs_wait_handle_internal(bool, int *);
 
 extern vfs_file_t *vfs_file_get(int);
 extern void vfs_file_put(vfs_file_t *);
 extern int vfs_fd_assign(vfs_file_t *, int);
-extern int vfs_fd_alloc(vfs_file_t **file, bool desc);
+extern int vfs_fd_alloc(vfs_file_t **file, bool desc, int *);
 extern int vfs_fd_free(int);
 
@@ -206,5 +206,5 @@
 extern int vfs_open_node_remote(vfs_node_t *);
 
-extern int vfs_op_clone(int oldfd, int newfd, bool desc);
+extern int vfs_op_clone(int oldfd, int newfd, bool desc, int *);
 extern int vfs_op_fsprobe(const char *, service_id_t, vfs_fs_probe_info_t *);
 extern int vfs_op_mount(int mpfd, unsigned servid, unsigned flags, unsigned instance, const char *opts, const char *fsname, int *outfd);
@@ -220,5 +220,5 @@
 extern int vfs_op_unlink(int parentfd, int expectfd, char *path);
 extern int vfs_op_unmount(int mpfd);
-extern int vfs_op_wait_handle(bool high_fd);
+extern int vfs_op_wait_handle(bool high_fd, int *out_fd);
 extern int vfs_op_walk(int parentfd, int flags, char *path, int *out_fd);
 extern int vfs_op_write(int fd, aoff64_t, size_t *out_bytes);
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/vfs/vfs_file.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -192,5 +192,5 @@
 }
 
-static int _vfs_fd_alloc(vfs_client_data_t *vfs_data, vfs_file_t **file, bool desc)
+static int _vfs_fd_alloc(vfs_client_data_t *vfs_data, vfs_file_t **file, bool desc, int *out_fd)
 {
 	if (!vfs_files_init(vfs_data))
@@ -223,5 +223,6 @@
 			
 			fibril_mutex_unlock(&vfs_data->lock);
-			return (int) i;
+			*out_fd = (int) i;
+			return EOK;
 		}
 		
@@ -249,10 +250,22 @@
  *             in a descending order.
  *
- * @return First available file descriptor or a negative error
- *         code.
- */
-int vfs_fd_alloc(vfs_file_t **file, bool desc)
-{
-	return _vfs_fd_alloc(VFS_DATA, file, desc);
+ * @param[out] out_fd  First available file descriptor
+ *
+ * @return Error code.
+ */
+int vfs_fd_alloc(vfs_file_t **file, bool desc, int *out_fd)
+{
+	return _vfs_fd_alloc(VFS_DATA, file, desc, out_fd);
+}
+
+static int _vfs_fd_free_locked(vfs_client_data_t *vfs_data, int fd)
+{
+	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || !vfs_data->files[fd]) {
+		return EBADF;
+	}
+
+	int rc = vfs_file_delref(vfs_data, vfs_data->files[fd]);
+	vfs_data->files[fd] = NULL;
+	return rc;
 }
 
@@ -265,11 +278,5 @@
 
 	fibril_mutex_lock(&vfs_data->lock);	
-	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || !vfs_data->files[fd]) {
-		fibril_mutex_unlock(&vfs_data->lock);
-		return EBADF;
-	}
-	
-	rc = vfs_file_delref(vfs_data, vfs_data->files[fd]);
-	vfs_data->files[fd] = NULL;
+	rc = _vfs_fd_free_locked(vfs_data, fd);
 	fibril_mutex_unlock(&vfs_data->lock);
 	
@@ -308,8 +315,8 @@
 		return EBADF;
 	}
-	if (FILES[fd] != NULL) {
-		fibril_mutex_unlock(&VFS_DATA->lock);
-		return EEXIST;
-	}
+
+	/* Make sure fd is closed. */
+	(void) _vfs_fd_free_locked(VFS_DATA, fd);
+	assert(FILES[fd] == NULL);
 	
 	FILES[fd] = file;
@@ -422,5 +429,5 @@
 }
 
-int vfs_wait_handle_internal(bool high_fd)
+int vfs_wait_handle_internal(bool high_fd, int *out_fd)
 {
 	vfs_client_data_t *vfs_data = VFS_DATA;	
@@ -436,9 +443,9 @@
 
 	vfs_file_t *file;
-	int fd = _vfs_fd_alloc(vfs_data, &file, high_fd);
-	if (fd < 0) {
+	int rc = _vfs_fd_alloc(vfs_data, &file, high_fd, out_fd);
+	if (rc != EOK) {
 		vfs_node_delref(bh->node);
 		free(bh);
-		return fd;
+		return rc;
 	}
 	
@@ -447,5 +454,5 @@
 	vfs_file_put(file);
 	free(bh);
-	return fd;
+	return EOK;
 }
 
Index: uspace/srv/vfs/vfs_ipc.c
===================================================================
--- uspace/srv/vfs/vfs_ipc.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/vfs/vfs_ipc.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -41,6 +41,7 @@
 	bool desc = IPC_GET_ARG3(*request);
 	
-	int ret = vfs_op_clone(oldfd, newfd, desc);
-	async_answer_0(rid, ret);
+	int outfd = -1;
+	int rc = vfs_op_clone(oldfd, newfd, desc, &outfd);
+	async_answer_1(rid, rc, outfd);
 }
 
@@ -279,6 +280,7 @@
 {
 	bool high_fd = IPC_GET_ARG1(*request);
-	int fd = vfs_op_wait_handle(high_fd);
-	async_answer_1(rid, EOK, fd);
+	int fd = -1;
+	int rc = vfs_op_wait_handle(high_fd, &fd);
+	async_answer_1(rid, rc, fd);
 }
 
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/vfs/vfs_lookup.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -222,6 +222,6 @@
 	vfs_exchange_release(exch);
 	
-	if ((int) rc < 0)
-		return (int) rc;
+	if (rc != EOK)
+		return rc;
 	
 	unsigned last = *pfirst + *plen;
@@ -229,6 +229,6 @@
 	*plen = last - *pfirst;
 	
-	result->triplet.fs_handle = (fs_handle_t) rc;
-	result->triplet.service_id = (service_id_t) IPC_GET_ARG1(answer);
+	result->triplet.fs_handle = (fs_handle_t) IPC_GET_ARG1(answer);
+	result->triplet.service_id = base->service_id;
 	result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer);
 	result->size = MERGE_LOUP32(IPC_GET_ARG4(answer), IPC_GET_ARG5(answer));
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/vfs/vfs_ops.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -86,5 +86,5 @@
 }
 
-int vfs_op_clone(int oldfd, int newfd, bool desc)
+int vfs_op_clone(int oldfd, int newfd, bool desc, int *out_fd)
 {
 	int rc;
@@ -102,12 +102,11 @@
 
 	if (newfd != -1) {
-		/* Make sure newfd is closed. */
-		(void) vfs_fd_free(newfd);
 		/* Assign the old file to newfd. */
 		rc = vfs_fd_assign(oldfile, newfd);
+		*out_fd = newfd;
 	} else {
 		vfs_file_t *newfile;
-		int newfd = vfs_fd_alloc(&newfile, desc);
-		if (newfd >= 0) {
+		rc = vfs_fd_alloc(&newfile, desc, out_fd);
+		if (rc == EOK) {
 			newfile->node = oldfile->node;
 			newfile->permissions = oldfile->permissions;
@@ -116,5 +115,4 @@
 			vfs_file_put(newfile);
 		}
-		rc = newfd;
 	}
 	vfs_file_put(oldfile);
@@ -225,10 +223,10 @@
 
 int vfs_op_mount(int mpfd, unsigned service_id, unsigned flags,
-    unsigned instance, const char *opts, const char *fs_name, int *outfd)
+    unsigned instance, const char *opts, const char *fs_name, int *out_fd)
 {
 	int rc;
 	vfs_file_t *mp = NULL;
 	vfs_file_t *file = NULL;
-	int fd = -1;
+	*out_fd = -1;
 	
 	if (!(flags & VFS_MOUNT_CONNECT_ONLY)) {
@@ -256,7 +254,6 @@
 	
 	if (!(flags & VFS_MOUNT_NO_REF)) {
-		fd = vfs_fd_alloc(&file, false);
-		if (fd < 0) {
-			rc = fd;
+		rc = vfs_fd_alloc(&file, false, out_fd);
+		if (rc != EOK) {
 			goto out;
 		}
@@ -297,10 +294,9 @@
 		vfs_file_put(file);
 
-	if (rc != EOK && fd >= 0) {
-		vfs_fd_free(fd);
-		fd = 0;
-	}
-	
-	*outfd = fd;
+	if (rc != EOK && *out_fd >= 0) {
+		vfs_fd_free(*out_fd);
+		*out_fd = -1;
+	}
+	
 	return rc;
 }
@@ -830,7 +826,7 @@
 }
 
-int vfs_op_wait_handle(bool high_fd)
-{
-	return vfs_wait_handle_internal(high_fd);
+int vfs_op_wait_handle(bool high_fd, int *out_fd)
+{
+	return vfs_wait_handle_internal(high_fd, out_fd);
 }
 
@@ -894,9 +890,9 @@
 	
 	vfs_file_t *file;
-	int fd = vfs_fd_alloc(&file, false);
-	if (fd < 0) {
+	rc = vfs_fd_alloc(&file, false, out_fd);
+	if (rc != EOK) {
 		vfs_node_put(node);
 		vfs_file_put(parent);
-		return fd;
+		return rc;
 	}
 	assert(file != NULL);
@@ -912,5 +908,4 @@
 	fibril_rwlock_read_unlock(&namespace_rwlock);
 
-	*out_fd = fd;
 	return EOK;
 }
Index: uspace/srv/volsrv/part.c
===================================================================
--- uspace/srv/volsrv/part.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/volsrv/part.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -37,4 +37,5 @@
 #include <stdbool.h>
 #include <errno.h>
+#include <str_error.h>
 #include <fibril_synch.h>
 #include <io/log.h>
@@ -271,5 +272,5 @@
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback "
-		    "for partition discovery (%d).", rc);
+		    "for partition discovery: %s.", str_error(rc));
 		return rc;
 	}
@@ -328,6 +329,6 @@
 	rc = volsrv_part_empty(part->svc_id);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part() - failed %d",
-		    rc);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part() - failed %s",
+		    str_error(rc));
 		return rc;
 	}
@@ -348,6 +349,6 @@
 	rc = volsrv_part_mkfs(part->svc_id, fstype, label);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part() - failed %d",
-		    rc);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part() - failed %s",
+		    str_error(rc));
 		fibril_mutex_unlock(&vol_parts_lock);
 		return rc;
Index: uspace/srv/volsrv/volsrv.c
===================================================================
--- uspace/srv/volsrv/volsrv.c	(revision 7f4937e65b167991b71e24b530864b61b7145134)
+++ uspace/srv/volsrv/volsrv.c	(revision 5340bfa17a8a9bf4c691594ca361efe8f52c7a43)
@@ -36,4 +36,5 @@
 #include <async.h>
 #include <errno.h>
+#include <str_error.h>
 #include <io/log.h>
 #include <ipc/services.h>
@@ -70,5 +71,5 @@
 	rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server: %s.", str_error(rc));
 		return EEXIST;
 	}
@@ -77,5 +78,5 @@
 	rc = loc_service_register(SERVICE_NAME_VOLSRV, &sid);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service: %s.", str_error(rc));
 		return EEXIST;
 	}
